本文介绍了施放IList< string>到IList< object>运行时失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有以下的简短C#程序:
IList< string> listString = new List< String>();
IList< object>的ListObject;
listObject = listString;
这个程序不能编译。最后一行会导致以下编译错误:
lockquote
不能将类型'System.Collections.Generic.IList'隐式转换为'System.Collections。 Generic.IList。
存在明确的转换(您是否缺少演员?)
所以,我添加了演员: p>
listObject =(IList< object>)listString;
现在程序编译正确,但在运行时失败。一个 InvalidCastException 会引发以下消息:
这两种转换都是非法的,应该被编译器捕获,或者它是合法的,不应该在运行时抛出异常。为什么不一致的行为?
澄清:我不问为什么演员失败。我明白为什么这样的铸造是有问题的。我问为什么演员只在运行时失败。
如你所知, IList< string> 到 IList< object> code> IList< T> 接口在 T 中是 not 协变的。如果使用.NET 4.5,您使用了 IReadOnlyList< out T> ,它就会起作用。
为什么显式投射
listObject =(IList< object>)listString;
会 编译, code> IList< string> 和 IList< object> 以任何方式相关。这两种类型都不能分配给其他类型。原因是变量的运行时类型( listString )可能是一个实现了两个接口的类(或结构体)!假设我创建了这个类:
class CrazyList:IList< string>,IList< object> //不是很聪明
{
//很多显式接口实现在这里
}
然后,如果某些 IList< string> 在运行时碰巧是 CrazyList cast 会成功。当你写一个明确的转换时,你告诉编译器我知道类型将被转换成我正在投入的这种类型。由于编译器无法证明你错了,当然它相信你。
I have the following short C# program:
IList<string> listString = new List<String>();
IList<object> listObject;
listObject = listString;
This program doesn't compile. The last line causes the following compilation error:
So, I've added the cast:
listObject = (IList<object>)listString;
Now the program compiles properly, but fails at runtime. An InvalidCastException is raised with the following message:
Either the cast is illegal and should be caught by the compiler, or it is legal and shouldn't throw an exception at runtime. Why the inconsistent behavior?
CLARIFICATION: I am not asking why the cast fails. I understand why such casting is problematic. I am asking why the cast fails only at runtime.
解决方案
The reason why the implicit cast from IList<string> to IList<object> won't compile is, as you seem to know, that the IList<T> interface is not covariant in T. If, with .NET 4.5, you used IReadOnlyList<out T> instead, it would work.
The reason why the explicit cast
listObject = (IList<object>)listString;
will compile, is not that IList<string> and IList<object> are related in any way. Neither type is assignable to the other. The reason is that the runtime type of your variable (listString) might be a class (or struct) which implemented both interfaces! Suppose I made this class:
class CrazyList : IList<string>, IList<object> // not very smart
{
// a lot of explicit interface implementations here
}
Then if some IList<string> happened to be a CrazyList at runtime, the explicit cast would succeed. When you write an explicit cast, you're telling the compiler "I know the type is going to be convertible to this type I'm casting into". Since the compiler can't prove you're wrong, of course it believes you.
这篇关于施放IList< string>到IList< object>运行时失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!