Program Tip

메서드 내에서 변수 대신 const를 사용할 때의 이점

programtip 2020. 11. 1. 18:33
반응형

메서드 내에서 변수 대신 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;

이것이 변수가 아니라 실제로 일정한 값이라는 점을 감안할 때 ReSharper가이를 const로 변경하도록 제안한다는 것을 이해합니다.

하지만 그 외에 const BindingFlags편리하고 읽기 쉬운 var키워드 대신 사용을 정당화하는 const (예 : 더 나은 성능)를 사용할 때 다른 이점이 있습니까?

BTW : 방금 비슷한 질문을 찾았습니다 .Resharper가 항상 string 대신 const string을 만들 것을 제안 했지만 내 질문이 지역 변수 / 상수에 관한 클래스의 필드에 관한 것 같습니다.


상수에 값을 할당하려고하면 컴파일러에서 오류가 발생하여 실수로 값을 변경하는 것을 방지 할 수 있습니다.

또한 일반적으로 상수와 변수를 사용하면 약간의 성능 이점이 있습니다. 이것은 MSDN 매거진 Q & A 에 따라 MSIL로 컴파일되는 방식과 관련이 있습니다 .

이제 코드에서 myInt가 참조되는 모든 곳에서 "ldloc.0"을 수행하여 변수에서 값을 가져 오는 대신 MSIL은 하드 코딩 된 상수 값을 MSIL에로드합니다. 따라서 상수를 사용하면 일반적으로 성능 및 메모리 이점이 작습니다. 그러나이를 사용하려면 컴파일 타임에 변수 값이 있어야하며 컴파일 타임에이 상수에 대한 참조는 다른 어셈블리에 있더라도이 대체가 이루어집니다.

컴파일 타임에 값을 알고 있다면 상수는 확실히 유용한 도구입니다. 그렇지 않지만 변수가 한 번만 설정되도록하려면 C #에서 readonly 키워드 (MSIL에서 initonly에 매핑 됨)를 사용하여 변수 값이 생성자에서만 설정 될 수 있음을 나타낼 수 있습니다. 그 후에 변경하는 것은 오류입니다. 필드가 클래스의 ID를 확인하는 데 도움이 될 때 자주 사용되며 생성자 매개 변수와 동일하게 설정되는 경우가 많습니다.


tl; dr 은 리터럴 값이있는 지역 변수에 const대해 전혀 차이가 없습니다.


"내부 방법"을 구분하는 것은 매우 중요합니다. 그것을보고 const필드 와 비교해 봅시다 .

Const 지역 변수

지역 변수 유일한 이점은 const값을 다시 할당 할 수 없다는 것입니다.

그러나 const기본 유형 (이에 한정되는 int, double...)과 string그 응용을 제한한다.

Digression : 이 이점을 다른 시나리오로 확장하는 '읽기 전용'지역 ( 여기 ) 의보다 일반적인 개념을 허용하는 C # 컴파일러에 대한 제안 이 있습니다. 그것들은 아마도 그렇게 생각되지 않을 것이고 const그러한 선언에 대해 다른 키워드를 가질 것입니다 (즉 let, readonly var또는 이와 비슷한 것).

다음 두 가지 방법을 고려하십시오.

private static string LocalVarString()
{
    var s = "hello";
    return s;
}

private static string LocalConstString()
{
    const string s = "hello";
    return s;
}

내장 Release모드에서는 다음 (요약 된) IL이 표시됩니다.

.method private hidebysig static string LocalVarString() cil managed 
{
    ldstr        "hello"
    ret          
}

.method private hidebysig static string LocalConstString() cil managed 
{
    ldstr        "hello"
    ret          
}

보시다시피 둘 다 똑같은 IL을 생성합니다. 로컬 여부 sIS const여부 아무런 영향을주지 않습니다.

기본 유형도 마찬가지입니다. 다음은 사용하는 예입니다 int.

private static int LocalVarInt()
{
    var i = 1234;
    return i;
}

private static int LocalConstInt()
{
    const int i = 1234;
    return i;
}

그리고 다시 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     
}

