无效的强制转换异常泛型

Phi*_*hil 13 c#

我遇到了这个问题,我正在使用反射从类中提取属性,但问题是反射将它们作为对象返回,我无法将其转换为实际类型.

例如,如果这是班级:

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; }
}
Run Code Online (Sandbox Code Playgroud)

从一个铸造说Row<bool>Row<object>作品:

    var a = new Row<bool>
    {
        Name = "Foo",
        Value = true
    };

    var b = (Row<object>)a; // Works
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试从它objectRow<object>它似乎忽略我的显式运算符并抛出System.InvalidCastException:

var c = (object) a; // Simulate getting from reflection

var d = (Row<object>) c; // System.InvalidCastException
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

Mar*_*zek 6

使用dynamic而不是object强制运行时实际类型检查:

var c = (dynamic)a;
var d = (Row<object>)c; // Works fine
Run Code Online (Sandbox Code Playgroud)

它将调用您的Row<T> -> Row<object>演员.

  • 我正在对这个答案提出正式投诉,因为它的作用是*让问题消失*.它并不试图解释出现了什么问题,了解OP正在尝试完成什么或建议更好的做事方式. (5认同)

Jon*_*Jon 4

这里的问题是,除非在您尝试转换的值的静态类型上定义了转换运算符,否则转换不会查找转换运算符。在您的示例中,静态类型cisobject并且object既不派生自也不具有转换运算符 to Row<object>,从而导致运行时异常。

看起来这个问题可以通过更好的设计轻松回避。

您希望将任何类型Row<T>视为 a Row<object>,而转换运算符只不过是解决这些类型在层次上不相关的事实。那么为什么不把它们联系起来并从一开始就避免这个问题呢?

例如:

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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

这似乎做你想做的:

  • 转换问题得到了解决,因为您现在可以将任何类型转换Row<T>为基类(它接管了初始设计中Row的职责)并且可以轻松访问,无论该类型是什么类型。Row<object>NameValueValue
  • setterRow.Value受到保护,因此您无法从外部投射 aRow<int>RowmakeValue例如 a string,从而保持类型安全。