読者です 読者をやめる 読者になる 読者になる

実装すべきインターフェイスの一意性

.NET

C# 2.0/3.0 で,以下のコードは,エラーである.

interface I<T> {}
class G<T1, T2> : I<T1>, I<T2> {}  // CS0695
error CS0695:
'G<T1, T2>' cannot implement both 'I<T1>' and 'I<T2>' because they may unify for some type parameter substitutions

CS0695 をエラーとする動機は,『C# Language Specification Version 3.0』の §13.4.2 "Uniqueness of implemented interfaces" に書かれている.一言でいえば,T1 == T2 のときに生じる曖昧性を排除するためである.
同セクションに書かれているのは動機だけではない.エラーの検出ルールおよび回避策についても書かれている.例えば,以下のような書き換えが可能だと紹介されている.

interface I<T> {}
class Base<T1> : Base<T1> {}
class Derived<T1,T2>: Base<T1>, I<T2> {} // OK

ところで,どうしても最初の構造を使いたい,という人がいた.T1 != T2 が確実ならこの構造は許可されるべきと考えた彼は,以下のコードを示し,「このコードでは必ず A != B なのだから,CS0695 は発生すべきではない」と主張した.

public class X<A, B> : IEnumerable<A>, IEnumerable<B>
where B : C<A>
{
}

一見もっともらしい.しかし,彼の主張にとってこのコードは不適切だ.実はこの制約では A != B が保証されない.という指摘が検証コメントでなされている.
私はよく検討する前に検証コメントを読んでしまった.そこには確かに反例として A == B となるケースが書かれている.自分で考えてみたいという人のために,その例の引用はしない.答えが知りたくなったら,以下の検証コメントを読むと良い.