2011-01-12 162 views
1

哪個版本更好:通用約束

using System; 

namespace Utils.Extensions 
{ 
    public static class EnumerableExtensions 
    { 
     public static bool Between<T>(this T item, T min, T max) where T : IComparable<T> 
     { 
      return item.CompareTo(min) >= 0 && item.CompareTo(max) <= 0; 
     } 
    } 
} 

using System; 

namespace Utils.Extensions 
{ 
    public static class EnumerableExtensions 
    { 
     public static bool Between<T>(this IComparable<T> item, T min, T max) 
     { 
      return item.CompareTo(min) >= 0 && item.CompareTo(max) <= 0; 
     } 
    } 
} 

我認爲兩者都應該工作,但哪一個我應該使用?

+1

定義「更好」。更高級的預設?可讀?還有別的嗎? – Oded 2011-01-12 11:06:35

+0

我想他們的表現差異可以忽略不計。我正在考慮更多的優雅或可讀性。 – 2011-01-12 11:10:48

回答

3

請注意,使用第二個版本時T是值類型意味着item將被裝箱。將值類型轉換爲接口總是需要裝箱。

我不會過多擔心接口的問題,但值得注意的是,BCL中幾乎所有的實現都是值類型的。只有你可以決定(小)拳擊開銷是否可以接受。

3

我認爲第二個更好。 它不會混亂 intelliSense建議列表的類型不是 IComparable 。 (它不會在任何情況下。)

而你在找什麼是IComparable特定。

因此,如果您選擇的是可讀性,那麼使用第二種方法已經足夠清楚了。

+1

這應該是沒有問題的,因爲您將T約束爲繼承IComparable的類型 ... – 2011-01-12 11:12:12

+1

請注意,第二個版本將導致「item」被裝箱,如果它是值類型的,並且幾乎每個「IComparable 」框架是一種價值型。 (這對於OP來說實際上是否是一個問題,是由他們來決定的。) – LukeH 2011-01-12 11:33:36

-1

我會說第一個,因爲它說了關於每個T的內容,其中第二個只說該項目應該是IComparable。事實上它也應該這樣做,但是通過你想說的話,每個T是IComparable。第一個更好。

2

這兩者之間有明顯的區別。第一個預計將用於實現IComparable<T>的類型,其中第二個旨在用於IComparable<T>

給出的例子答:

對比度,以例B
IComparable<int> x = 14; 
bool y = x.Between(12, 23); 

int x = 14; 
bool y = x.Between(12, 23); 

如果您嘗試使用例如一個與你的第一個技術(通用約束),那麼你會得到一個編譯器錯誤,因爲約束需要實現IComparable<int>的類型,而不是IComparable<int>本身。

示例B將使用兩種技術進行編譯。我會建議使用第二種技術,以使其在兩種情況下都能發揮同樣的作用。無論如何,這似乎是一個慣例,可能是出於這個原因。但還有其他原因可以避免使用第一個。在您可能希望爲特定類型重載方法的情況下,第二種方法爲您提供更大的靈活性。