~최근에 다른 언어를 다루지 않아서 그렇게 느끼는 거일수도 있지만~ C#으로 업무를 하다 보면 간혹 “왜 안되지?”하는 부분들이 있다.
C# Const가 그런 것 중 하나였는데 정리를 해두면 좋을 것 같아서 정리를 하였다.
문제를 인식하다
싱글톤 인스턴스를 통해 class 상수 멤버 변수에 접근하려고 했는데 접근이 되지 않았다.
문제 상황을 코드로 봐보자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class SingleTon
{
static SingleTon _instance = null;
public static SingleTon Instance
{
get
{
return _instance ??= new SingleTon();
}
}
private SingleTon() { }
public const string _constData = "const Data";
}
static void Main(string[] args)
{
Console.WriteLine(SingleTon.Instance._constData);
}
코드를 작성하면 컴파일 에러를 확인할 수 있다.
원인
왜 그런가 검색을 해보았는데
원인은 C#에서 상수(==Const)는 정적 멤버로 취급하지만 정적 한정자(== static)을 선언을 허용하지 않기 때문이다.
해결 방법
해결 방법은 여러 가지 방법이 있다.
1. 정적 멤버처럼 사용하기
상수가 정적 멤버로 취급되기 때문에 기본적으로 정적 멤버와 동일하게 사용이 가능하다.
1
2
// 상수 _constData는 정적 멤버이다.
Console.WriteLine(SingleTon._constData);
2. Getter 사용하기
상수 데이터를 외부에 노출시키지 않고 싶을 때는 Getter 프로퍼티를 사용하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class SingleTon
{
static SingleTon _instance = null;
public static SingleTon Instance
{
get
{
return _instance ??= new SingleTon();
}
}
private SingleTon() { }
const string _constData = "const Data";
// 상수 _constData에 대한 Getter Property 생성
public string GetConstData => _constData;
}
static void Main(string[] args)
{
Console.WriteLine(SingleTon.Instance.GetConstData);
}
3. readonly 키워드 사용하기
readonly는 정적 멤버로 취급하지 않기 때문에 싱글톤 인스턴스를 통해 접근할 수 있다.
C#에는 const와 동일한 기능을 하는 readonly 키워드가 존재한다.
readonly는 const와 다르게 선언에서 뿐만 아니라 생성자에서도 값을 수정할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class SingleTon
{
// 선언과 동시에 초기화 가능
public readonly string _readonlyData = "readonly Data";
/**
* 생성자에서도 초기화가 가능하다
*
* 생성자에서 변수를 받아 readonly 멤버 변수에 값을 할당할 수 있는 것으로 보아
* readonly는 런타임 상수에 사용될 수 있음을 알 수 있다.
*/
public SingleTon(string value)
{
_readonlyData = value;
}
// "CS0191" 컴파일 에러!! -> 읽기 전용 필드에는 할당할 수 없습니다.
public void SetData(string value)
{
_readonlyData = value;
}
}
static void Main(string[] args)
{
// 컴파일 에러가 발생하지 않음
Console.WriteLine(SingleTon.Instance._readonlyData);
}