C# 使用转换运算符强制转换对象失败
所以我有这个物体,比如说双容器C# 使用转换运算符强制转换对象失败,c#,generics,implicit-conversion,C#,Generics,Implicit Conversion,所以我有这个物体,比如说双容器 public struct DoubleContainer { private readonly double _value; private DoubleContainer(double value) { _value = value; } public static implicit operator double(DoubleContainer 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);
}
}
几乎在所有情况下,强制转换都能按预期工作,但将其作为对象传递到函数中的情况除外
如果传入DoubleContainer,以下代码将生成InvalidCastException:
public double GetDouble(Object input)
{
return (double)input;
}
如果我使用dynamic,我可以让它工作:
public double GetDouble(Object input)
{
return (double)(dynamic)input;
}
这个解决方案的问题是VisualStudio将(动态)显示为灰色,因为它应该是冗余的,所以有人可能会删除它。另外,我不知道在代码库中是否还有其他地方会出现同样的问题
对于DoubleContainer的实现,我能做些什么呢?是什么让我的第一个GetDouble()实现工作?我尝试添加另一个从Object到DoubleContainer的隐式转换运算符,但“不允许向基类或从基类进行用户定义的转换”…将对象强制转换为double时,编译器不知道它应该调用现有的
运算符double
,因此,它不会向用户定义的运算符double插入任何调用
当你在中间插入<代码>动态< /代码>时,编译器将生成“如果这个引用有一个操作符加倍,调用它”,那么它就起作用了。
因此,只要您将系统对象
强制转换为double,它实际上就无法工作,而@juharr建议的代码经过稍微修改后,可以工作:
public double GetDouble(Object input)
{
if (input is DoubleContainer)
{
var dc = (DoubleContainer)input;
return (double)dc;
}
return (double)input;
}
编辑:根据@SergiyKlimkov comment修改代码,您无法使其正常工作,因为您只能将装箱结构(这是您使用
(double)input所做的)取消装箱到确切的未装箱类型,原因最好由Eric Lippert在本文中描述。因此,无论何时执行(double)someObject
-只有当object实际上是一个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);
}
为什么要将一个double
封装到一个类中,只是为了将其强制转换为对象
?如果这只是一个示例,并且您有一个更复杂的类,具有有效的强制转换为double
,那么为什么要将其强制转换为对象
。基本上,如果您有这些类型的强制转换问题,您应该真正查看您的设计。我同意我们的代码这方面的设计是有问题的。不幸的是,在发行版的这一点上重新设计是不可能的。我只是想为一个bug找到一个修复方法,希望它有点健壮,而不是超级黑客。@Ash该类本身就是超级黑客。你可以做一些类似于var dc=input as DoubleContainer;if(dc!=null)return(double)dc;else返回(double)input;
我想这真的取决于您希望传递给GetDouble
的内容。“我能对我的DoubleContainer实现做些什么吗?什么能让我的第一个GetDouble()实现工作?”-不,没有。DoubleContainer是一个结构。所以“作为DoubleContainer输入”“不会编译。它需要替换为“(DoubleContainer)input”。你链接的那篇文章解释得很好。@Ash:很高兴听到这个消息!这是一个关于演员阵容的常见问题。