コードの前にquestionを記入してください:
_IEnumerable<T>
_を期待する拡張メソッドのレシーバーとして_where T : ITest
_ _this IEnumerable<ITest>
_が受け入れられないのはなぜですか?
そしてcode:
私は3つのタイプがあります:
_public interface ITest { }
public class Element : ITest { }
public class ElementInfo : ITest { }
_
そして2つの拡張メソッド:
_public static class Extensions
{
public static IEnumerable<ElementInfo> Method<T>(
this IEnumerable<T> collection)
where T : ITest
{
→ return collection.ToInfoObjects();
}
public static IEnumerable<ElementInfo> ToInfoObjects(
this IEnumerable<ITest> collection)
{
return collection.Select(item => new ElementInfo());
}
}
_
(マークされた行で)発生するコンパイラエラー:
_
CS1929
_:_'IEnumerable<T>'
_には_'ToInfoObjects'
_の定義が含まれておらず、最適な拡張メソッドオーバーロード'Extensions.ToInfoObjects(IEnumerable<ITest>)'
にはタイプ_'IEnumerable<ITest>'
_のレシーバーが必要です
これはなぜですか? ToInfoObjects
拡張メソッドのレシーバーは_IEnumerable<T>
_であり、ジェネリック型制約により、T
はITest
を実装する必要があります。
なぜレシーバーは受け入れられないのですか?私の推測では、_IEnumerable<T>
_の共分散ですが、よくわかりません。
ToInfoObjects
を変更して_IEnumerable<T> where T : ITest
_を受け取るようにすると、すべて問題ありません。
このことを考慮:
public struct ValueElement : ITest { }
この:
IEnumerable<ValueElement> collection = ...
collection.Method(); //OK, ValueElement implement ITest, as required.
collection.ToInfoObjects() //Error, IEnumerable<ValueElement> is not IEnumerable<ITest>
//variance does not work with value types.
そのため、Method
に許可されているすべての型がToInfoObjects
にも許可されているわけではありません。 class
制約をT
のMethod
に追加すると、コードがコンパイルされます。