代码之家  ›  专栏  ›  技术社区  ›  Robert H.

扩展System.Object时如何避免装箱/拆箱?

  •  3
  • Robert H.  · 技术社区  · 16 年前

    我正在研究一个只适用于引用类型的扩展方法。然而,我认为,它目前正在装箱和拆箱的价值。我怎样才能避免这种情况?

    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
    
    2 回复  |  直到 16 年前
        1
  •  4
  •   John K    15 年前

    那不是拳击。你觉得它在哪里 T , TResult )配对。实际上,所有引用类型的代码都是共享的,而值类型的代码则不同。所以你最终会得到:

    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中仍然会有一个盒子,但是不要担心-实际上不会发生拳击。毕竟,什么

        2
  •  2
  •   Marc Gravell    16 年前

    简单地说,代码中没有任何东西需要装箱。在那里 constrained )在某些情况下。

    但不是在这种情况下;不 实际的 需要装箱(JIT可以移除一些类似箱子的案例,但遗憾的是,不是全部)

    推荐文章