如何从对象引用执行转换

时间:2011-04-01 15:38:52

标签: c#

class Mock
{
    public static explicit operator String(Mock s)
    {
        return "ok";
    }
}

static T GetValue<T>(object o)
{
    return (T)o;
}

Mock m = new Mock();
var v1 = (string) m;
var v2 = GetValue<string>(m);   // InvalidCastException is thrown.
                                // How to modify GetValue method
                                // internally, without changing its
                                // signature, for this casting to work ?

此致

3 个答案:

答案 0 :(得分:2)

两个选项:

  • 使用反射查找转化并调用它
  • 如果您使用的是C#4
  • ,请使用动态类型

使用反射可能会很痛苦。如果你可以逃脱它,那么动态方法就更简单了:

public static T GetValue<T>(dynamic d)
{
    return (T) d;
}

这不是对签名的特别重大改变,但如果你想保持完全相同,你可以使用:

public static T GetValue<T>(object o)
{
    dynamic d = o;
    return (T) d;
}

答案 1 :(得分:1)

直接强制转换成功且GetValue方法失败的原因是因为直接强制转换方法在Mock<T>类型上使用explicitcast运算符。此显式转换运算符在通用版本中不可用,因为C#编译器只看到T,因此不绑定到隐式转换运算符,而是选择执行CLR转换。

最简单的方法是添加一个接口来表示此转换,然后约束T来实现接口

interface IConvertToString {
  string Convert();
}

public class Mock : IConvertToString {
  public string Convert() {
    return "ok";
  }
}

public static T GetValue<T>(T o) where T : IConvertToString {
  return o.ConvertToString();
}

答案 2 :(得分:0)

这个怎么样:var v2 = GetValue<string>((string)m);

这不会修改GetValue方法,而是强制转换发送到其中的参数。你保留了你的签名。演员看起来有点多余,但你必须指定GetValue的类型......