2017-04-06 344 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