2010-03-04 15 views
4

我有下面的代碼「!=」:使用比較操作符,比如和「==」,在C#中的限制爲值仿製藥

class Foo<T> where T : struct 
{ 
    private T t; 
    [...] 
    public bool Equals(T t) { return this.t == t; } 
} 

當我嘗試編譯,它給了我下面的錯誤:

Operator '==' cannot be applied to operands of type 'T' and 'T'

爲什麼不能這樣做?如果約束是where T : class它會起作用。但我需要它是值類型的,因爲在我的實現中,這個泛型將永遠是一個枚舉。

我在做什麼來避免這種情況是使用Object.Equals()方法。它會一直保證正確的行爲,因爲我只是比較T?

+0

這是在我的時區有點晚了。明天我會檢查其他答案並標記已接受的答案。謝謝大家! – 2010-03-04 10:48:07

+0

請記住,您可以使用'ReferenceEquals'來檢查引用是否相等,這就是'=='通常會做的事情(除非我錯了或者它已被覆蓋)。 – Svish 2010-03-04 11:00:40

+0

@Svish - 當傳遞值類型時,'ReferenceEquals'總是返回'false',這就是'T'被限制在這裏的原因。 – 2010-03-04 14:33:02

回答

3

這是約束系統的不受歡迎的限制。除非在接口中定義,否則不能根據其上的特定操作約束值類型。所以你不能限制對經營者的定義,因爲它們不會在所有的值類型來定義,struct約束允許任何類型的值,以傳遞。

struct A { } 

一個沒有定義==,可是你的約束說你會很樂意接受它。所以你不能使用==

其參考類型不同的原因是因爲總是有一個可用於它們的==的定義(身份比較)。

enum上的==的實施已經足夠接近Equals的執行情況,您的解決方法很好。

與數字類型的>的情況比較!沒有這樣的解決方法。標準號碼與GreaterThan等方法沒有接口。

+0

嗯,我明白了...感謝所有的澄清! – 2010-03-04 10:49:44

+0

在您的引用類型註釋中,請記住'=='不能被重寫*,但可以重載*。因此,只有當運算符用於從該類型派生的靜態已知參數時,纔會調用特定引用類型上的'=='定義。對泛型方法只有一個「類」約束,這意味着'=='總是*身份比較。 – kvb 2010-03-04 16:52:20

+0

@kvb - 你說得對,我已經刪除了「除非被覆蓋」,因爲無論如何這兩個詞都措辭不佳,無關緊要。 – 2010-03-04 16:56:30

1

看看Jon Skeet和Marc Gravell的this article。它描述了使用Linq表達式的「泛型操作符」的實現。實際的實現可在the MiscUtil library

+0

這是一篇很棒的文章,但當僅僅比較平等時肯定是過度的 - 。NET框架已經爲它提供了一個通用的方法名稱'Equals',因此它可以用於所有類型。因此,OP的解決方法很好,並保證可用於任何其他類型的參數。對於更多與數字相關的運算符,Linq表達式的方法非常巧妙,但它引入了一個類型空洞。 – 2010-03-04 10:48:42