Reputation: 9562
Complete question before code:
Why is IEnumerable<T>
where T : ITest
not accepted as receiver of an extension method that expects this IEnumerable<ITest>
?
And now the code:
I have three types:
public interface ITest { }
public class Element : ITest { }
public class ElementInfo : ITest { }
And two extension methods:
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());
}
}
The compiler error I get (on the marked line):
CS1929
:'IEnumerable<T>'
does not contain a definition for'ToInfoObjects'
and the best extension method overload'Extensions.ToInfoObjects(IEnumerable<ITest>)'
requires a receiver of type'IEnumerable<ITest>'
Why is this so? The receiver of the ToInfoObjects
extension method is an IEnumerable<T>
and by the generic type constraint, T
must implement ITest
.
Why is then the receiver not accepted? My guess is the covariance of the IEnumerable<T>
but I am not sure.
If I change ToInfoObjects
to receive IEnumerable<T> where T : ITest
, then everything is ok.
Upvotes: 18
Views: 15642
Reputation: 22102
Consider this:
public struct ValueElement : ITest { }
and this:
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.
So that not every type allowed for Method
also allowed for ToInfoObjects
. If you add class
constraint to T
in Method
, then your code will compile.
Upvotes: 14
Reputation: 600
You can do the following:
public static IEnumerable<ElementInfo> Method<T>(
this IEnumerable<T> collection)
where T : ITest
{
return collection.ToInfoObjects();
}
public static IEnumerable<ElementInfo> ToInfoObjects<T>(
this IEnumerable<T> collection)
{
return collection.Select(item => new ElementInfo());
}
Notice on ToInfoObjects.
Upvotes: -1