Joa*_*nge 10 .net c# generics interface icomparable
当我想约束类型T可比时,我应该使用:
where T : IComparable
Run Code Online (Sandbox Code Playgroud)
要么
where T : IComparable<T>
Run Code Online (Sandbox Code Playgroud)
如果#2有道理,我无法理解.任何人都可以解释它的区别是什么?
IComparable和IComparable <>之间的主要区别在于,第一个是pre-generics,所以允许你用任何对象调用compare方法,而第二个强制它共享相同的类型:
IComparable - CompareTo(object other);
IComparable<T> - CompareTo(T other);
Run Code Online (Sandbox Code Playgroud)
我会选择第二个选项,前提是您不打算使用任何旧的.net 1.0库,其中的类型可能无法实现现代的通用解决方案.你将获得性能提升,因为你将避免拳击,比较不需要检查类型匹配,你也会得到以最前沿的方式做事的温暖感觉......
为了解决Jeff的非常好和相关的观点,我认为将执行任务所需的通用限制放在通用上是一种好习惯.由于您完全控制通用内部的代码,因此您知道是否正在使用任何需要基本IComparable类型的方法.因此,考虑到他的评论,我个人会遵循以下规则:
如果您不希望泛型使用任何仅实现IComparable(即遗留1.0代码)的类型,并且您没有从依赖于IComparable参数的泛型内部调用任何方法,则仅使用IComparable <>约束.
如果您正在使用,只有实现IComparable类型,然后使用该约束只
如果您使用的方法需要IComparable参数,但不使用仅实现IComparable的类型,那么使用Jeff的答案中的两个约束将在您使用接受泛型类型的方法时提高性能.
要扩展第三条规则 - 让我们假设您正在编写的类如下:
public class StrangeExample<T> where ... //to be decided
{
public void SortArray(T[] input)
{
Array.Sort(input);
}
public bool AreEqual(T a, T b)
{
return a.CompareTo(b) == 0;
}
}
Run Code Online (Sandbox Code Playgroud)
我们需要决定对它施加什么限制.SortArray方法调用Array.Sort,它要求传入的数组包含实现IComparable的对象.因此,我们必须有一个IComparable约束:
public class StrangeExample<T> where T : IComparable
Run Code Online (Sandbox Code Playgroud)
现在该类将编译并正常工作,因为T的数组对于Array.Sort是有效的,并且在接口中定义了一个有效的.CompareTo方法.但是,如果您确定不希望使用类型不能实现IComparable <>接口的类,则可以将约束扩展为:
public class StrangeExample<T> where T : IComparable, IComparable<T>
Run Code Online (Sandbox Code Playgroud)
这意味着当调用AreEqual时,它将使用更快,通用的CompareTo方法,您将看到性能优势,但代价是无法将其与旧的.NET 1.0类型一起使用.
另一方面,如果你没有AreEqual方法,那么IComparable <>约束没有任何优势,所以你也可以删除它 - 你只是使用IComparable实现.
您可能需要两个约束,如:
where T : IComparable, IComparable<T>
Run Code Online (Sandbox Code Playgroud)
这将使您的类型与更多的IComparable接口用户兼容.通用版本IComparable,IComparable<T>将有助于避免装箱时T是值类型和允许的接口方法更强类型的实现.支持两者都可以确保无论其他对象要求哪个接口,您的对象都可以遵守,从而可以很好地互操作.
例如,Array.Sort并ArrayList.Sort使用IComparable,而不是IComparable<T>.
允许IComparable<T>比较器是强类型的。
你可以有
public int CompareTo(MyType other)
{
// logic
}
Run Code Online (Sandbox Code Playgroud)
与相反
public int CompareTo(object other)
{
if (other is MyType)
// logic
}
Run Code Online (Sandbox Code Playgroud)
以下一个实现这两个接口的示例为例:
public class MyType : IComparable<MyType>, IComparable
{
public MyType(string name, int id)
{ Name = name; Id = id; }
public string Name { get; set; }
public int Id { get; set; }
public int CompareTo(MyType other)
{
if (null == other)
throw new ArgumentNullException("other");
return (Id - other.Id > 0 ? 1 : 0);
}
public int CompareTo(object other)
{
if (null == other)
throw new ArgumentNullException("other");
if (other is MyType)
return (Id - (other as MyType).Id > 0 ? 1 : 0);
else
throw new InvalidOperationException("Bad type");
}
}
MyType t1 = new MyType("a", 1);
MyType t2 = new MyType("b", 2);
object someObj = new object();
// calls the strongly typed method: CompareTo(MyType other)
t1.CompareTo(t2);
// calls the *weakly* typed method: CompareTo(object other)
t1.CompareTo(someObj);
Run Code Online (Sandbox Code Playgroud)
如果MyType仅使用 实现IComparable<MyType>,则第二个compareTo(someObj)是编译时错误。这是强类型泛型的优点之一。
另一方面,框架中的某些方法需要非泛型,IComparable例如Array.Sort. 在这些情况下,您应该考虑实现两个接口,如本例所示。