我目前正在使用C#中的运算符重载实现算法区分的简单版本。我试图弄清楚如何设计适用于普通双打的通用数学函数和我自己的类“ADouble”,它类似于double,但重载算术运算符,如+,*, - 等等。
例如,我想创建一个像
这样的函数Public T MathFunction<T>(T x) where T : "is either double or Adouble"
{
if (x > 0)
return new T(1.0)
else
// something
}
适用于双打和ADoubles。在这种情况下,我需要“新建”特定值(此处为1.0)。在其他情况下,我可能需要做类似
的事情Public T MathFunction<T>(T x) where T : "is either double or Adouble"
{
T temporaryVar = 2*x;
// .. More calculations
return "some T";
}
我已经实现了必要的接口来进行比较,如上所述,但我无法完成其余工作。
我可以使用double来实例化我的ADouble类,比如说
Adouble myADouble = new ADouble(12.3);
但是双打没有一个以这种方式工作的构造函数。我尝试了不同的东西。首先,我想到了像
这样的东西if (typeof(T) == typeof(ADouble)
return new ADouble(1.0)
但这不起作用,因为该函数无法明确地将ADouble转换为T(我理解)。
有没有人建议我如何实现适用于我的ADouble类和双打的通用计算函数?或者是使用不同签名制作多个方法的唯一选择?对设计的不同建议也非常感谢。
答案 0 :(得分:1)
或者是使用不同签名制作多个方法的唯一选择吗?
称为“方法重载”。
是。这是表达“类型A或类型B”约束的正确方法,特别是因为即使您可以成功地将其表达为通用约束,您仍然需要调用相应的构造函数。
C#泛型中没有一种机制可以使语句return new T(1.0);
成功编译。这样做需要一些语法,这些语法还会将类型限制为具有类型为double
的单个参数的构造函数的类型,并且C#中没有这样的特性。
这不起作用,因为函数无法将ADouble强制转换为T
实际上,它不能隐式地 。但是,足够接近。 :)
这将是您必须清除的下一个障碍。具有讽刺意味的是,这是最简单的。问题是,当你编写表达式时,编译器已经知道了什么,知道它不能保证演员表能够成功。但是,如果您首先将值转换为object
,则可以在没有编译器抱怨的情况下将其强制转换为T
。
请注意,并非我建议这样做。这里真正的问题是你试图使用通用语法来实现非常规的东西。通用代码适用于您可以使用任何类型的地方,或者至少是广泛约束类型。如果您有特定的类型,特别是如果每种特定类型的实现都不同,那么您不应该使用泛型。
在这种情况下,方法重载更合适。
除此之外:假设您的ADouble
类型实际上等同于double
,并且您可以实现转换而不会丢失任何数据,您应该考虑编写隐式转换,以帮助使类型可以互换。这看起来像这样:
public static implicit operator ADouble(double value)
{
return new ADouble(value);
}
然后,您可以使用简单的分配初始化ADouble
值,例如:
ADouble adouble = 1.0;