开发者

Generic constraints

Which version is better:

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

or

using System;

namespace Utils.Extensions
{
    public static class EnumerableExtensions
    {
        public static bool Between<T>(this IComparable<T> item, T min, T max)
        {
            return ite开发者_开发技巧m.CompareTo(min) >= 0 && item.CompareTo(max) <= 0;
        }
    }
}

I think both should work, but which one should I use?


Note that using the second version when T is a value-type means that item will be boxed. Casting a value-type to an interface always requires boxing.

I wouldn't worry too much about this for interfaces in general, but it's worth noting that almost every IComparable<T> implementation in the BCL is a value-type. Only you can decide whether the (small) boxing overhead is acceptable.


I think the second one is better. It won't clutter up intelliSense suggestion list for types that are not IComparable. (It won't in any case.)

And what you are looking for is specific to IComparable.

So, it is clear enough to use the second approach if what you are opting for is readability.


There's an obvious difference between the two. The first one is expected to be used on a type that implements IComparable<T>, where the second one is meant to be use on an IComparable<T>.

Given example A:

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

Contrast to example B:

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

If you attempt to use example A with your first technique (the generic constraint), then you are going to get a compiler error, because the constraint requires a type that implements IComparable<int>, and not an IComparable<int> itself.

Example B will compile using both techniques. I would advise using the second technique so that it works the same in both situations. It appears to be the convention anyway, probably for this reason. But there are other reasons to avoid using the first one anyway. In situations where you might wish to overload a method for particular types, the second method gives you more flexibility.


I would say the first one, because it says something about every T, where the second one only says that item should be IComparable. Indeed it should do the same, but by means of what you want to say, that every T is IComparable. The first one is better.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