2011-01-12 123 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将使用两种技术进行编译。我会建议使用第二种技术,以使其在两种情况下都能发挥同样的作用。无论如何,这似乎是一个惯例,可能是出于这个原因。但还有其他原因可以避免使用第一个。在您可能希望为特定类型重载方法的情况下,第二种方法为您提供更大的灵活性。