-1

如果对象是不可变的(我自己实现的对象),我应该使用 Length 属性还是只读变量?如果对象具有 Length 作为属性,它会在 for 循环中失去一些性能。

for (int i = 0; i < myObject.Length; i++) // Length is readonly variable
{
    // some code
}

和:

int len = myObject.Length; // Length is a property

for (int i = 0; i < len; i++)
{
    // some code
}

你有什么建议?

4

3 回答 3

3

在这样的样本中,这并不重要。JIT 不插入简单的可能性get非常低。即使get没有内联,额外的函数调用也不会成为非常简单的代码之外的性能瓶颈。

为了说明我的意思,我在发布模式下运行了以下命令(如果你让它调试它会以不同的方式工作)。

private int Length { get; set; }
private int _length;
void Run()
{
    Length = int.MaxValue;
    _length = int.MaxValue;
    var watch = new Stopwatch();
    watch.Start();
    for (int i = 0; i < Length; i++)
    {
    }
    watch.Stop();
    Console.WriteLine("Elapsed: {0}ms", watch.ElapsedMilliseconds);
    watch.Restart();
    for (int i = 0; i < _length; i++)
    {
    }
    watch.Stop();
    Console.WriteLine("Elapsed: {0}ms", watch.ElapsedMilliseconds);
}

我运行了 10 次,得到以下平均值:Property 为 743 ms,Variable 为 740 ms。这种差异可能只是因为我的机器上发生的尝试次数和其他事情很少。

现在,如果您通过属性关闭内联,您将获得时间差异:属性为 4577 毫秒,变量为 775 毫秒。现在这听起来差别很大(总时间的 6 倍),但请记住我的循环条件:20 亿次迭代。这意味着每次操作的差异大约为 2 ns。换句话说,大约 4 个时钟周期,除了最极端的性能场景外,还不足以担心。

于 2013-04-19T19:14:43.507 回答
1

除非您在这里有一些非常大的特殊数据集,因此您希望对循环进行大量迭代,否则属性和变量之间的差异可能可以忽略不计。

简单的选择是使用变量。使用属性将为您带来额外的好处,即以后能够在不更改类签名的情况下修改其行为(例如,如果您想以某种新方式计算长度)。

另一个相关的好处可能是能够私下设置属性(如果需要,可以在以后更改),但只能公开阅读。

我想我会因为这些原因去买房。无论如何,我不会仅根据对性能的预期影响做出此选择。

于 2013-04-19T19:07:48.033 回答
0

将临时变量更改为查询是一个非常标准的重构。换句话说,强烈建议如果属性调用非常快,那么您不应该创建临时变量。它被称为“replaceTempWithQuery”。这是一个简介:

http://www.refactoring.com/catalog/replaceTempWithQuery.html

我会向所有从事编程的人强烈推荐《重构》这本书。

添加为编辑:我对此表示反对,但过早的优化确实是要避免的 - 如果它产生非常明显的问题,我只会建议使用临时查询修复。

Donald Knuth 的一句名言:“我们应该忘记小的效率,比如大约 97% 的时间:过早的优化是万恶之源”。无论如何,这是一个选择问题,除非您的代码有很多维护者。然后,维护时间通常会对您的优化/设计选择产生重大影响。

于 2013-04-14T05:13:17.827 回答