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

时间:2010-03-05 17:23:53

标签: c# foreach verbosity

在以下示例中:

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

哪种编码方式更好?

第一个例子:

using System;
using System.Collections.Generic;

namespace TestForeach23434
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> names = new List<string> { "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<string> names = new List<string> { "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();
        }
    }
}

12 个答案:

答案 0 :(得分:45)

第二种形式不再浪费 - 它只是更好。

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

(注意通常这没有任何行为差异,但如果变量是由lambda表达式或匿名方法捕获的,那就不是真的。)

答案 1 :(得分:18)

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

这提供了许多好处:

  1. 重构更容易,因为当变量已经在同一范围内时,提取方法会更简单。
  2. 变量用法更清晰,这将带来更可靠的代码。
  3. 唯一的(潜在的)缺点是额外的变量声明 - 但是,JIT倾向于优化这个问题,所以这是我在实际工作中不必担心的。

    这是一个例外:

    如果您的变量将添加大量GC压力,,如果可以通过foreach / for循环重用相同的对象实例来避免这种情况,如果GC压力导致测量的性能问题,我将其提升到外部范围。

答案 2 :(得分:5)

这些都是浪费和冗长的。

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

</tongueincheek>

答案 3 :(得分:2)

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

我自己的理念很简单:

优化以便于理解。

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

答案 4 :(得分:1)

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

也许您可以发布真实问题而不是示例?

答案 8 :(得分:0)

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

答案 9 :(得分:0)

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

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

答案 10 :(得分:0)

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

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

答案 11 :(得分:-1)

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

第一次需要时声明它