2016-07-25 5 views
4

制約(クラスまたはジェネリックメソッド)がメソッド自体にどのように影響するかを理解しようとしています。たとえば、このコードを取る:オーバーライドされたジェネリックメソッドの制約

class Base<T> where T:class, IComparable<T> 
{ 
    public virtual void Method(T obj) { } 
} 

class Derived<T> : Base<T> where T:class, IComparable<T>, IEnumerable<T> 
{ 
    public override void Method(T obj) { } 
} 

このコードは、罰金コンパイルとコンパイラ/ランタイムがジェネリック型であるパラメータを取る非ジェネリックメソッド「メソッド」に多型の呼び出しを解決することができます。基本クラスと派生クラスでは、型パラメーターの制約が異なります。

また、値型のインスタンス化ごとに異なるクラスが生成され、参照型に対してそのようなクラスが1つだけインスタンス化されるため、おそらく問題の可能性がある値型を保持するようにクラス制約を指定しました。

一方、次のコードはコンパイルされません。

class Base 
{ 
    public virtual void Method<T>() where T : class, IComparable<T> { } 
} 

class Derived : Base 
{ 
    public override void Method<T>() where T : class, IComparable<T>, IEnumerable<T> { } 
} 

のC#の言語仕様では、それがオーバーライドするメソッドにあり、のような制約を指定することは違法であることと、一般的な方法に制約が引き継がれていることを述べています。私はGoogleでそれを検索していましたが、多態呼び出しのサポートに関連する複雑さ(メソッドテーブルの維持などに関して)が禁止されていることがわかりました。しかし、私はまだそれが一般的なクラスであることを除いて、上記のケース1でこれが似ている理由を理解していません。ケース2はコンパイラエラーとしてフラグが立てられていますが、コンパイラ/ランタイムはケース1でどのように実行できますか?

+0

ケース1基本クラスがあり、両方とも汎用性があります –

+0

@EhsanSajjad - so?最初のケースでは、それは汎用クラスであり、後者ではそれがメソッドです。インスタンス化を1つだけに制限する 'クラス制約'を指定していませんか?だから、もう一方はうまくいくのに対して、なぜ許可されないのですか? – Madhusudhan

答えて

3

「なぜ、仮想オーバーライドのジェネリックメソッドに制約を追加するのは不正ですか?」という質問を考えてみましょう。それは本当に簡単なので。

class Foo : IComparable<Foo> { ... } 
... 
Base b = new Derived(); 
b.Method<Foo>(); 

まず、これは違法であるべきですか?はい。 b.Method<Foo>を呼び出すと実際にDerived.Method<Foo>が呼び出されますが、Fooはその制約を満たしていません。だからこれは違法でなければならない。

エラーの報告先はどのコードですか? Fooの宣言は合法です。 DerivedからBaseへの変換は合法です。コンパイラの観点からは、b.Method<Foo>の呼び出しは合法です。 bBaseであり、FooBase.Methodの制約を満たしています。したがって、これらの行のいずれにもエラーを報告することはできません。エラーを報告する唯一の場所は、問題の原因となるwhere句を持つBase.Methodの行にあります。したがって、そのような種類のwhere句は、誰も上記のように他の法的プログラムの断片を書くことを防ぐために、違法でなければなりません。

ここで、クラスが一般的な最初のケースはどうですか?さて、このシナリオではどのようにBase<Foo>を取得しますか?確かに、Derived<Foo>のインスタンスからではありません。なぜなら、最初にそのタイプを作ることさえできないからです!同等の問題プログラムは次のとおりです。

Base<Foo> b = new Derived<Foo>(); 
b.Method(); 

ここで、エラーはどこで報告されるべきですか?明らかに、それはDerived<Foo>を作成する行に報告することができます!したがって、追加のwhere句を不正にする必要はありません。

4

ケース1では、Tがクラスによって決定されたときに、T型の任意のオブジェクトに対してこのメ​​ソッドを使用できます。特定のクラスについては、タイプTは1つしかないので、オーバーライドは簡単です。より多くのタイプのTを使用してBase <T>を生成するよりも、Derived <T>を生成するよりも、問題はありません。

ケース2の場合、メソッドは任意の数の型に対して呼び出すことができます。ただし、Derivedクラスで使用できる型は、Baseクラスで許可されている型のサブセットのみです。つまり、部分的なオーバーライドがあることを意味します。

関連する問題