所以我有这个对象,比如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);
}
}
在几乎所有情况下,它都可以按预期运行,除非它作为Object传递给函数。
如果我传入DoubleContainer,则以下代码生成InvalidCastException:
public double GetDouble(Object input)
{
return (double)input;
}
如果我使用动态,我可以让它工作:
public double GetDouble(Object input)
{
return (double)(dynamic)input;
}
我对这个解决方案的问题是Visual Studio灰色(动态),因为它应该是多余的,所以有人可能会删除它。此外,我不知道代码库中是否还有其他地方可能会出现同样的问题。
我对DoubleContainer的实现有什么办法可以让我第一次实现GetDouble()工作吗?我尝试将另一个隐式转换运算符从Object添加到DoubleContainer,但是“不允许用户定义到基类的转换”....
答案 0 :(得分:3)
你不能使它工作,因为你只能将装箱的结构(这是你用(double) input
做的那样)取消对确切的未定类型,因为这个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 :(得分:1)
当将对象转换为double时,编译器不知道它应该调用现有的operator double
,因此它不会向用户定义的运算符double插入任何调用。
当您在中间插入dynamic
时,编译器将生成类似"如果此引用具有运算符double,则调用它`,这样就可以了。
所以,只要你将System.Object
转换为double,它实际上就无法工作,而@juharr建议稍微修改的代码将起作用:
public double GetDouble(Object input)
{
if (input is DoubleContainer)
{
var dc = (DoubleContainer)input;
return (double)dc;
}
return (double)input;
}
编辑:根据@SergiyKlimkov评论修改代码