使用转换操作符投射对象失败
所以我有这个对象,比如说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的隐式转换运算符,但“不允许用户定义到基类或从基类转换”......
你不能使它工作,因为你只能拆箱盒装结构(这就是你在做什么(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);
}
你链接的那篇文章解释得非常好。 – Ash
@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评论
DoubleContainer是一个结构体。所以“输入为DoubleContainer”将不会编译。它需要替换为“(DoubleContainer)输入”。 –
工作,为什么你想包一个'double'成一个类只是把它转换为'对象'?如果这仅仅是一个例子,并且你有一个更复杂的类并且有效的转换为'double',那么为什么将它转换为'object'。基本上你应该看看你的设计,如果你有这些类型的铸造问题。 – juharr
我同意我们在这方面的代码设计是有问题的。不幸的是,在这个版本中重新设计是不可能的。我只是想找到一个修复程序,希望有点强大,而不是超级黑客。 – Ash
@Ash该类本身是超级hacky – Franck