We are currently working with generics on extensions for enumerable-derived classes. Apparently, the compiler produces an error CS0411 with extension methods if they are called on a class derived from IEnumerable<T>
and return values that are of the enclosed T
type.
The following example reproduces the error:
public class Item { }
public class CollectionType : IEnumerable<Item>
{
public IEnumerator<Item> GetEnumerator()
{
throw new NotImplementedException();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
public static class CollectionExtension
{
public static T[] DoSomething<T, TCollection>(this TCollection source)
where TCollection : IEnumerable<T>
{
throw new NotImplementedException();
}
}
public class Test
{
public void TestMethod()
{
var collection = new CollectionType();
collection.DoSomething();
collection.DoSomething<Item, CollectionType>(); // This works fine
}
}
Calling DoSomething()
will produce the following error:
The type arguments for method 'T[] [...].CollectionExtension.DoSomething<T,TCollection>(this TCollection)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
How can this happen if TCollection
is bound to be of type IEnumerable<T>
and T
is also defined as a generic type parameter of DoSomething()
?
Calling the extension method on the CollectionType
should provide DoSomething()
with both generic types.
It would not be possible to use the DoSomething()
method as-is without specifying the generic types explicitly. The class IEnumerable<T>
from which it seemingly would be possible to infer the type of T
is located in the type constraint declaration, unfortunately C# "...cannot infer the type parameters only from a constraint or return value" . See the details here:
[https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generic-methods]
This is issue can be solved in a different ways, you could explicitly specify the type as you have done in the example code - collection.DoSomething<Item, CollectionType>()
, or add to DoSomething()
an argument of type T
, in that case C# will be able to infer the type, or get rid of the generic type TCollection, replacing it with IEnumerable<T>
in the following way:
public static T[] DoSomething<T>(this IEnumerable<T> source)
{
throw new NotImplementedException();
}
The last one I think would be a cleaner way.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.