代码之家  ›  专栏  ›  技术社区  ›  Toshi

检查list<t>是否为空时空合并运算符的性能

c#
  •  2
  • Toshi  · 技术社区  · 6 年前

    我有一个 List<int> 它从方法中获取其值

    List<int> items = GetIntegerStuff();
    

    所以避免空引用异常的当前代码如下所示

    if (items == null)
    {
        items = new List<int>();
    }
    

    我之所以改成这样是因为我喜欢短代码——但我的高级开发人员说这不好,因为如果有项目(大约占所有请求的90%),就会分配整个列表,这对性能不利。这是真的吗?

    items = items ?? new List<int>();
    
    2 回复  |  直到 6 年前
        1
  •  3
  •   MineR    6 年前

    在您使用它的方式上,两者在性能上完全相同,因为它们编译成完全相同的东西。

    测试代码:

    static void NullCoalescing(List<int> a)
    {
        a = a ?? new List<int>();
        Console.WriteLine(a);
    }
    static void IfStatement(List<int> a)
    {
        if(a == null) a = new List<int>();
        Console.WriteLine(a);
    }
    

    编译为:

    C.NullCoalescing(System.Collections.Generic.List`1<Int32>)
        L0000: push rsi
        L0001: sub rsp, 0x20
        L0005: test rcx, rcx
        L0008: jnz L0044
        L000a: mov rcx, 0x7ffb92892a78
        L0014: call 0x7ffb94712540
        L0019: mov rsi, rax
        L001c: mov ecx, 0x1
        L0021: mov edx, 0x43
        L0026: call 0x7ffb9487ff10
        L002b: mov rdx, 0x2966e0ddef8
        L0035: mov rdx, [rdx]
        L0038: lea rcx, [rsi+0x8]
        L003c: call 0x7ffb94713e70
        L0041: mov rcx, rsi
        L0044: call System.Console.WriteLine(System.Object)
        L0049: nop
        L004a: add rsp, 0x20
        L004e: pop rsi
        L004f: ret
    
    C.IfStatement(System.Collections.Generic.List`1<Int32>)
        L0000: push rsi
        L0001: sub rsp, 0x20
        L0005: test rcx, rcx
        L0008: jnz L0044
        L000a: mov rcx, 0x7ffb92892a78
        L0014: call 0x7ffb94712540
        L0019: mov rsi, rax
        L001c: mov ecx, 0x1
        L0021: mov edx, 0x43
        L0026: call 0x7ffb9487ff10
        L002b: mov rdx, 0x2966e0ddef8
        L0035: mov rdx, [rdx]
        L0038: lea rcx, [rsi+0x8]
        L003c: call 0x7ffb94713e70
        L0041: mov rcx, rsi
        L0044: call System.Console.WriteLine(System.Object)
        L0049: nop
        L004a: add rsp, 0x20
        L004e: pop rsi
        L004f: ret
    

    如您所见,它们的编译完全相同。

    此处查看:

    https://sharplab.io/#v2:EYLgHgbALANALiAhgZwLYB8ACAGABJgRgG4BYAKB3wKlIoGZ8AmXAYVwG9zzceqJ8ouAHIBXADZiWAe0RiApsgDGASwB2AcwAUAGWXI4AHjVwAfLkQBKbr05le987gC8jgPyvcquQHdcu/UaqppoWtA68hACcmpZhvAC+1jyE/JiCAJIAZgDKcIhwcqhyQTp6hsZmlkkc1fbKmTHOLqriYhaOzT5+ZYHBobURBNGx1Ylk8UA

        2
  •  1
  •   Marco Salerno    6 年前

    以下是可能的方法:

    //APPROACH 1
    List<int> items = GetIntegerStuff();
    if (items == null)
    {
        items = new List<int>();
    }
    
    //APPROACH 2
    List<int> items = GetIntegerStuff() ?? new List<int>();
    
    //APPROACH 3
    List<int> items = GetIntegerStuff();
    items = items ?? new List<int>();
    
    //APPROACH 4
    List<int> items = GetIntegerStuff();
    items = items == null ? new List<int>() : items;
    

    我会选2号,从我的观点来看,它是最干净的。


    为了完整起见,有些场景中可以找到类似的内容:

    class Program
    {
        private static List<int> _items = new List<int>();
    
        private static List<int> Items
        {
            get
            {
                return _items;
            }
    
            set
            {
                _items = value ?? new List<int>();
            }
        }
    
        static void Main(string[] args)
        {
            //APPROACH 5
            Items = GetIntegerStuff();
        }
    
        private static Random Random = new Random();
        private static List<int> GetIntegerStuff()
        {
            switch (Random.Next(0, 2))
            {
                case 0:
                    return null;
                    break;
                default:
                    return new List<int>();
                    break;
            }
        }
    }
    

    这对表演有害吗?

    List<int> items = GetIntegerStuff();
    items = items ?? new List<int>();
    

    不,但它实际上会执行更多有关以下方面的指令:

    List<int> items = GetIntegerStuff();
    if (items == null)
    {
        items = new List<int>();
    }
    

    List<int> items = GetIntegerStuff() ?? new List<int>();