C# 检查if List<;时空合并运算符的性能;T>;是空的

C# 检查if List<;时空合并运算符的性能;T>;是空的,c#,C#,我有一个列表,它从一个方法获取它的值 List<int> items = GetIntegerStuff(); List items=GetIntegerStuff(); 因此,当前避免NullReference异常的代码如下所示 if (items == null) { items = new List<int>(); } if(items==null) { 项目=新列表(); } 我把它改成这样是因为我喜欢短代码——但我的高级开发人员说这不好,因为如果

我有一个
列表
,它从一个方法获取它的值

List<int> items = GetIntegerStuff();
List items=GetIntegerStuff();
因此,当前避免NullReference异常的代码如下所示

if (items == null)
{
    items = new List<int>();
}
if(items==null)
{
项目=新列表();
}
我把它改成这样是因为我喜欢短代码——但我的高级开发人员说这不好,因为如果有项目(大约90%的请求发生),整个列表都会被分配,这对性能不利。这是真的吗

items = items ?? new List<int>();
items=项目??新列表();

以下是可能的方法:

//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;
//方法1
List items=GetIntegerStuff();
if(items==null)
{
项目=新列表();
}
//方法2
列表项=GetIntegerStuff()??新列表();
//方法3
List items=GetIntegerStuff();
项目=项目??新列表();
//方法4
List items=GetIntegerStuff();
items=items==null?新列表():项目;
我会选择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;
        }
    }
}
类程序
{
私有静态列表_items=新列表();
私有静态列表项
{
收到
{
退货(物品);;
}
设置
{
_项目=值??新列表();
}
}
静态void Main(字符串[]参数)
{
//方法5
Items=GetIntegerStuff();
}
私有静态随机=新随机();
私有静态列表GetIntegerStuff()
{
开关(随机。下一个(0,2))
{
案例0:
返回null;
打破
违约:
返回新列表();
打破
}
}
}

这对性能有害吗?

List<int> items = GetIntegerStuff();
items = items ?? new List<int>();
List items=GetIntegerStuff();
项目=项目??新列表();
不,但它实际上会执行更多关于以下方面的指令:

List<int> items = GetIntegerStuff();
if (items == null)
{
    items = new List<int>();
}
List items=GetIntegerStuff();
if(items==null)
{
项目=新列表();
}

List items=GetIntegerStuff()??新列表();

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

测试代码:

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);
}
静态无效合并(列表a)
{
a=一个??新列表();
控制台写入线(a);
}
静态void语句(列表a)
{
如果(a==null)a=newlist();
控制台写入线(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
C.NullCoalescing(System.Collections.Generic.List`1)
L0000:推式rsi
L0001:子rsp,0x20
L0005:测试rcx,rcx
L0008:jnz L0044
L000a:mov rcx,0x7ffb92892a78
L0014:调用0x7ffb94712540
L0019:mov rsi,rax
L001c:mov ecx,0x1
L0021:mov edx,0x43
L0026:呼叫0x7ffb9487ff10
L002b:mov rdx,0x2966e0ddef8
L0035:mov rdx[rdx]
L0038:lea rcx[rsi+0x8]
L003c:调用0x7ffb94713e70
L0041:mov rcx,rsi
L0044:调用System.Console.WriteLine(System.Object)
L0049:没有
L004a:添加rsp,0x20
L004e:pop rsi
L004f:ret
C.IFS语句(系统集合通用列表'1)
L0000:推式rsi
L0001:子rsp,0x20
L0005:测试rcx,rcx
L0008:jnz L0044
L000a:mov rcx,0x7ffb92892a78
L0014:调用0x7ffb94712540
L0019:mov rsi,rax
L001c:mov ecx,0x1
L0021:mov edx,0x43
L0026:呼叫0x7ffb9487ff10
L002b:mov rdx,0x2966e0ddef8
L0035:mov rdx[rdx]
L0038:lea rcx[rsi+0x8]
L003c:调用0x7ffb94713e70
L0041:mov rcx,rsi
L0044:调用System.Console.WriteLine(System.Object)
L0049:没有
L004a:添加rsp,0x20
L004e:pop rsi
L004f:ret
如您所见,它们的编译方式完全相同

在此处查看:


虽然您的作业可行,但您可以将其简化为
List items=GetIntegerStuff()??新列表()将引用分配给本地服务器的成本可以忽略不计。它不会复制列表。真正糟糕的是
GetIntegerStuff
实现:我们几乎应该总是返回一个空集合,而不是
null
您的“高级开发人员”听说过过早优化吗?将变量分配给引用肯定不是性能杀手。性能成本是理论上的,可以忽略不计。@Toshi.NET是一个库。你问的是C语言。如果您想知道您已经编写的代码的性能成本是多少,那么运行代码,亲自看看您已经编写的两个解决方案之间的区别。虽然这显示了执行相同任务的各种方法,但它并没有解决最初的性能问题。
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