개발/C#

[Effective C#] const보다는 readonly 사용하기

huiyu 2021. 1. 13. 06:00

const보다는 readonly 사용하기

const - 컴파일 타임 상수, 컴파일 타임에 변수가 값으로 대체된다.
readonly - 런타임 파일 상수, 런타임 타임에 값이 평가된다. 컴파일 타임에 값으로 대체되지 않고 상수에 대한 참조로 컴파일 된다.

//컴파일 타임 상수:
public const int Millennium = 2000;

//런타임 상수:
public static readonly int ThisYear = 2004;

const 예제)

if (myDateTime.Year == Millennium)

위 코드는 컴파일시 아래와 같이 컴파일 된다.

if (myDateTime.Year == 2000)

- const는 컴파일 시점에 값이 대체, readonly의 경우엔 const처럼 값으로 대체되지 않고 상수에 대한 참조로 컴파일된다.
-> 컴파일타임 상수가 빠르긴 하지만 런타임 상수에 비해 유연성이 떨어진다. 컴파일타임 상수는 성능이 매우 중요하고 상수의 값이 절대로 바뀌지 않는 경우에만 제한적으로 사용한다.

readonly의 유연성

- 생성자를 이용한 초기화 : readonly의 경우 생성자를 통해 초기화가 가능하다.

//컴파일되지 않음. readonly를 사용하면 초기화가 가능하다.
private const DateTime classCreation = new DateTime(2000, 1, 1, 0, 0, 0);

-> 클래스내에서 런타임 상수를 정의하는 경우라면 동일 클래스의 인스턴스라 하더라도 인스턴스별로 서로 다른 값을 갖게 구현할 수 있다. 그러나 컴파일타입상수(const)라면 컴파일 시 값이 결정됨으로 모든 인스턴스가 동일한 값을 가질 수밖에 없다.

프로그램 유지보수/호환성

Infrastrucutre 어셈블리 코드

public class UsefulValues
{
  public static readonly int StartValue = 5;
  public const int EndValue = 10;
}

Infastrucutre 사용 코드

for (int i = UsefulValues.StartValue; i < UsefulValues.EndValue; i++)
  Console.WriteLine("value is {0}", i);

[출력]
Value is 5
Value is 6
...
Value is 9

* 위 코드의 Infrastrucutre 어셈블리만 수정.(프로그램 전체 rebulid하지 않음)

public class UsefulValues
{
  public static readonly int StartValue = 105;
  public const int EndValue = 120;
}

 위의 수정으로 105~120까지의 값을 출력할 거라고 예상되지만, 결과는 아무것도 출력되지 않는다. 사용중인 프로그램에서 StartValue는 105, EndValue는 10을 계속 사용중이기 때문이다.
-> const는 컴파일 타임에 값을 대체해버리고, readonly는 런타임 상수이기 때문!
readonly를 사용하면 프로그램 전체를 리빌드하지 않고도 어셈블리의 변경사항을 올바르게 반영할 수 있다.

** 컴파일 타임 상수(const) 값을 수정할 때는 타입의 인터페이스 변경만큼 신중하게 해야 하며, 해당 상수를 참조하는 모든 코드를 재컴파일 해야한다. 런타임파일 상수의 경우 기존값만 변경하여도 기존 응용프로그램과의 코드 호환성이 유지된다.

const

- const는 성능이 빠르다. 상숫값으로 코드를 대체하면 readonly 변수를 통해 값을 참조하는 것보다 빠를 수밖에 없다. 성능과 유연성, 두가지를 비교해서 필요한 경우를 고려하여 구현한다.
- 컴파일 시 필요한 상숫값 : 특성(attribute)의 매개변수, switch/case문의 레이블, enum 상수와 같이 거의 수정이 필요없는 값은 const로 선언한다.

[참고]
EffectiveC# - 아이템2 : const보다는 readonly가 좋다.

728x90
반응형