我正在扩展的方法,只适用于参照类型。我认为,然而,它目前是拳击和拆箱的价值。我如何可以避免这种情况?

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
有帮助吗?

解决方案

这不是拳击。当你认为它的的拳击?如果是因为你已经看过了IL围绕“==”,不要让它愚弄你 - JIT变来决定在这里做什么。它具有产生不同的本机代码对于每个(TTResult)一对的机会。实际上,代码将所有引用类型共享,并且值类型不同。所以,你会结束:

T = string, TResult = int (native code #1)
T = Stream, TResult = byte (native code #2)
T = string, TResult = byte (native code #2)
T = Stream, TResult = string (native code #3)

说了这么多,如果你想限制你的扩展方法来引用类型,这样做的:

public static TResult GetOrDefaultIfNull<T, TResult>
    (this T obj, Func<T, TResult> getValue, TResult defaultValue)
    where T : class

有仍然会处于一个IL框,但不要担心 - 实际上不会发生拳。毕竟,什么的可能的加框?你提供参考,而自己从来没有盒装的引用 - 只有值类型的值被装箱

其他提示

简单地说,没有什么代码,将需要拳击。还有 方案的拳击是不可避免的,也有额外的操作码为之间的差距值/ref类型(constrained)在某些情况下。

但不是在这种情况;没有 实际 拳击所需要(JIT可以删除的几个箱状的情况下-但并不是所有的,可悲的是)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top