Ранее я спрашивал об этом как о «двойной ковариации» и понял, что у меня все с ног на голову
У меня есть интерфейс
public interface INodeProvider
{
void LoadNodes(INode parent, Action<IEnumerable<INode>> action);
}
У меня есть класс, полученный из INode, называемый DeviceNode
У меня есть класс, который реализует интерфейс
public override void LoadNodes(INode parent, Action<IEnumerable<INode>> action)
{
List<DeviceNode> devices = new List<DeviceNode>();
foreach (var dev in list)
{
devices.Add(new DeviceNode(this, dev));
}
action(devices);
}
Это не компилируется.Но это делает
List<INode> devices = new List<INode>();
Это также компилируется, если я
action(devices.Cast<INode>());
И возвращаюсь к моей первоначальной декларации
Это удивило меня.Может быть, мне нужно больше читать.
Но у меня есть еще один вопрос.Вызываемый делегат (действие) действительно должен знать тип объекта в IEnumerable.т.е. я хочу сделать
Type[] typeParameters = l.GetType().GetGenericArguments();
в методе действия.Я предполагаю, что это даст мне фактический тип, используемый для создания экземпляра IEnumerable.За исключением его всегда INode, учитывая, что я могу получить для компиляции.Я был удивлен, что тот, в котором Cast <> () по-прежнему говорил INode, учитывая, что базовый тип - List {DeviceNode} (я думаю, это означает, что .Cast фактически копирует)
Примечание - я знаю, что могосмотрите объекты в коллекции, чтобы определить их тип, но это не то, что я хочу сделать
РЕДАКТИРОВАТЬ: это похоже на разницу между Silverlight 4 и «нормальным» .net 4. Если я беру один и тот же коди вставьте его в проект .net 4, он прекрасно компилируется