Cad*_*oux 2 c# .net-4.0 covariance
我在这些行上遇到编译器错误:
RenderLookup(Cars);
RenderLookup(Employees);
Error 2 Argument 1: cannot convert from 'Demo.MyList<Demo.Car>' to 'System.Collections.Generic.IEnumerable<Demo.KeyedBase>' Program.cs 85 26 Demo
Error 4 Argument 1: cannot convert from 'Demo.MyList<Demo.Employee>' to 'System.Collections.Generic.IEnumerable<Demo.KeyedBase>' Program.cs 86 26 Demo
Run Code Online (Sandbox Code Playgroud)
这是怎么回事?我以为.NET 4.0会处理这个?我错过了什么?
using System;
using System.Collections.Generic;
namespace Demo
{
public interface KeyedBase
{
int Key { get; }
string Description { get; }
}
public class MyList<T> : Dictionary<int, T> where T : KeyedBase
{
public void Add(T itm)
{
Add(itm.Key, itm);
}
}
public class Car : KeyedBase
{
private readonly int _ID;
private readonly string _Description;
public Car(int ID, string Description)
{
_ID = ID;
_Description = Description;
}
public int Key
{
get { return _ID; }
}
public string Description
{
get { return _Description; }
}
}
public class Employee : KeyedBase
{
private readonly int _ID;
private readonly string _FirstName;
private readonly string _LastName;
public Employee(int ID, string FirstName, string LastName)
{
_ID = ID;
_FirstName = FirstName;
_LastName = LastName;
}
public int Key
{
get { return _ID; }
}
public string Description
{
get { return _LastName + ", " + _FirstName; }
}
}
class Program
{
private static void RenderLookup(IEnumerable<KeyedBase> Lookup)
{
Console.WriteLine("Choose:");
foreach (var itm in Lookup)
{
Console.WriteLine("{0} : {1}", itm.Key, itm.Description);
}
}
static void Main(string[] args)
{
var Cars = new MyList<Car> { new Car(1, "Subaru"), new Car(2, "Volswagen") };
var Employees = new MyList<Employee>
{
new Employee(1, "Mickey", "Mouse"),
new Employee(2, "Minnie", "Mouse")
};
RenderLookup(Cars);
RenderLookup(Employees);
}
}
}
Run Code Online (Sandbox Code Playgroud)
你正试图将Dictionary<int, T>衍生的课程投入IEnumerable<T>.你必须将它投射到IEnumerable<KeyValuePair<int, T>>或通过Values你的词典集合.
RenderLookup(Cars.Values);
RenderLookup(Employees.Values);
Run Code Online (Sandbox Code Playgroud)
这不是协方差的问题,而是与类型兼容性有关.
首先,共同/逆转支持是选择加入.您需要添加限定符out或in泛型类型参数才能使其工作(在接口上,而不是类).所以你必须要:
interface IMyList<(in/out) T> : ...
Run Code Online (Sandbox Code Playgroud)
其次,你不能在你的例子中这样做,因为你的参数T既有共变量又有逆变量.为简化起见,仅由类返回的类型参数可以是covariant(aka out),并且仅由类接受的类型参数是逆变(aka in).你的班级都接受并返回T.
最后,你的真正问题Dictionary<K,V>不是IEnumerable<V>,但是IEnumerable<KeyValuePair<K,V>>.您需要在MyList上覆盖GetEnumerator方法,如下所示:
public class MyList<T> : Dictionary<int, T>, IEnumerable<T> where T : KeyedBase
{
public void Add(T itm)
{
Add(itm.Key, itm);
}
public virtual IEnumerator<T> GetEnumerator()
{
return Values.GetEnumerator();
}
}
Run Code Online (Sandbox Code Playgroud)
那么你的例子就可以了.
| 归档时间: |
|
| 查看次数: |
699 次 |
| 最近记录: |