在构造函数中将整数字段/属性分配为零

时间:2010-11-03 16:51:57

标签: c#

在最近的代码审查期间,一位同事建议,对于具有4个int属性的类,在构造函数中将每个属性赋值为零将导致性能损失。

例如,

    public Example()
    {
        this.major = 0;
        this.minor = 0;
        this.revision = 0;
        this.build = 0;
    }

他的观点是,这是多余的,因为默认情况下它们将被设置为零,并且您通过两次基本上执行相同的任务来引入开销。我的观点是,如果一个存在,并且这更可读(有几个构造函数),性能命中可以忽略不计,因为调用此构造函数后对象状态的意图非常清楚。

你怎么看?这里有值得关注的性能提升吗?

8 个答案:

答案 0 :(得分:6)

不,没有。编译器将优化这些操作;相同的任务不会执行两次。你的同事错了。

[根据总是优秀的Jon Skeet的输入进行编辑]

编译器应该优化操作,但显然它们没有完全优化;然而,优化增益完全可以忽略不计,并且赋值具有如此明确的好处是好的。你的同事可能不是完全错误的,但他们专注于一个完全无关紧要的优化。

答案 1 :(得分:5)

我不相信它们是相同的操作,并且 是性能差异。这是一个显示它的微基准测试:

using System;
using System.Diagnostics;

class With
{
    int x;

    public With()
    {
        x = 0;
    }
}


class Without
{
    int x;

    public Without()
    {
    }
}


class Test
{
    static void Main(string[] args)
    {
        int iterations = int.Parse(args[0]);
        Stopwatch sw = Stopwatch.StartNew();
        if (args[1] == "with")
        {
            for (int i = 0; i < iterations; i++)
            {
                new With();
            }
        }
        else
        {
            for (int i = 0; i < iterations; i++)
            {
                new Without();
            }
        }
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);
    }
}

结果:

c:\Users\Jon\Test>test 1000000000 with
8427

c:\Users\Jon\Test>test 1000000000 without
881

c:\Users\Jon\Test>test 1000000000 with
7568

c:\Users\Jon\Test>test 1000000000 without
819

现在,这会让我改变代码吗?绝对不。首先编写最易读的代码。 如果,通过作业更具可读性,请将作业保留在那里。即使微基准测试显示它有成本,但在执行任何真正的工作的情况下,这仍然是一个小成本。即使比例差异很大,它仍然会在“慢”路线中在8秒内创建十亿个实例。我的猜测是,对于完全空的构造函数实际上存在某种优化,直接链接到完全空的object()构造函数。分配给两个字段和仅分配给一个字段之间的区别要小得多。

就编译器无法优化它而言,请记住基础构造函数可以通过反射或虚拟方法调用来修改值。编译器可能可能注意到这些,但这似乎是一种奇怪的优化。

答案 2 :(得分:4)

我的理解是通过简单且非常快速的内存擦除将对象内存清零。但是,这些明确的分配将需要额外的IL。实际上,有些工具会发现您分配了默认值(在字段初始化程序中)并建议不要使用它。

所以我会说:不要这样做 - 它可能略微更慢。但不是很多。总之,我认为你的朋友是正确的。

不幸的是,我现在正在移动设备上,没有正确的工具来证明它。

答案 3 :(得分:3)

您应该专注于代码清晰度,这是最重要的事情。如果性能成为问题,那么衡量性能,看看你的瓶颈是什么,并改进它们。当理解代码更容易理解时,花费这么多时间来担心性能是不值得的。

答案 4 :(得分:1)

您可以直接将它们初始化为字段:

public int number = 0;

并且也很清楚。

答案 5 :(得分:1)

更重要的问题是:是否真的有可读性?如果维护代码的人已经知道int被分配为零,那么这只是他们需要解析的一些代码。也许代码会更清晰,没有什么都不做的行。

答案 6 :(得分:1)

事实上,我在构造函数中使用赋值,只是为了可读性,并标记'我不忘记初始化那些'意图。依赖默认行为往往会混淆其他开发人员。

答案 7 :(得分:0)

我认为你不应该关心性能损失,通常还有很多其他地方可以优化程序。另一方面,我没有看到在构造函数中指定这些值有任何好处,因为无论如何它们都将设置为0.