2017-06-29 21 views
2

比較結構下面就是我掙扎的簡單情況:在一個通用的方法

public bool CompareStruct<S>(S a, S b) where S : struct 
{ 
    return a == b; 
} 

上面不會有錯誤Operator '==' cannot be applied to operands of type 'S' and 'S'編譯。

通常情況下,我不會感到驚訝。但我已經指出,S是一個結構 - 所以爲什麼我不能比較這兩個參數?

我不認爲this SO question有這裏的任何相關性 - 畢竟,我與struct類型的工作,而不是引用類型。

+3

'其中S:IEquatable '和'a.Equals(b)'。 –

+0

@ LasseV.Karlsen好的,這解決了「如何獲得這個編譯」。但是......爲什麼在上面的例子中'=='不能用於'struct'?編譯器不知道它能夠比較這兩個參數嗎? – Shaamaan

+0

請參閱這篇文章:https://www.codeproject.com/Articles/1166856/Equality-Operator-equalsequals-and-Value-Types-in –

回答

2

這裏讀取的問題是,==在C#中的默認行爲是引用相等。結構中的引用相等是沒有意義的,因爲它總是會返回false

編譯器無法知道==是否已經過載,並且S具有值相等的語義,因此不允許使用它。

要解決此問題,請使用Equals並考慮將S限制爲IEquatable<S>,以避免不必要的裝箱操作。

1

除非明確覆蓋==!=運算符,否則不能在用戶定義的ValueType上使用==。這是因爲struct的默認實現不會實現這些運算符。例如,下面的不編譯:

struct Foo 
{ 

} 

void Main() 
{ 
    Foo f1; 
    Foo f2; 

    if(f1 == f2) // The compiler complains here 
    { 

    } 
} 

所以,如果你不能做到這一點已知結構(默認),那麼你可以這樣做,對於一般結構(在編譯時已知的信息較少),除非你提供更多的信息(例如,這個結構必須實現IEquatable<S>

上面的方法適用於類,因爲它們在使用==時默認使用引用相等。這不適用於值類型,因爲它們是按值複製的。

2

的問題是,當你指定的泛型類型參數爲struct即值類型的約束,這是沒有必要的調用該方法的struct提供了==超載實施和!=操作它,因爲對於自定義值類型,當我們定義它時,我們需要提供==!=運算符重載以供它們使用。

另一種可能是使用Object.Equals方法或撥打Equals()方法在它自己的實例,如:

public bool CompareStruct<S>(S a, S b) where S : struct 
{ 
    return a.Equals(b); 
} 

或:

public bool CompareStruct<S>(S a, S b) where S : struct 
{ 
    return Object.Equals(a,b); 
} 

的一點要記住的是,但平等的運營商默認情況下不適用於值類型,除非您爲該類型和參考類型使用==過載==運算符將檢查引用是否相等,因此這就是爲什麼應用約束nt到class工作正常。

我曾經寫過一個關於這個職位,這可能是有用的,可以在this link (Equality Operator (==) and Value Types in C#)

+0

對'class'的約束消除了編譯時錯誤,類型也不一定實現'=='。你的答案中遺漏的重要事實(你當然知道,但OP可能不會)是'=='默認引用相等,這對數值類型沒有意義。 – InBetween

+0

你是對的,我已經提到這種情況是特定於'struct' ValueType –