【问题标题】:Defining Local Variable const vs Class const定义局部变量 const 与类 const
【发布时间】:2011-09-16 09:57:55
【问题描述】:

如果我使用仅在方法中需要的常量,最好是在方法范围内还是在类范围内声明该常量?在方法中声明它是否有更好的性能?如果这是真的,我认为在类范围(文件顶部)定义它们以更改值并更容易重新编译是更标准的。

public class Bob
{
   private const int SomeConst = 100; // declare it here?
   public void MyMethod()
   {
      const int SomeConst = 100; // or declare it here?
      // Do something with SomeConst
   }
}

【问题讨论】:

    标签: c# .net constants jit


    【解决方案1】:

    将常量移到类中没有性能提升。 CLR 足够聪明,可以将常量识别为常量,因此就性能而言,两者是相等的。编译到 IL 时实际发生的情况是,编译器将常量的值作为字面值硬编码到程序中。

    换句话说,常量不是引用的内存位置。它不像一个变量,它更像是一个字面量。常量是在代码中的多个位置同步的文字。所以这取决于你 - 尽管将常量的范围限制在相关的地方是一种更简洁的编程。

    【讨论】:

    • 同意“限制 const 的范围是一种更简洁的编程方式”,不幸的是,大多数 C# 程序员似乎仍然自动为类甚至项目创建一个全局 const,即使它只在一个本地使用方法
    【解决方案2】:

    取决于你是否想在课堂上使用它。顶部声明将在您的整个班级中使用,而另一个仅在 MyMethod 中可用。无论哪种方式,您都不会获得任何性能提升。

    【讨论】:

    • 明白。我试图在我的第一句话中表明这一点。 const 仅在 MyMethod() 范围内需要
    • @Stealth Rabbi: 然后在MyMethod :o) 中声明它
    【解决方案3】:

    这是我为评估场景所做的一个小基准;

    代码:

    using System;
    using System.Diagnostics;
    
    namespace TestVariableScopePerformance
    {
        class Program
        {
            static void Main(string[] args)
            {
                TestClass tc = new TestClass();
                Stopwatch sw = new Stopwatch();
    
                sw.Start();
                tc.MethodGlobal();
                sw.Stop();
    
                Console.WriteLine("Elapsed for MethodGlobal = {0} Minutes {1} Seconds {2} MilliSeconds", sw.Elapsed.Minutes, sw.Elapsed.Seconds, sw.Elapsed.Milliseconds);
                sw.Reset();
    
                sw.Start();
                tc.MethodLocal();
                sw.Stop();
    
                Console.WriteLine("Elapsed for MethodLocal = {0} Minutes {1} Seconds {2} MilliSeconds", sw.Elapsed.Minutes, sw.Elapsed.Seconds, sw.Elapsed.Milliseconds);
    
                Console.WriteLine("Press any key to continue...");
                Console.ReadKey();
            }
    
    
        }
    
        class TestClass
        {
            const int Const1 = 100;
    
            internal void MethodGlobal()
            {
                double temp = 0d;
                for (int i = 0; i < int.MaxValue; i++)
                {
                    temp = (i * Const1);
                }
            }
    
            internal void MethodLocal()
            {
                const int Const2 = 100;
                double temp = 0d;
                for (int i = 0; i < int.MaxValue; i++)
                {
                    temp = (i * Const2);
                }
            }
        }
    }
    

    3次迭代的结果:

    Elapsed for MethodGlobal = 0 Minutes 1 Seconds 285 MilliSeconds
    Elapsed for MethodLocal = 0 Minutes 1 Seconds 1 MilliSeconds
    Press any key to continue...
    
    Elapsed for MethodGlobal = 0 Minutes 1 Seconds 39 MilliSeconds
    Elapsed for MethodLocal = 0 Minutes 1 Seconds 274 MilliSeconds
    Press any key to continue...
    
    Elapsed for MethodGlobal = 0 Minutes 1 Seconds 305 MilliSeconds
    Elapsed for MethodLocal = 0 Minutes 1 Seconds 31 MilliSeconds
    Press any key to continue...
    

    我猜观察结束@jnm2 答案。

    请在您的系统中运行相同的代码,然后告诉我们结果。

    【讨论】:

    • 你做的很好。对 IL 进行逆向工程并准确了解幕后发生的情况也很有帮助。在这种情况下,常量被硬编码为文字值。它们不像变量。
    • 我在 x86 机器上的结果。看起来全局 const 稍微慢一些,但是反转调用(全局之前的本地)显示 Local 需要更多时间。 MethodGlobal 已用 = 0 分 8 秒 MethodLocal 已用 593 毫秒 MethodLocal = 0 分 8 秒 501 毫秒 按任意键继续... MethodGlobal 已用 = 0 分 8 秒 MethodLocal 已用 571 毫秒 = 0 分 8 秒 494 毫秒 按任意键继续的关键... PS - 哎呀,我的盒子里有很多废品。
    • 呃,对于令人讨厌的格式感到抱歉。我不认为我可以选择 cmets。
    • 因此差异约为 1%,即没有差异(尤其是当您考虑到许多不同的因素可能会导致您的机器上存在约 1% 的差异时)。
    【解决方案4】:

    我会把它放在方法本身中。我不喜欢在不需要存在时在范围内徘徊的变量。

    【讨论】:

    • 一个 const 实际上不是一个变量。它更多的是文字的占位符。我认为这可能是一些混乱的来源:-)。
    【解决方案5】:

    我尝试只在我需要的最小范围内定义常量/变量。在这种情况下,如果您仅在 MyMethod 内使用它,则将其留在那里。

    这样就更清楚了,常量/变量适用于何处,并且如果常量在其他地方被引用,也可以省去检查(即使是编译检查)。

    一个例外可能是创建/计算“昂贵”(时间方面)的东西,所以我可能想要定义一个实例或静态字段,所以我只需要计算一次。

    【讨论】:

      【解决方案6】:

      取决于你想在哪里使用它,如果你要在其他方法中使用,请在类中定义它,如果你只在一种方法中使用它,请在你要使用的方法中定义它: )

      【讨论】:

      • 但是在方法范围内定义它是否有性能优势?
      • @stealth-rabbi:这两种方式都没有性能优势。 (见我的回答。)
      猜你喜欢
      • 2018-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多