[英]Invalid cast exception generics
I'm having this issue, I'm using reflection to pull properties from a class but the problem is reflection returns them as an object and I can't get it into my actual type. 我遇到了这个问题,我正在使用反射从类中提取属性,但问题是反射将它们作为对象返回,我无法将其转换为实际类型。
Take for example, if this is the class: 例如,如果这是班级:
public class Row<T>
{
public static explicit operator Row<object>(Row<T> o)
{
return new Row<object>
{
Name = o.Name,
Value = o.Value
};
}
public string Name { get; set; }
public T Value { get; set; }
}
Casting from one say Row<bool>
to Row<object>
works: 从一个人说出Row<bool>
到Row<object>
工作原理:
var a = new Row<bool>
{
Name = "Foo",
Value = true
};
var b = (Row<object>)a; // Works
But when I try to go from object
to Row<object>
it seems to ignore my explicit operator and throw a System.InvalidCastException: 但是当我尝试从object
转到Row<object>
,似乎忽略了我的显式运算符并抛出了System.InvalidCastException:
var c = (object) a; // Simulate getting from reflection
var d = (Row<object>) c; // System.InvalidCastException
What am I missing? 我错过了什么?
Use dynamic
instead of object
to force runtime real type check: 使用dynamic
而不是object
来强制运行时实际类型检查:
var c = (dynamic)a;
var d = (Row<object>)c; // Works fine
It will call your Row<T> -> Row<object>
cast operator. 它将调用Row<T> -> Row<object>
强制转换运算符。
The problem here is that casting does not look for a conversion operator unless one is defined on the static type of the value you are trying to cast. 这里的问题是,除非在您尝试强制转换的值的静态类型上定义转换运算符,否则转换不会查找转换运算符。 In your example the static type of c
is object
and object
neither derives from nor has a conversion operator to Row<object>
, resulting in the runtime exception. 在您的示例中, c
的静态类型是object
而object
既不是从Row<object>
派生也没有转换运算符,从而导致运行时异常。
It looks like this problem can be easily sidestepped with a better design. 看起来这个问题可以通过更好的设计轻松回避。
You want to treat any type of Row<T>
as a Row<object>
and the conversion operator does nothing more than work around the fact that these types are not hierarchically related. 您希望将任何类型的Row<T>
视为Row<object>
,并且转换运算符只会解决这些类型与层次结构无关的事实。 So why not make them related and avoid the problem in the first place? 那么为什么不让它们相关并首先避免这个问题呢?
For example: 例如:
public abstract class Row
{
public string Name { get; set; }
public object Value { get; protected set; }
}
public class Row<T> : Row
{
public new T Value
{
get { return (T)base.Value; }
set { base.Value = value; }
}
}
This seems to do what you want: 这似乎做你想要的:
Row<T>
to the base class Row
(which takes over the responsibilities of Row<object>
in your initial design) and easily access Name
and Value
no matter what type the Value
is. 铸造问题就解决了,因为你现在可以将任何类型的Row<T>
基类Row
(其接管的职责Row<object>
在初始设计),并方便地访问Name
和Value
,不管是什么类型的Value
是。 Row.Value
setter is protected so you cannot cast a Row<int>
to Row
and make Value
eg a string
from outside, maintaining type safety. Row.Value
setter受到保护,因此您无法将Row<int>
Row.Value
为Row
并从外部生成Value
例如string
,从而保持类型安全。 You can accomplish this with reflection: 你可以用反射完成这个:
public class RowHelper
{
public static Row<object> LoadRow(object o)
{
var type = o.GetType();
return new Row<object>
{
Name = (string)type.InvokeMember("Name", BindingFlags.GetProperty, null, o, null),
Value = type.InvokeMember("Value", BindingFlags.GetProperty, null, o, null)
};
}
}
You would call this with: 您可以这样称呼:
var d = RowHelper.LoadRow(c);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.