使用局部变量有什么好处?

时间:2018-05-04 10:34:50

标签: c# variables properties

我一直在网上看到示例,其中在方法中有一个元素的属性,在使用之前复制到局部变量。例如,像这样的东西(来自微软的StackPanel源代码):

UIElementCollection children = arrangeElement.InternalChildren;

...

for (int i = 0, count = children.Count; i < count; ++i)
{
    UIElement child = (UIElement)children[i];
    if (child == null) { continue; }

    ...
}

任何人都可以向我解释这样做的好处是什么(如果有的话),而不是每次直接访问该属性,如下所示?:

for (int i = 0, count = arrangeElement.InternalChildren.Count; i < count; ++i)
{
    UIElement child = (UIElement)arrangeElement.InternalChildren[i];
    if (child == null) { continue; }

    ...
}

显然,它会在屏幕上保存一些字符,但这并不是理由。另外,我理解为什么我们可能希望使用长时间运行的方法来执行此操作,作为一种缓存形式:

double value = GetValueFromLongRunningMethod();

...

for (int i = 0; i < someCollection.Count; i++) DoSomethingWith(value);

但是我看到这对属性做了很多,并想知道为什么。这是互联网上与虚拟化有关的另一个常见例子:

IItemContainerGenerator generator = this.ItemContainerGenerator;
GeneratorPosition position = generator.GeneratorPositionFromIndex(firstVisibleItemIndex);

为什么要这样做呢?:

GeneratorPosition position = 
    this.ItemContainerGenerator.GeneratorPositionFromIndex(firstVisibleItemIndex);

最后,如果这样做是因为我们可能会缓存长时间运行的方法的结果,那么我们怎么知道需要以这种方式访问​​哪些属性?

3 个答案:

答案 0 :(得分:6)

首先,它避免多次调用.InternalChildren。这个可能是虚拟调用的一个小但明显的减少(因为它在循环中使用),但在某些情况下它可能更重要。在某些情况下,返回集合或数组的属性可能会在每次调用时分配 ; DataRow.ItemArray是一个典型的例子 - 因此每次调用它都是主动有害的。另外一个考虑因素是,即使每次调用它都会返回相同的数组,也会出现JIT魔法,这种魔法恰好会忽略边界检查,但只有当JIT可以看到你正在为整个迭代迭代单个数组时它才会起作用。持续时间。如果你在中间粘贴一个属性访问器:这不会很明显,并且不会发生边界检查删除。如果您手动提升上限,也可能不会发生!

旁注:如果不是一个数组,那么foreach可能通常更好,并且不会由于foreach如何在内部工作,因此引入本地优势。

注意:由于您使用.Count vs .Length,这肯定不是数组,您应该简化为:

foreach(UIElement child = in arrangeElement.InternalChildren) {...}

foreach(var child = in arrangeElement.InternalChildren) {...}

这不仅完全消除了这个问题,而且意味着类型自己的迭代器(可能是一个优化的结构迭代器,或者可能是一个简单的IEnumerable<T>类,例如编译器生成的迭代器块)可以使用。这通常可以更直接地访问内部,从而绕过索引器所需的一些间接和API检查。

答案 1 :(得分:1)

  

为什么要这样做呢?:

GeneratorPosition position =
 this.ItemContainerGenerator.GeneratorPositionFromIndex(firstVisibleItemIndex);

让我们对此非常抽象:

  1. 我们得到了一台发电机。那显然现在是this.ItemContainerGenerator,但这可能会改变。
  2. 我们使用它。这里只有一次,但通常是多次陈述。
  3. 当我们后来决定在其他地方使用该发生器时,用法应该保持不变。

    这个例子太小了,无法令人信服,但这里有一些逻辑可供辨别。

答案 2 :(得分:1)

在某些情况下,如果必须

,这可能会很有成效
  • 调试一些代码,你需要立即看到变量的值
  • 一次使用一个对象执行一些操作,这需要进行转换 - 因此您需要进行一次
  • 有时,当您使用值类型对象时,这种制作本地副本会让您有机会不更改类'property
  • 的值