2017-04-06 350 views
1

我目前正在实现一个简单版本的算法差异,并在C#中使用运算符重载。我试图弄清楚如何设计适用于普通双打的通用数学函数,以及像“double”一样工作的自己的类“ADouble”,但重载了算术运算符(如+,*,等等)。通用方法:返回double或double-like类

举例来说,我想创建一个函数像

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

我已经实现必要的接口做像上面的比较,但我不能让剩下的工作。

我可以实例我ADouble类具有双重的,说

Adouble myADouble = new ADouble(12.3); 

但双打不具有这样工作构造,效果显着。我尝试过不同的事情。首先,我认为像

if (typeof(T) == typeof(ADouble) 
    return new ADouble(1.0) 

但这不起作用,因为该功能可以不投ADouble至T明确(据我所知)。

有没有人有一个关于如何去实现通用计算函数,我的ADouble类和双打的建议?或者是用不同签名制作多种方法的唯一选择?不同的设计建议也非常感谢。

+0

AFAIK你不能用'x或y'在泛型约束。你可以用'dynamic'参数创建一个方法,如果它是'double'或者'ADouble',并且不抛出无效参数异常,就可以在里面进行测试。 –

+0

您可以利用'Double'类实现的接口,如'IConvertible','IComparable'或'IEquatable'。 – Romoku

+0

另一种方法是构建[Expressions](https://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx)。 – Romoku

回答

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; 
+0

感谢您的详细解释。特别是最后一部分。这非常有帮助。我最终做的是为ADouble实现所有数学方法,然后创建一个重载版本,该重载版本返回double并将其作为输入双精度,然后使用隐式转换方法调用该方法的ADouble版本。这现在工作正常。 – amri