在C#中声明局部范围内的常数有什么好处吗?
如果我知道不会改变局部变量的值,那么将其声明为“const”有什么好处吗在C#中声明局部范围内的常数有什么好处吗?,c#,constants,C#,Constants,如果我知道不会改变局部变量的值,那么将其声明为“const”有什么好处吗 谢谢,是的。您将保护代码不被意外更改此变量。将局部变量声明为常量将让编译器知道您的意图,因此您将无法在函数的其他位置更改变量的值。您通常会在整个解决方案中使用常量。但是在本地范围中使用的好处是,您知道范围中的其他地方,您不会更改它。而且,如果其他人正在处理此代码,他们也会知道不要更改它。 这使您的程序更易于维护,因为您只需要维护常量(即使它只是在本地范围内)进一步,您不仅要告诉编译器该值不会更改,还可以根据使用情况快速告诉
谢谢,是的。您将保护代码不被意外更改此变量。将局部变量声明为常量将让编译器知道您的意图,因此您将无法在函数的其他位置更改变量的值。您通常会在整个解决方案中使用常量。但是在本地范围中使用的好处是,您知道范围中的其他地方,您不会更改它。而且,如果其他人正在处理此代码,他们也会知道不要更改它。
这使您的程序更易于维护,因为您只需要维护常量(即使它只是在本地范围内)进一步,您不仅要告诉编译器该值不会更改,还可以根据使用情况快速告诉其他人将查看您的代码。 比如说,
void Foo()
{
const string xpath = "//pattern/node";
new XmlDocument().SelectNodes(xpath);
}
在这种情况下,我认为const声明是没有意义的声明变量const还将允许编译器进行优化-而不是说在堆栈上分配一个int并将其值放在那里,编译器可以直接在代码中使用该值 即:
const int test = 4;
DoSomething(test);
可汇编为
DoSomething(4);
由编译器
编辑:回复“持续传播”,因为评论框有大小限制
使用ildasm检查常量和非常量之间的关系,以进行优化:
代码
int test = 4;
Console.WriteLine(test*2);
编译成
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 11 (0xb)
.maxstack 2
.locals init ([0] int32 test)
IL_0000: ldc.i4.4
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.2
IL_0004: mul
IL_0005: call void [mscorlib]System.Console::WriteLine(int32)
IL_000a: ret
} // end of method Program::Main
当
优化到
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldc.i4.8
IL_0001: call void [mscorlib]System.Console::WriteLine(int32)
IL_0006: ret
} // end of method Program::Main
这是使用2010年发布的优化
我进行了一次搜索,以了解有关常数传播的更多信息,虽然可能,但当前编译器不会像前面提到的那样执行此操作我喜欢在将布尔标志指示器传递给方法时执行此操作:
const bool includeFoo = true;
int result = bar.Compute(10, includeFoo);
对我来说,这比简单的true/false更容易理解,后者需要阅读方法声明来确定其含义。我为其他程序员声明局部常量比其他任何原因都重要。将常量声明为变量有什么好处吗?我喜欢这一点。我注意到微软似乎在其源代码中做到了这一点:base.Compute(10,true/*includefo*/);在C#4.0中,您可以使用命名参数来完成相同的任务(希望参数有合理的名称!)这不是引入它们的目的,但它们的优点是确保您使用正确的名称(在带有许多这样的标志的调用中使用const locals或comments可能会使它们意外混淆)。当我设计自己的接口时,我现在倾向于首先避免使用布尔参数,或者创建不同的公共方法,映射到具有标志的内部方法,或者使用枚举值作为标志。我仍然发现,在与采用布尔或“魔法”参数的API进行交互操作时,此技术很有用(如string.Empty表示“缺少”)。我认为这仍然有价值,原因之一是一致性。如果您总是使用局部scope const规则,那么您就不太可能在更有利的地方忘记它(您在这里使用它不会丢失任何东西,而且也不会有太多额外的键入)。此外,如果此函数将来会变大,您无需担心有人在未实现初始意图的情况下进一步更改范围中的值。即使您不将变量标记为常量,优化器也会轻松确定您的变量是常量,然后生成上述代码。它被称为“持续传播”。@Roubachof我以前没听说过“持续传播”,谢谢你的评论。我在阅读时找到了一个链接,编辑了我的答案;结果是当前的编译器没有做到这一点——也许在将来!(一旦他们在2010年修复了当前的bug!)真的吗?这是一个非常基本的优化技术,我对这个消息感到非常惊讶。干得好!
const bool includeFoo = true;
int result = bar.Compute(10, includeFoo);