【问题标题】:C# Explicit Operators and InheritanceC# 显式运算符和继承
【发布时间】:2011-06-06 12:06:20
【问题描述】:

我确定这是一个愚蠢的问题,但为什么下面的代码不调用子类 MyBool 上的强制转换的显式运算符?

public class DataType
{
    public static explicit operator bool(DataType D)
    {
        return false;
    }

    public static explicit operator DataType(bool B)
    {
        return new DataType();
    }
}

public class MyBool : DataType
{
    public bool Value;

    public MyBool()
    {
        Value = false;
    }

    public static explicit operator bool(MyBool B)
    {
        return B.Value;
    }

    public static explicit operator MyBool(bool B)
    {
        return new MyBool() { Value = B };
    }
}

然后:

List<DataType> Types = new List<DataType>();

Types.Add(new MyBool() { Value = true });
Types.Add(new MyBool() { Value = false });

foreach (DataType T in Types)
{
    bool Value = (bool)T;
    MessageBox.Show(Value.ToString());
}

产生输出:假,假

我唯一的选择是在每个类上编写函数来代替显式运算符函数吗?

【问题讨论】:

  • 我的问题是“为什么下面的代码不调用显式运算符...?”不是“这工作正常吗?”。

标签: c# operator-overloading


【解决方案1】:

为什么下面的代码没有为子类 MyBool 的强制转换调用显式运算符?

因为运算符函数是static,因此也不是virtual,因此它们的目标是在编译时而不是运行时解析的。这是预期的行为。

如果您想拥有多态转换运算符,您可以在运算符内部调用虚函数:

public abstract class DataType
{
    public static explicit operator bool(DataType D)
    {
        return D.DoCastToBool();
    }

    public static explicit operator DataType(bool B)
    {
        // We haven’t got an instance of our class here.
        // You can use a factory method pattern to emulate virtual constructors.
    }

    protected abstract bool DoCastToBool();
}

【讨论】:

    【解决方案2】:

    运算符是重载而不是覆盖 - 换句话说,在编译时选择使用哪个实现。编译器只知道TDataType,所以它调用DataType中的运算符。

    一种选择是从MyBool 中删除运算符,但在DataType 中添加一个虚拟方法,允许多态行为:

    public class DataType
    {
        public static explicit operator bool(DataType D)
        {
            // TODO: Decide how you want to handle null references
            return D.ToBoolean();
        }
    
        protected virtual bool ToBoolean()
        {
            return false;
        }
    }
    
    public class MyBool : DataType
    {
        // ...
    
        protected override bool ToBoolean()
        {
            return Value;
        }
    }
    

    请注意,这不会适用于从boolDataType 的转换,因为在这种情况下,我们没有任何关于您实际上是DataType 子类型的任何信息想创作。

    (旁注:如果您使用正常的 .NET 命名约定,您的代码会更容易遵循。)

    【讨论】:

    • Jon,在 .NET 版本中一直都是这种情况吗?或者是否曾经有过 .NET 搜索继承层次结构的时候?我问是因为与此相关的错误似乎与项目升级到更新的 .NET 相吻合。有问题的对象在编译时被键入为“对象”,但运行时类型确实定义了运算符。我非常怀疑这种情况,但有人建议......
    • @Sprague:不,一直都是这样。
    【解决方案3】:

    这里有一个垃圾解决方案:

    替换:bool Value = (bool)T;

    与:bool Value = (bool)(T as MyBool);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-07
      • 2012-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多