扩展 System.Object 时如何避免装箱/拆箱?
我正在研究一种仅适用于引用类型的扩展方法。然而,我认为目前正在对值进行装箱和拆箱。我怎样才能避免这种情况?
namespace System
{
public static class SystemExtensions
{
public static TResult GetOrDefaultIfNull<T, TResult>(this T obj, Func<T, TResult> getValue, TResult defaultValue)
{
if (obj == null)
return defaultValue;
return getValue(obj);
}
}
}
用法示例:
public class Foo
{
public int Bar { get; set; }
}
在某些方法中:
Foo aFooObject = new Foo { Bar = 1 };
Foo nullReference = null;
Console.WriteLine(aFooObject.GetOrDefaultIfNull((o) => o.Bar, 0)); // results: 1
Console.WriteLine(nullReference.GetOrDefaultIfNull((o) => o.Bar, 0)); // results: 0
I'm working on an extension method that's only applicable to reference types. I think, however, it's currently boxing and unboxing the the value. How can I avoid this?
namespace System
{
public static class SystemExtensions
{
public static TResult GetOrDefaultIfNull<T, TResult>(this T obj, Func<T, TResult> getValue, TResult defaultValue)
{
if (obj == null)
return defaultValue;
return getValue(obj);
}
}
}
Example usage:
public class Foo
{
public int Bar { get; set; }
}
In some method:
Foo aFooObject = new Foo { Bar = 1 };
Foo nullReference = null;
Console.WriteLine(aFooObject.GetOrDefaultIfNull((o) => o.Bar, 0)); // results: 1
Console.WriteLine(nullReference.GetOrDefaultIfNull((o) => o.Bar, 0)); // results: 0
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
那不是拳击。你认为这是拳击的什么地方?如果这是因为您已经查看了“==”周围的 IL,请不要让它欺骗您 - JIT 可以决定在这里做什么。它有机会为每个 (
T
,TResult
) 对生成不同的本机代码。事实上,所有引用类型的代码都是共享的,而值类型的代码则有所不同。因此,您最终会得到:话虽如此,如果您想将扩展方法限制为引用类型,请这样做:
IL 中仍然会有一个框,但不用担心 - 实际上不会发生装箱。毕竟,什么可以被装箱呢?您提供了一个引用,并且引用本身永远不会被装箱 - 只有值类型值才会被装箱。
That's not boxing. Where do you think it is boxing? If it's because you've looked at the IL around "==", don't let it fool you - the JIT gets to decide what to do here. It has the chance to generate different native code for each (
T
,TResult
) pair. In fact, the code will be shared for all reference types, and differ for value types. So you'd end up with:Having said that, if you want to restrict your extension method to reference types, do so:
There'll still be a box in the IL, but don't worry - no boxing will actually occur. After all, what could be boxed? You're providing a reference, and references themselves are never boxed - only value type values are boxed.
简而言之,该代码中没有任何内容需要装箱。在某些情况下,装箱是不可避免的,并且还有其他操作码用于弥合值/引用类型之间的差距(
受约束
)。但在这种情况下并非如此;不需要实际装箱(JIT 可以删除一些类似盒子的情况 - 但遗憾的是不是全部)
Simply, there is nothing in that code that would require boxing. There are scenarios where boxing is unavoidable, and there are also additional opcodes for bridging the gap between value/ref types (
constrained
) in some cases.But not in this case; no actual boxing required (the JIT can remove a few box-like cases - but not all, sadly)