2013-01-15 49 views
5

在C++超載,你可以這樣寫代碼:你爲什麼不能要求運營商在仿製藥

template<class T> 
T Add(T lhs, T rhs) 
{ 
    return lhs + rhs; 
} 

但是,你不能做這樣的事情在C#:

public static T Add<T>(T x, T y) where T : operator+ 
{ 
    return x + y; 
} 

有任何理由?我知道它可以通過反射來實現(通用的Add與對象,然後運行類型檢查全部),但這是效率低下,並不能很好地擴展。那麼,爲什麼呢?

+0

這看起來像是一個重複的http://stackoverflow.com/questions/756954/arithmetic-operator-overloading-for-a-generic-class-in-c-sharp – neontapir

+0

@neontapir接受的答案使用反射。我提到我知道可以這樣做,我不想。 –

+0

我認爲在第二段中你的意思是你不能在C#中這樣做,即問題是「爲什麼沒有運算符重載類型約束?」 (我不知道的答案,順便說一句)。 –

回答

5

這並不存在的內在原因。泛型類型約束的實現方式是通過接口調用。如果有一個接口提供了一個operator+這將工作。

儘管如此,該接口將被要求用於所有相關類型,與基於C++模板的模擬類似。

另一個問題是,.NET沒有多次調度。界面調用將是不對稱的:a.Plus(b)可能意味着與b.Plus(a)不同。 Equals也有同樣的問題,順便說一句。

所以這個問題可能不符合「有用性」欄或「成本/效用」欄。這不是不可能的問題,而是實際問題。

證明有可能:((dynamic)a) + ((dynamic)b)

+3

有一件事你沒有提到(至少不是明確的):*不能*是一個提供'operator +'的接口,因爲操作符必須是'static'方法而'static'方法不能成爲一個界面。 – svick

+1

@svick我正在談論一個假想的.NET未來版本。運營商可以增加實例方法版本。現在,你是對的。 – usr

3

CLR本身不支持這種約束,而C#設計團隊顯然決定支持與CLR相同的一組約束。據推測,CLR團隊和C#團隊都認爲,實現這樣一個功能的好處並沒有超過指定,實施和測試它的成本。

如果您想要使用支持此類約束的.NET語言,請考慮查看F#。

+0

儘管我相信F#只在某些情況下支持這種約束(因爲CLR約束的限制)。 – svick

+1

@svick - F#在可能的情況下使用CLR約束,但具有自己的元數據格式,用於表示大量無法在CLR類型系統中表示的F#特定信息。一個這樣的項目是一個成員約束,它需要一個類型具有一個具有特定名稱和簽名的方法。 – kvb

0

有幾種可能的方式來實現操作符約束,它們都是非平凡的(並且可能需要更改CLR)或者有明顯的缺點(例如,它們會很慢,比添加兩個整數慢得多)。

這是一個相對容易解決的問題(使用dynamic的緩慢,一般和不安全的方式,或者具有bajillion重載的快速,類型特定和安全的方式)。因此,這樣的功能可能被認爲「很高興」,但遠不足以保證這種改變。