static IEnumerable<U> DoSomething<T, U>(IEnumerable<T> a)
where T : U
{
// Works, compiler can compile-time statically cast
// T as U.
T testA = default(T);
U testB = testA;
// And the following works, though:
IEnumerable<string> test2A = null;
IEnumerable<object> test2B = test2A;
// Doesn’t work. Compiler cannot compile-time statically
// cast IEnumerable<T> to IEnumerable<U> even though it is
// out and T is U.
return a;
}
我有代码可以执行这种类型的隐式转换,这将节省我编写很多样板接口实现代码。
这似乎是协方差应该有助于的那种事情。
但我总是在上面的return a;
行上收到此错误:
错误CS0266:无法隐式转换类型&#39; System.Collections.Generic.IEnumerable&lt; T&gt;&#39;到&#39; System.Collections.Generic.IEnumerable&lt; U&gt;&#39;。存在显式转换(您是否错过了演员?)
为什么会这样,有没有办法解决这个问题而不做return from o in a select o;
之类的事情?
答案 0 :(得分:6)
当弄乱我的最小版本并阅读类似但无关的问题about interface casting时,我意识到以下编译:
static IEnumerable<U> DoSomethingElse<T, U>(IEnumerable<T> a)
where T : class, U
{
// Works! Ridik!
return a;
}
此外,以下内容失败并显示相同的错误消息:
static void Blah()
{
// Fails for I bet the same reason that DoSomething{T, U} fails:
IEnumerable<int> a = null;
IEnumerable<object> b = a;
}
错误CS0266:无法隐式转换类型&#39; System.Collections.Generic.IEnumerable&lt; int&gt;&#39;到&#39; System.Collections.Generic.IEnumerable&lt; object&gt;&#39;。存在显式转换(您是否错过了演员?)
所以这似乎与.net如何将某些类型的赋值限制为引用类型有关,因为在这些情况下装箱会是错误的(例如,您可能会假设引用类型并且实际上正在处理值的副本在运行时很难/不可能实现(给定一个IEnumerable<int>
你必须实现一个包装适应类。好的,听起来好像.net不能/不应该尝试做为你在运行时)。我认为它是一种情况,其中.net允许指针式多态,就其本质而言,它与值类型的概念不兼容。
因此,对于我的情况,我不需要在我的API中支持值类型,并添加class
约束使一切变得神奇!