Я знаю, IEnumerable<String>
должен конвертироваться в IEnumerable<Object>
, но IList<String>
не может конвертироваться в IEnumerable<String>
?
IList<String>
может конвертироваться в IEnumerable<String>
.Проблема в том, что вы пытаетесь конвертировать Person<List<String>>
в Person<IEnumerable<String>>
, что недопустимо.Например, совершенно правильно написать:
var x = new Person<IEnumerable<String>>();
x.Value = new string[0];
, поскольку значение имеет тип IEnumerable<String>
, а строковый массив - IEnumerable<String>
.Однако вы не можете написать:
var x = new Person<List<String>>();
x.Value = new string[0];
, поскольку значение имеет тип List<String>
.Поскольку вы не можете использовать Person<List<String>>
во всех местах, где вы могли бы использовать Person<IEnumerable<String>>
, это не законный бросок.
Обратите внимание, что вы можете сделать что-то похожее на то, что вам нужно, если вы добавите параметр второго типа в свой метод расширения:
public static void Process<TResult, TList>(this Person<TList> p)
where TList : IEnumerable<TResult>
{
Console.WriteLine(p.Value.Any());
}
К сожалению, компилятор не сможет вывести обавведите параметры, так что вам придется называть его так:
var x = new Person<List<String>>();
x.Process<String, List<String>>();
Если вы используете C # 4.0 и можете использовать ковариацию, то вы можете определить ковариантный интерфейс для персоны:
public interface IPerson<out T>
{
T Value { get; }
}
public class Person<T>
: IPerson<T>
{
public T Value { get; set; }
}
А затем напишите свой метод расширения следующим образом:
public static void Process<TResult>(this IPerson<IEnumerable<TResult>> p)
{
// Do something with .Any().
Console.WriteLine(p.Value.Any());
}
Поскольку IPerson<T>.Value
только для чтения, IPerson<List<String>>
может использоваться везде, где может быть IPerson<IEnumerable<String>>
,и преобразование действительно.