[英]Cast MyClass<string> to MyClass<object> fails in runtime
In developing a class that should handle various generic lambda expressions, I fell into a rather familiar hole: I had a MyClass<T>
class, and I tried to cast MyClass<string>
to MyClass<object>
, like so: 在开发应该处理各种通用lambda表达式的类时,我陷入了一个相当熟悉的漏洞:我拥有
MyClass<T>
类,并且试图将MyClass<string>
MyClass<object>
为MyClass<object>
,如下所示:
MyClass<string> myClassString = GetMyClass(); // Returns MyClass<String>
MyClass<object> myClassObject = myClassString;
Doing so returned an compilation error saying there there's no implicit conversion between the two types, but that an explicit conversion does exist. 这样做会返回一个编译错误,指出这两种类型之间没有隐式转换,但确实存在显式转换。 So I added the explicit conversion:
因此,我添加了显式转换:
MyClass<object> myClassObject = (MyClass<object>)myClassString;
Now the code compiled, but failed in runtime, claiming the conversion is illegal. 现在,代码已编译,但在运行时失败,声称转换是非法的。
I am using Visual Studio 2012, and the code is part of a Portable Class Library project compiled with C# 5. 我正在使用Visual Studio 2012,并且代码是使用C#5编译的可移植类库项目的一部分。
Just to make sure, I replaced MyClass
IList
- the same behavior appeared - an explicit conversion is allowed, but fails during run-time. 为了确保,我替换了
MyClass
IList
出现了相同的行为-允许显式转换,但在运行时失败。
Why? 为什么? Why does the compiler accept this?
编译器为什么接受这个? What's the point of the explicit conversion if it fails in runtime?
如果显式转换在运行时失败,那有什么意义呢?
In order to allow the cast, you need to mark it as covariant. 为了允许强制转换,您需要将其标记为协变。 However, covariance is only allowed for interfaces (and delegates).
但是,协方差仅适用于接口(和委托)。 This would look like:
看起来像:
interface MyInterface<out T> ...
The reason why you can compile the explicit cast is probably that the compiler assumes that the return value of GetMyClass()
could be a MyClass<object>
. 之所以可以编译显式
GetMyClass()
,可能是因为编译器假定GetMyClass()
的返回值可以是MyClass<object>
。 But That's hard to say without the declaration. 但是,如果没有声明,这很难说。
To be able to cast MyClass<string>
to MyClass<object>
you need to fulfill the following: 为了能够将
MyClass<string>
MyClass<object>
为MyClass<object>
您需要满足以下条件:
MyClass<T>
must be an interface, eg IMyClass<T>
. MyClass<T>
必须是接口,例如IMyClass<T>
。 out
keyword to the type parameter T
, making the type parameter covariant . out
关键字添加到类型参数T
,以使类型参数为协变 。 T
may only appear in output positions of the members of the interface. T
只能出现在接口成员的输出位置。 For example: 例如:
public interface IMyClass<out T>
{
T GetItem(); // T in an output position
}
Now you can cast it: 现在您可以投射它:
IMyClass<string> myClassString;
IMyClass<object> myClassObject = (IMyClass<object>)myClassString;
If you have classes A and B and you want to cast B to A then one of the following must be true: 如果您具有A和B类,并且要将B强制转换为A,则以下条件之一必须为真:
None of the above is true in your case so the cast is invalid. 以上情况都不符合您的情况,因此强制转换无效。
If your class implements IEnumerable you may use an extension method 如果您的类实现IEnumerable,则可以使用扩展方法
using System.Linq
...
MyClass<Object> asObject = GetMyClass().Cast<Object>();
Otherwise, write an explicit operator or function that does the conversion: 否则,编写执行转换的显式运算符或函数:
public MyClass<Base> ConvertToBase<Base, Derived>(MyClass<Derived>) where Derived : Base
{
// construct and return the appropriate object
}
use Conversion operator to implement casting of your class to another classes 使用Conversion运算符将您的课程转换为其他课程
http://msdn.microsoft.com/en-us/library/85w54y0a.aspx http://msdn.microsoft.com/zh-CN/library/85w54y0a.aspx
http://msdn.microsoft.com/en-us/library/09479473(v=vs.80).aspx http://msdn.microsoft.com/zh-CN/library/09479473(v=vs.80).aspx
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.