I have the following class and extension class (for this example):
public class Person<T>
{
public T Value { get; set; }
}
public static class PersonExt
{
public static void Process<TResult>(this Person<IEnumerable<TResult>> p)
{
// Do something with .Any().
Console.WriteLine(p.Value.Any());
}
}
I was expecting I could write something like the following and it would work, but it doesn’t:
var x = new Person<List<String>>();
x.Process();
Since List is lower in the inheritance tree than IEnumerable, shouldn’t this be valid? It works if I new up a Person<IEnumerable<String>> of course because that’s the direct type.
I’m trying to use an extension method that can be applied to all Person<T>‘s as long as T implements IEnumerable<Something> because I need to use the .Any() method.
EDIT: Maybe my understanding of covariance is off? I know IEnumerable<String> should convert to IEnumerable<Object>, but couldn’t IList<String> convert to IEnumerable<String>?
EDIT2: Forgot to mention that I am using .net 4.0.
IList<String>can convert toIEnumerable<String>. The problem is that you’re trying to convertPerson<List<String>>toPerson<IEnumerable<String>>, which is illegal. For example, it’s perfectly valid to write:since Value is of type
IEnumerable<String>and a string array is anIEnumerable<String>. However, you cannot write:since Value is of type
List<String>. Since you can’t use aPerson<List<String>>in all places where you could use aPerson<IEnumerable<String>>, it’s not a legal cast.Note that you can do something similar to what you want if you add a second type parameter to your extension method:
Unfortunately, the compiler won’t be able to infer both type parameters, so you would have to call it like this:
If you are using C# 4.0 and can use covariance, then you can define a covariant interface for person:
And then write your extension method as:
Since
IPerson<T>.Valueis read-only, aIPerson<List<String>>can be used everywhere that anIPerson<IEnumerable<String>>can be, and the conversion is valid.