다시 한번 우리는 차이가 없습니다. 여기에는 성능이나 메모리 차이가있을 수 없습니다. 유일한 차이점은 개발자가 기호를 다시 할당 할 수 없다는 것입니다.

Const 필드

const필드를 변수 필드와 비교하는 것은 다릅니다. 상수가 아닌 필드 런타임에 읽어야합니다. 따라서 다음과 같이 IL로 끝납니다.

// Load a const field
ldc.i4       1234

// Load a non-const field
ldsfld       int32 MyProject.MyClass::_myInt

JIT가 상수 값 자체를 인라인 할 수 없다고 가정하면 이것이 어떻게 성능 차이를 초래할 수 있는지는 분명합니다.

Another important difference here is for public const fields that are shared across assemblies. If one assembly exposes a const field, and another uses it, then the actual value of that field is copied at compile time. This means that if the assembly containing the const field is updated but the using assembly is not re-compiled, then the old (and possibly incorrect) value will be used.

Const expressions

Consider these two declarations:

const int i = 1 + 2;
int i = 1 + 2;

For the const form, the addition must be computed at compile time, meaning the number 3 is kept in the IL.

For the non-const form, the compiler is free to emit the addition operation in the IL, though the JIT would almost certainly apply a basic constant folding optimisation so the generated machine code would be identical.

The C# 7.3 compiler emits the ldc.i4.3 opcode for both of the above expressions.


As per my understanding Const values do not exist at run time - i.e. in form of a variable stored in some memory location - they are embeded in MSIL code at compile time . And hence would have an impact on performance. More over run-time would not be required to perform any house keeping (conversion checks / garbage collection etc) on them as well, where as variables require these checks.


const is a compile time constant - that means all your code that is using the const variable is compiled to contain the constant expression the const variable contains - the emitted IL will contain that constant value itself.

This means the memory footprint is smaller for your method because the constant does not require any memory to be allocated at runtime.


Besides the small performance improvement, when you declare a constant you are explicitly enforcing two rules on yourself and other developers who will use your code

  1. I have to initialize it with a value right now i can't to do it any place else.
  2. I cannot change its value anywhere.

In code its all about readability and communication.


A const value is also 'shared' between all instances of an object. It could result in lower memory usage as well.

As an example:

public class NonStatic
{
    int one = 1;
    int two = 2;
    int three = 3;
    int four = 4;
    int five = 5;
    int six = 6;
    int seven = 7;
    int eight = 8;
    int nine = 9;
    int ten = 10;        
}

public class Static
{
    static int one = 1;
    static int two = 2;
    static int three = 3;
    static int four = 4;
    static int five = 5;
    static int six = 6;
    static int seven = 7;
    static int eight = 8;
    static int nine = 9;
    static int ten = 10;
}

Memory consumption is tricky in .Net and I won't pretend to understand the finer details of it, but if you instantiate a list with a million 'Static' it is likely to use considerably less memory than if you do not.

    static void Main(string[] args)
    {
        var maxSize = 1000000;
        var items = new List<NonStatic>();
        //var items = new List<Static>();

        for (var i=0;i<maxSize;i++)
        {
            items.Add(new NonStatic());
            //items.Add(new Static());
        }

        Console.WriteLine(System.Diagnostics.Process.GetCurrentProcess().WorkingSet64);
        Console.Read();
    }

When using 'NonStatic' the working set is 69,398,528 compared to only 32,423,936 when using static.


The const keyword tells the compiler that it can be fully evaluated at compile time. There is a performance & memory advantage to this, but it is small.


Constants in C# provide a named location in memory to store a data value. It means that the value of the variable will be known in compile time and will be stored in a single place.

When you declare it, it is kind of 'hardcoded' in the Microsoft Intermediate Language (MSIL).

Although a little, it can improve the performance of your code. If I'm declaring a variable, and I can make it a const, I always do it. Not only because it can improve performance, but also because that's the idea of constants. Otherwise, why do they exist?

Reflector can be really useful in situations like this one. Try declaring a variable and then make it a constant, and see what code is generated in IL. Then all you need to do is see the difference in the instructions, and see what those instructions mean.

참고URL : https://stackoverflow.com/questions/5833912/advantages-of-using-const-instead-of-variables-inside-methods

반응형