Computer >> 컴퓨터 >  >> 프로그래밍 >> C#

C# const와 readonly 키워드 차이점 완벽 정리

C#에서 constreadonly 키워드는 모두 한 번 선언되면 수정할 수 없는 불변(immutable) 값을 정의하는 데 사용됩니다. 하지만 두 키워드 사이에는 몇 가지 중요한 차이점이 존재합니다.

const란?

const 한정자는 컴파일 시점에 값이 확정되며 이후 변경되지 않는 상수를 선언합니다. C#에서는 기본 제공 타입(built-in types)만 const로 지정할 수 있으며, 클래스나 구조체 같은 사용자 정의 타입은 const로 선언할 수 없습니다. 또한 메서드, 프로퍼티, 이벤트 같은 클래스 멤버에도 const를 적용할 수 없습니다.

const 상수는 반드시 선언과 동시에 초기화해야 합니다.

class Period{
    public const int hours = 12;
    public const int minutes = 60;
}

const는 private, public, protected, protected internal, private protected 등 모든 접근 제한자와 함께 사용할 수 있습니다.

또한 const는 암묵적으로 static처럼 동작합니다. 즉, 상수의 값은 클래스의 모든 인스턴스에서 동일합니다. 별도로 static 키워드를 붙일 필요가 없으며, 인스턴스 변수를 통해서는 접근할 수 없고 반드시 클래스 이름을 통해 접근해야 합니다.

readonly란?

readonly로 표시된 필드는 선언 시점 또는 생성자 내부에서만 값을 할당할 수 있습니다. 클래스 인스턴스가 생성된 이후에는 readonly 필드를 수정할 수 없습니다.

필드가 값 타입(value type)이라면 readonly를 붙이는 순간 해당 필드는 불변이 됩니다. 반면 참조 타입(reference type)인 경우에는 변수가 참조하는 객체의 내부 데이터는 여전히 변경할 수 있습니다. 다만 그 참조 자체를 새로운 객체를 가리키도록 바꾸는 것은 불가능합니다.

class Person{
    private readonly string _title;
    private readonly string _skill;
    public Person(string title, string skill){
        _title = title;
        _skill = skill;
    }
}

readonly 필드는 필드 선언부와 각 생성자에서 여러 번 할당될 수 있으며, 어떤 생성자가 사용되었는지에 따라 서로 다른 값을 가질 수도 있다는 점이 특징입니다.

어셈블리 관점에서의 핵심 차이

두 키워드의 가장 중요한 차이점은 한 어셈블리(assembly)에 선언된 const 또는 readonly 필드가 다른 어셈블리에서 사용될 때 나타납니다.

  • const의 경우: 마치 찾아 바꾸기(find-replace)처럼 동작합니다. 상수 값이 두 번째 어셈블리의 IL(중간 언어) 코드에 직접 '구워져(baked into)' 들어갑니다. 따라서 상수 값을 업데이트하더라도 두 번째 어셈블리를 다시 컴파일하기 전까지는 이전 값이 유지됩니다.

  • readonly의 경우: 메모리 위치에 대한 참조처럼 동작합니다. 값이 두 번째 어셈블리의 IL 코드에 포함되지 않기 때문에, 메모리 위치의 값이 업데이트되면 두 번째 어셈블리는 재컴파일 없이도 새로운 값을 얻게 됩니다. 즉, readonly 필드를 수정하면 첫 번째 어셈블리만 다시 컴파일하면 되고, 사용자 측 어셈블리는 재컴파일할 필요가 없습니다.

예제 코드

using System;
class Program{
    static void Main(){
        Console.WriteLine(Period.HOURS);
        var person = new Person("John", "Programmer");
        person.Print();
    }
}
class Period{
    public const int HOURS = 12;
    public const int MINUTES = 60;
}
class Person{
    private readonly string _title;
    private readonly string _skill;
    public Person(string title, string skill){
        _title = title;
        _skill = skill;
    }
    public void Change(string skill){
        // 오류: readonly 필드에는 할당할 수 없습니다.
        // this._skill = skill;
    }
    public void Print(){
        Console.WriteLine($"{_title}: {_skill}");
    }
}

실행 결과

12
John: Programmer

정리

컴파일 시점에 값이 확정되고 절대 변하지 않는 값이라면 const를, 런타임에 결정되거나 생성자를 통해 초기화해야 하는 값이라면 readonly를 사용하는 것이 좋습니다. 특히 라이브러리를 배포하는 경우, const 값 변경 시 참조하는 모든 어셈블리의 재컴파일이 필요하다는 점을 고려하면 readonly가 더 유연한 선택이 될 수 있습니다.