通用约束

时间:2011-01-12 11:03:53

标签: c# generics

哪个版本更好:

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;
        }
    }
}

我认为两者都应该有用,但我应该使用哪一个?

4 个答案:

答案 0 :(得分:3)

我认为第二个更好。 对于不是intelliSense 的类型,它不会使IComparable建议列表混乱。 (在任何情况下都不会。)

您正在寻找的是IComparable特有的。

因此,如果您选择的是可读性,那么使用第二种方法就足够了。

答案 1 :(得分:3)

请注意,T为值类型时使用第二个版本意味着item将被装箱。将值类型转换为接口总是需要装箱。

我不会过于担心接口的这种情况,但值得注意的是,BCL中几乎每个IComparable<T>实现都是值类型。只有你可以决定(小)拳击开销是否可以接受。

答案 2 :(得分:2)

两者之间存在明显差异。第一个应该用于实现IComparable<T>的类型,其中第二个用于IComparable<T>

举例A:

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

与示例B对比:

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

如果您尝试使用第一种技术(通用约束)使用示例A,那么您将获得编译器错误,因为约束需要一个实现IComparable<int>的类型,而不是{{1本身。

示例B将使用这两种技术进行编译。我建议使用第二种技术,以便它在两种情况下都能正常工作。无论如何,它似乎是惯例,可能是出于这个原因。但是还有其他原因可以避免使用第一个。在您可能希望为特定类型重载方法的情况下,第二种方法可以提供更大的灵活性。

答案 3 :(得分:-1)

我会说第一个,因为它说明了每一个T,其中第二个只说该项应该是IComparable。确实它应该做同样的事情,但是通过你想说的话,每个T都是IComparable。第一个更好。