代码之家  ›  专栏  ›  技术社区  ›  Ash

使用转换运算符强制转换对象失败

  •  3
  • Ash  · 技术社区  · 7 年前

    我有一个物体,比如说双容器。

    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);
        }
    }
    

    几乎在所有情况下,强制转换都能按预期工作,除非它作为对象传递到函数中。

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

    如果我使用dynamic,我可以让它工作:

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

    2 回复  |  直到 7 年前
        1
  •  3
  •   Eric Lippert    7 年前

    您无法使其工作,因为您只能取消装箱结构(这就是您正在使用的) (double) input )对于确切的非真实类型,原因最好在本文中描述 article 作者:Eric Lippert。所以无论什么时候 (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);
    }
    
        2
  •  1
  •   Gian Paolo    7 年前

    将对象强制转换为double时,编译器不知道它应该调用现有的 operator double ,因此它不会插入对用户定义的运算符double的任何调用。

    插入时 dynamic 在中间,编译器将生成类似“如果此引用具有运算符double,则将其称为”,这样它就可以工作。

    所以,只要你投一个 System.Object

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

    编辑:根据@SergiyKlimkov注释修改代码