是否更好的编码实践来定义foreach之外的变量,即使更冗长?

在以下示例中:

  • 一个似乎更冗长但更少浪费资源
  • 第二个是更简洁但更浪费资源(重新定义每个循环的字符串)

哪种编码更好?

第一个例子:

using System; using System.Collections.Generic; namespace TestForeach23434 { class Program { static void Main(string[] args) { List names = new List { "one", "two", "two", "three", "four", "four" }; string test1 = ""; string test2 = ""; string test3 = ""; foreach (var name in names) { test1 = name + "1"; test2 = name + "2"; test3 = name + "3"; Console.WriteLine("{0}, {1}, {2}", test1, test2, test3); } Console.ReadLine(); } } } 

第二个例子:

 using System; using System.Collections.Generic; namespace TestForeach23434 { class Program { static void Main(string[] args) { List names = new List { "one", "two", "two", "three", "four", "four" }; foreach (var name in names) { string test1 = name + "1"; string test2 = name + "2"; string test3 = name + "3"; Console.WriteLine("{0}, {1}, {2}", test1, test2, test3); } Console.ReadLine(); } } } 

第二种forms不再浪费 – 它只是更好。

除非你想在迭代之间保持它们的值,否则在循环外声明变量没有任何好处。

(请注意, 通常这不会产生行为差异,但如果变量是由lambda表达式或匿名方法捕获的,则不是这样。)

就个人而言,我认为最好的做法是尽可能在最严格的范围内声明变量。

这提供了许多好处:

  1. 重构更容易,因为当变量已经在同一范围内时,提取方法更简单。
  2. 变量用法更清晰,这将导致更可靠的代码。

唯一的(潜在的)缺点是额外的变量声明 – 然而,JIT倾向于优化这个问题,因此它是我在实际工作中不必担心的。

一个例外:

如果你的变量将增加很多GC压力, 并且如果通过foreach / for循环重复使用相同的对象实例可以避免这种情况, 并且如果GC压力导致测量的性能问题,我会将其提升到外部范围。

这些都是浪费和冗长的。

 foreach (var name in names) { Console.WriteLine("{0}1, {0}2, {0}3", name); } 

  

根据语言和编译器,它可能相同或不同。 对于C#,我希望得到的代码非常相似。

我自己的理念很简单:

优化以便于理解。

其他任何事情都是过早的优化! 大多数开发中最大的瓶颈是开发人员的时间和注意力。 如果你绝对必须挤出每个最后一个CPU周期,那么一定要这样做,但除非你有一个令人信服的业务需要做或正在编写一个关键组件(公共库,操作系统内核等),你最好等到你可以对已完成的程序进 那时优化一些最昂贵的例程是合理的,在此之前几乎肯定是浪费时间。

我不确定你通过在循环外定义字符串变量获得了什么。 字符串是不可变的,因此它们不会被重用。 无论何时分配给它们,都会创建一个新实例。

我认为这取决于你想要解决的问题。 我喜欢第二个例子,因为你可以一步到位地移动代码。 我喜欢第一个例子,因为它更快,因为更少的堆栈操作,更少的内存碎片,以及更少的对象构造/创建。

我发现循环中的“提升”声明通常是一种更好的长期维护策略。 编译器通常会对性能进行可接受的排序。

就性能而言,它们几乎是相同的(字符串是不可变的),但就可读性而言……我说两者都不是很好。 您可以轻松地在Console.WriteLine中完成所有操作。

也许你可以发布真正的问题而不是一个例子?

我通常将变量声明为与作用域允许的接近使用,在这种情况下,这将是您的第二个示例。 Resharper也倾向于鼓励这种风格。

对于POD类型数据声明最接近第一次使用。 对于任何类似内存分配的类,你应该考虑在任何循环之外声明那些。 字符串几乎肯定会进行某种forms的分配,大多数实现(至少在C ++中)将尽可能重用内存。 基于堆的分配确实非常慢。

我曾经描述过一些C ++代码,其中包含了一个新的数据类。 使用在循环外声明的变量,它比循环内声明的变量快17%。 YMMV在C#所以个人资料表现你可能会对结果感到非常惊讶。

这是我最喜欢的Linq部分,我想它适合这里:

 names.ForEach(x => Console.WriteLine("{0}1, {0}2, {0}3", x)); 

在声明变量时遵循一个简单的规则

在您第一次需要它时声明它