M4N*_*M4N 70 c# resharper coding-style const
每当我在方法中有局部变量时,ReSharper建议将它们转换为常量:
// instead of this:
var s = "some string";
var flags = BindingFlags.Public | BindingFlags.Instance;
// ReSharper suggest to use this:
const string s = "some string";
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
Run Code Online (Sandbox Code Playgroud)
鉴于这些是真正的常量值(而不是变量)我理解ReSharper建议将它们更改为const.
但除此之外,使用const(例如更好的性能)是否有任何其他优势可以证明使用const BindingFlags而不是方便可读的var关键字?
BTW:我刚刚在这里发现了一个类似的问题:Resharper总是建议我创建const字符串而不是字符串,但我认为它更多的是关于类的字段,我的问题是关于局部变量/ consts.
lan*_*ncz 82
如果您尝试将值分配给常量,编译器将抛出错误,从而可能会阻止您意外更改它.
此外,通常使用常量与变量有一个小的性能优势.根据MSDN杂志问答,这与编译到MSIL的方式有关:
现在,无论在代码中引用myInt,而不是必须执行"ldloc.0"来从变量中获取值,MSIL只需加载硬编码到MSIL中的常量值.因此,使用常量通常具有较小的性能和内存优势.但是,为了使用它们,您必须在编译时具有变量的值,并且在编译时对该常量的任何引用,即使它们位于不同的程序集中,也会进行此替换.
如果在编译时知道值,常量肯定是一个有用的工具.如果不这样做,但想确保您的变量只设置一次,则可以使用C#中的readonly关键字(映射到MSIL中的initonly)来指示变量的值只能在构造函数中设置; 在那之后,改变它是一个错误.这通常在字段有助于确定类的标识时使用,并且通常设置为等于构造函数参数.
Dre*_*kes 23
tl; dr用于具有文字值的局部变量,const根本没有任何区别.
你对"内部方法"的区分非常重要.让我们看看它,然后将它与const字段进行比较.
局部变量的唯一好处const是无法重新分配值.
但是const仅限于原始类型(int,, double......)string,这限制了它的适用性.
题外话:C#编译器有一些建议允许更一般的'readonly'本地化概念(这里),这会将这种好处扩展到其他场景.他们可能不会像想到的const,虽然,很可能有这种声明(即不同的关键字let或readonly var或类似的东西).
考虑这两种方法:
private static string LocalVarString()
{
var s = "hello";
return s;
}
private static string LocalConstString()
{
const string s = "hello";
return s;
}
Run Code Online (Sandbox Code Playgroud)
内置Release模式我们看到以下(删节)IL:
.method private hidebysig static string LocalVarString() cil managed
{
ldstr "hello"
ret
}
.method private hidebysig static string LocalConstString() cil managed
{
ldstr "hello"
ret
}
Run Code Online (Sandbox Code Playgroud)
如您所见,它们都产生完全相同的IL.无论当地s是否const有影响.
原始类型也是如此.这是一个使用示例int:
private static int LocalVarInt()
{
var i = 1234;
return i;
}
private static int LocalConstInt()
{
const int i = 1234;
return i;
}
Run Code Online (Sandbox Code Playgroud)
IL再次:
.method private hidebysig static int32 LocalVarInt() cil managed
{
ldc.i4 1234
ret
}
.method private hidebysig static int32 LocalConstInt() cil managed
{
ldc.i4 1234
ret
}
Run Code Online (Sandbox Code Playgroud)
所以我们再次看到没有区别.这里不存在性能或内存差异.唯一的区别是开发人员无法重新分配符号.
将const字段与可变字段进行比较是不同的.必须在运行时读取非const字段.所以你最终得到这样的IL:
// Load a const field
ldc.i4 1234
// Load a non-const field
ldsfld int32 MyProject.MyClass::_myInt
Run Code Online (Sandbox Code Playgroud)
很明显,假设JIT本身不能内联一个常量值,这会导致性能差异.
这里的另一个重要区别是跨程序集共享的公共const字段.如果一个程序集公开const字段,而另一个程序集使用它,则在编译时复制该字段的实际值.这意味着如果更新包含const字段的程序集但不重新编译using程序集,则将使用旧的(可能不正确的)值.
Yet*_*ser 14
根据我的理解,Const值在运行时不存在 - 即以存储在某些内存位置的变量的形式 - 它们在编译时嵌入在MSIL代码中.因此会对性能产生影响.在变量需要这些检查的情况下,不需要更多的运行时间来执行任何内容保存(转换检查/垃圾收集等).