是否应将通用约束作为参数类型使用接口?

Dan*_*Tao 13 .net generics boxing interface constraints

考虑这个简单的功能:

public static bool IsPositive(IComparable<int> value)
{
    return value.CompareTo(0) > 0;
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我传递int给这个方法,它会被装箱.因此,将上述方法定义如下更好吗?

public static bool IsPositive<T>(T value) where T : IComparable<int>
{
    return value.CompareTo(0) > 0;
}
Run Code Online (Sandbox Code Playgroud)

以这种方式使用泛型约束,我可以实现与上面的代码完全相同的功能,并且具有额外的好处,即不需要装箱(因为调用IsPositive<int>接受类型的参数int).

上面的示例代码显然毫无意义.但我更广泛的问题是:以后一种方式定义方法(使用通用约束而不是某种接口类型的参数)不是有意义,以避免潜在的值类型装箱?

我怀疑答案可能是"是的,但它需要更多的打字,并且在很多情况下遇到值类型将是非常不可能的,例如当方法接受一些时IEnumerable<T>." 但是我想知道这些方法之间是否存在更大的差异,这些方法目前正在逃避我.

Mat*_*ted 8

一个问题是通用约束实际上不是签名的一部分.如果你有 ...

static T Method<T>(T value) where T : ICompareable<int>
Run Code Online (Sandbox Code Playgroud)

......而且......

static T Method<T>(T value) where T : IEnumerable<int>
Run Code Online (Sandbox Code Playgroud)

...编译器无法知道哪个是哪个.

并调用Eric Lippert ......

  • 我还在等待那天我可以说`T.Parse(字符串)` (2认同)

Eri*_*ert 7

关于在参数传递之后对方法的调用是否引发装箱的问题的评论中存在一些混淆.

当您对类型为带有约束的类型参数的表达式调用虚方法时,C#编译器会发出constrained.callvirt指令.正如人们所希望的那样,这是正确的; 拳击只在绝对必要时才会发生.

有关约束虚拟调用的精确装箱语义的详细信息,请阅读文档:

http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.constrained.aspx