C#显式运算符和继承
本文关键字:继承 运算符 | 更新日期: 2023-09-27 17:58:32
我确信这是一个愚蠢的问题,但为什么下面的代码没有为子类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());
}
生成输出:false,false
我唯一的选择是在每个类上编写函数来代替显式运算符函数吗?
为什么下面的代码没有为子类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();
}
运算符被重载,而不是被覆盖-换句话说,在编译时可以选择使用哪个实现。编译器只知道T
是DataType
,所以它调用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;
}
}
请注意,这个不适用于从bool
到DataType
的转换,因为在这种情况下,我们没有任何关于您实际要创建DataType
的子类型的信息。
(附带说明:如果您使用普通的.NET命名约定,您的代码将更容易遵循。)
这里有一个垃圾解决方案:
替换:bool Value = (bool)T;
带有:bool Value = (bool)(T as MyBool);