c# - 将结构转换为对象以进行空值比较不会导致装箱吗?

标签 c# performance casting nullable boxing

我在做一些基准测试时遇到了这个问题。

bool b;
MyStruct s;
for (int i = 0; i < 10000000; i++)
{
    b = (object)s == null;
}

Debug: 200 ms

Release: 5 ms

bool b;
MyStruct? s = null;
for (int i = 0; i < 10000000; i++)
{
    b = (object)s == null;
}

Debug: 800 ms

Release: 800 ms

我可以理解这个结果,因为将可为空的结构转换为 object 会为我提供该结构的盒装类型。 但为什么将 struct s 转换为 object 进行空值比较(如第一种方法)不会产生相同的性能? 是吗?编译器正在优化返回 false 的调用,因为结构不能为 null?

最佳答案

是的,编译器正在优化它。

它知道结构永远不会为空,因此将它转换为对象的结果永远不会为空 - 因此它只会在第一个示例中将 b 设置为 false。事实上,如果您使用 Resharper,它会警告您表达式始终为假。

当然对于第二个,可空对象可以为空,因此它必须进行检查。

(您也可以使用 Reflector 检查编译器生成的 IL 代码来验证这一点。)

原始测试代码不好,因为编译器知道可空结构将始终为空,因此也会优化该循环。不仅如此,在发布版本中,编译器意识到未使用 b 并优化了整个循环。

为了防止这种情况,并展示在更真实的代码中会发生什么,像这样测试它:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            bool b = true;
            MyStruct? s1 = getNullableStruct();
            Stopwatch sw = Stopwatch.StartNew();

            for (int i = 0; i < 10000000; i++)
            {
                b &= (object)s1 == null; // Note: Redundant cast to object.
            }

            Console.WriteLine(sw.Elapsed);

            MyStruct s2 = getStruct();
            sw.Restart();

            for (int i = 0; i < 10000000; i++)
            {
                b &= (object)s2 == null;
            }

            Console.WriteLine(sw.Elapsed);
        }

        private static MyStruct? getNullableStruct()
        {
            return null;
        }

        private static MyStruct getStruct()
        {
            return new MyStruct();
        }
    }

    public struct MyStruct {}
}

关于c# - 将结构转换为对象以进行空值比较不会导致装箱吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16035505/

相关文章:

c# - 在 WPF 中使用 BackgroundWorker 更新 UI

c# - 将 It.IsAny<int>() 和 It.IsAny<int>() 的值传递给方法设置有什么区别

java - Scala 中隐藏的性能成本?

c# - c#中的整数数学

c# - 转换为原始类型并用作参数?

c# - 在 C# 中对这种行为的解释是什么

c# - 代码如何在 WebService 中运行?

javascript - 在 javascript 中,访问 'window.Math' 比访问没有 'Math' 的 'window.' 对象慢还是快?

c# - IEnumerable 在使用后是否存储对象

c - 将 int 和 const int 转换为 float 时的不同结果