使用转换操作符投射对象失败

使用转换操作符投射对象失败

问题描述:

所以我有这个对象,比如说DoubleContainer。使用转换操作符投射对象失败

public struct DoubleContainer 
{ 
    private readonly double _value; 

    private DoubleContainer(double value) 
    { 
     _value = value; 
    } 

    public static implicit operator double(DoubleContainer doubleContainer) 
    { 
     return doubleContainer._value; 
    } 

    public static DoubleContainer Create(double value) 
    { 
     return new DoubleContainer(value); 
    } 
} 

在几乎所有情况下都可以按预期工作,除非它作为对象传递给函数。

下面的代码生成一个InvalidCastException如果我通过在DoubleContainer:

public double GetDouble(Object input) 
{ 
    return (double)input; 
} 

我可以得到,如果我不使用动态它的工作:

public double GetDouble(Object input) 
{ 
    return (double)(dynamic)input; 
} 

我的问题,这个解决方案是, Visual Studio会将(动态)变成灰色,因为它应该是多余的,所以有人可能会删除它。此外,我不知道在代码库中是否还有其他可能会出现相同问题的地方。

有什么我可以做我的实现DoubleContainer什么会让我第一次执行GetDouble()的工作?我尝试添加另一个从Object到DoubleContainer的隐式转换运算符,但“不允许用户定义到基类或从基类转换”......

+0

工作,为什么你想包一个'double'成一个类只是把它转换为'对象'?如果这仅仅是一个例子,并且你有一个更复杂的类并且有效的转换为'double',那么为什么将它转换为'object'。基本上你应该看看你的设计,如果你有这些类型的铸造问题。 – juharr

+0

我同意我们在这方面的代码设计是有问题的。不幸的是,在这个版本中重新设计是不可能的。我只是想找到一个修复程序,希望有点强大,而不是超级黑客。 – Ash

+0

@Ash该类本身是超级hacky – Franck

你不能使它工作,因为你只能拆箱盒装结构(这就是你在做什么(double) input)到确切的undelying类型,这是由Eric Lippert在article中最好的描述。所以,无论何时你做(double) someObject - 只有当对象实际上是double而不是int,而不是float,而不是DoubleContainer。如果您期望其他类型 - 您可以更好地使用Convert.ToDouble。对于与您的类型工作,你需要它来实现IConvertible

public struct DoubleContainer : IConvertible 
{ 
    private readonly double _value; 

    private DoubleContainer(double value) 
    { 
     _value = value; 
    } 

    public static implicit operator double(DoubleContainer doubleContainer) 
    { 
     return doubleContainer._value; 
    } 

    public static DoubleContainer Create(double value) 
    { 
     return new DoubleContainer(value); 
    } 

    public double ToDouble(IFormatProvider provider) { 
     return _value; 
    } 

    public bool ToBoolean(IFormatProvider provider) { 
     // delegate to your double 
     return ((IConvertible) _value).ToBoolean(provider); 
    } 

    // ... rest is skipped ... 

然后,它会与

public double GetDouble(Object input) 
{ 
    return Convert.ToDouble(input); 
} 
+1

你链接的那篇文章解释得非常好。 – Ash

+0

@Ash:很高兴听到它!这是关于剧组的一个非常常见的问题。 –

当将对象转换为double时,编译器不知道它应该调用你现有的operator double,所以它不会将任何调用插入到你的用户定义的操作符double中。

当你在中间插入dynamic,编译器将产生类似“如果这个参考具有操作双,叫it`,所以它的工作原理。

因此,它实际上无法工作,只要你施放System.Object一个双,而代码由@juharr建议,稍加修改,将工作:

public double GetDouble(Object input) 
{ 
    if (input is DoubleContainer) 
    { 
     var dc = (DoubleContainer)input; 
     return (double)dc; 
    } 
    return (double)input; 
} 

编辑:修改后的代码按@SergiyKlimkov评论

+0

DoubleContainer是一个结构体。所以“输入为DoubleContainer”将不会编译。它需要替换为“(DoubleContainer)输入”。 –