通用约束是否应该优先于使用接口作为参数类型?
考虑这个简单的函数:
public static bool IsPositive(IComparable<int> value)
{
return value.CompareTo(0) > 0;
}
现在,如果我将一个 int
传递给这个方法,它就会被装箱。因此,将上述方法定义如下不是更好吗?
public static bool IsPositive<T>(T value) where T : IComparable<int>
{
return value.CompareTo(0) > 0;
}
以这种方式使用通用约束,我可以实现与上面的代码完全相同的功能,还有一个好处是不需要装箱(因为对 IsPositive
的调用接受类型的参数int
)。
上面的示例代码显然毫无意义。但我更广泛的问题是:用后一种方式定义方法(使用泛型约束而不是具有某种接口类型的参数)是否总是有意义,以避免潜在的潜在问题值类型装箱?
我怀疑答案可能是“是的,但它需要更多的输入,并且在许多情况下遇到值类型的可能性很小,例如当方法接受一些 IEnumerable< ;T>
。”但我想知道这些方法之间是否存在目前我无法理解的更大差异。
Consider this trivial function:
public static bool IsPositive(IComparable<int> value)
{
return value.CompareTo(0) > 0;
}
Now, if I pass an int
to this method, it gets boxed. Wouldn't it therefore be better to define the above method as follows?
public static bool IsPositive<T>(T value) where T : IComparable<int>
{
return value.CompareTo(0) > 0;
}
Using a generic constraint in this way, I can achieve exactly the same functionality as the code above, with the added benefit that no boxing is necessary (since a call to IsPositive<int>
accepts a parameter of type int
).
The example code above is clearly quite pointless. But my broader question is: wouldn't it always make sense to define methods in the latter way (using a generic constraint rather than having a parameter of some interface type), to avoid the potential boxing of value types?
I suspect that the answer is likely to be "yes, but it requires more typing and in many cases encountering a value type will be very unlikely, such as when a method accepts some IEnumerable<T>
." But I'm wondering if there's a greater difference between these approaches that is escaping me at the moment.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
一个问题是通用约束实际上并不是签名的一部分。如果你有……
和
……编译器将无法知道哪个是哪个。
并调用 Eric Lippert...
约束不是签名的一部分
通用约束问题
One issue would be with the fact that the generic constrain isn't really part of the signature. If you have ...
... and ...
... the compiler wouldn't have a way to know which is which.
And to invoke Eric Lippert...
Constraints are not part of the signature
A Generic Constraint Question
对于关于在参数传递后调用该方法是否会引发装箱的问题,评论中存在一些混乱。
当您在类型为带有约束的类型参数的表达式上调用虚拟方法时,C# 编译器会发出
constrained.callvirt
指令。正如人们所希望的那样,这样做是正确的。拳击只有在绝对必要时才会发生。有关受约束虚拟调用的精确装箱语义的详细信息,请阅读文档:
http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.constrained.aspx
There was some confusion in the comments to the question regarding whether or not the call to the method induces a boxing after the argument is passed.
When you make a call to a virtual method on an expression whose type is a type parameter with a constraint on it, the C# compiler emits a
constrained.callvirt
instruction. As one would hope, this does the right thing; the boxing only happens when absolutely necessary.For details regarding the precise boxing semantics of constrained virtual calls, read the documentation:
http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.constrained.aspx
另一个问题是,当泛型约束位于参数化类型的泛型类型参数上时,例如,
它并不总是能够以这种方式转换泛型类型参数,除非您引入像这样的第二个类型参数:
这看起来不正确。
Another issue would be when the generic constraint is on a parameterized type's generic type parameters, such as
It is not always possible to convert the generic type parameter this way, unless you introduce a second type parameter like this:
That just doesn't look right.