Menu

C# 변수: var, const, readonly, 범위, 명명 규칙

C#에서 변수를 선언하고 값을 대입하는 방법, var를 쓰면 좋을 때와 아닐 때, 범위가 동작하는 방식, const와 readonly와 static readonly의 차이, 명명 규칙, 할당되지 않은 변수 오류를 알아봅니다.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

변수는 타입이 정해진, 이름 붙은 저장 공간입니다. C#에서는 타입과 이름으로 변수를 선언하고, 원하면 같은 문장에서 값을 줍니다. 타입은 이후에 절대 바뀌지 않습니다. int 변수는 존재하는 동안 계속 정수를 담습니다.

출력:

Priya bought 5 items for 20.25
10

잘못된 타입의 값을 대입하면 컴파일 오류입니다. quantity = "five";는 CS0029(cannot implicitly convert type 'string' to 'int')로 실패합니다. 타입 간 변환은 명시적으로 합니다. 형 변환을 참고하세요.

var: 컴파일러가 타입을 추론하게 하기

var는 초기화 식으로부터 타입이 추론되는 지역 변수를 선언합니다. 동적 타입이 아닙니다. 타입을 직접 쓴 것과 똑같이 컴파일 시점에 고정됩니다.

출력:

String
Int32
Decimal
Double
List`1

var에는 세 가지 규칙이 있습니다. 지역 변수에만 쓸 수 있습니다(필드나 매개변수에는 안 됩니다). 선언에서 초기화해야 합니다. var x;는 CS0818 오류 "Implicitly-typed variables must be initialized"입니다. 그리고 초기화 식에 타입이 있어야 합니다. null만으로는 타입이 없으므로 var nothing = null;은 컴파일되지 않습니다.

언제 쓸지는 팀 스타일의 문제입니다. 보통의 지침은 오른쪽에서 타입이 분명하면 var를 쓰고, 그렇지 않으면 타입을 쓰는 것입니다:

var orders = new List<Order>();         // obvious: var is fine
var reader = new StreamReader(path);    // obvious
decimal discount = CalculateDiscount(); // not obvious: name the type
int count = items.Count();              // makes the intent clear

미묘한 함정이 있습니다. var total = 0;은 total을 int로 만들기 때문에 나중에 2.5를 더하면 실패하고, var price = 10;은 decimal이 아니라 int입니다. 리터럴의 타입이 원하는 타입이 아닐 때는 타입을 쓰거나 접미사(10m, 0.0)를 붙이세요.

범위

지역 변수는 선언된 곳부터 그 변수가 선언된 블록 { }의 끝까지 존재합니다. 루프 헤더나 if 본문에서 선언한 변수는 그 뒤에서 보이지 않습니다.

출력:

high
240

C나 C++와 달리 C#에서는 안쪽 블록이 바깥쪽 블록의 지역 변수와 같은 이름을 선언할 수 없습니다(CS0136 오류). 한 메서드 안에서 이름은 하나의 의미만 가져야 합니다. 형제 관계인 두 블록은 이름을 재사용할 수 있습니다. 두 개의 별도 for 루프가 각각 i를 선언하는 것이 그 예입니다.

확정 할당

지역 변수에는 기본값이 없습니다. 컴파일러는 메서드의 모든 경로를 추적하고, 변수가 대입되기 전에 읽힐 가능성이 있으면 컴파일을 거부합니다:

int discount;
if (isMember)
{
    discount = 10;
}
Console.WriteLine(discount);
// error CS0165: Use of unassigned local variable 'discount'

선언할 때 초기화하거나(int discount = 0;) 모든 분기에서 대입하면(else 추가) 해결됩니다. 필드와 배열 요소는 다릅니다. 이들은 타입의 기본값(0, false, null)으로 자동 설정됩니다.

const: 컴파일 시점 상수

const는 컴파일 시점에 고정되는 값입니다. 상수 식(리터럴, 다른 const, 또는 이들의 산술 연산)으로 초기화해야 하며, 숫자, char, bool, string, 열거형, null만 될 수 있습니다.

출력:

Price in EUR
120.00 EUR
350

const 필드는 암시적으로 static이므로 타입 이름으로 접근하며(Pricing.VatRate), static const라고 쓰면 오류입니다. 컴파일러는 값을 사용하는 모든 곳에 복사합니다. 그래서 const는 실행 시점 비용이 없고, 또 그래서 라이브러리의 public const는 절대 바뀌지 않을 값(일주일의 일수 같은)이어야 합니다.

readonly와 static readonly

readonly 필드는 선언에서나 그 클래스의 생성자에서만 대입할 수 있습니다. 생성이 끝나면 바꿀 수 없습니다. const와 달리 값은 실행 시점에 계산되고, 어떤 타입이든 될 수 있으며, 객체마다 다를 수 있습니다.

출력:

ACC-17 opened 2024-05-02
Launch: 2020-01-15
basic, pro

마지막 줄들이 흔한 오해를 보여 줍니다. readonly는 필드를 보호하지, 필드가 가리키는 객체를 보호하지 않습니다. Plans는 항상 같은 배열을 가리키지만 배열의 요소는 여전히 바뀔 수 있습니다. 정말로 불변인 컬렉션이 필요하면 ReadOnlyCollection<T>나 ImmutableArray<T>를 쓰세요.

세 가지 요약:

constreadonlystatic readonly
값이 정해지는 시점컴파일 시점실행 시점실행 시점
허용 타입숫자, char, bool, string, 열거형, null모든 타입모든 타입
설정 위치선언에서만선언 또는 생성자선언 또는 정적 생성자
객체별인가 공유인가공유(암시적 static)객체별공유
지역 변수가능(const int x = 1;)불가불가

명명 규칙

C# 이름은 대소문자를 구분하며(total과 Total은 다른 변수), 글자나 밑줄로 시작해야 합니다. 거의 모든 C# 코드가 따르는 Microsoft 규칙은 다음과 같습니다:

  • 지역 변수와 매개변수: camelCase(orderCount, unitPrice).
  • 상수, 속성, 메서드, 클래스, public 필드: PascalCase(MaxItems, VatRate).
  • private 필드: 앞에 밑줄을 붙인 _camelCase(_balance). .NET 코드에서 널리 쓰이는 관례입니다.
  • 불리언은 질문처럼 읽히게: isActive, hasDiscount, canRetry.
  • 약어와 헝가리안 접두사(strName, iCount)는 피합니다.

C# 키워드는 이름이 될 수 없지만, 앞에 @를 붙이면 됩니다. var @class = "5B";는 올바른 코드이며, 생성된 코드나 JSON 필드 이름에 가끔 유용합니다.

값 교환과 다중 대입

C# 7부터는 튜플로 한 문장에서 여러 변수에 대입할 수 있어서 한 줄로 값을 교환할 수 있습니다:

출력:

20 10
Lisbon: 545,000

두 번째 형태는 분해입니다. 튜플로부터 city를 string으로, population을 int로 선언합니다. 자세한 내용은 튜플에 있습니다.

자주 묻는 질문

C#의 var는 무엇인가요?

var는 컴파일러에게 초기화 값으로부터 지역 변수의 타입을 추론하라고 알립니다. var count = 5;는 int를 선언합니다. 변수는 여전히 정적 타입이라 나중에 문자열을 담을 수 없습니다. var는 같은 문장에서 초기화되는 지역 변수에만 쓸 수 있습니다.

C#에서 const와 readonly의 차이는 무엇인가요?

const는 컴파일 시점 상수입니다. 값을 컴파일할 때 알 수 있어야 하고(숫자, 문자열, bool, null), 암시적으로 static이며, 사용하는 모든 곳에 값이 복사됩니다. readonly 필드는 실행 시점에 선언이나 생성자에서 한 번 설정되고, 어떤 타입이든 담을 수 있으며, 객체마다 값이 다를 수 있습니다.

언제 const 대신 static readonly를 써야 하나요?

DateTime, 배열, 객체처럼 컴파일 시점 상수가 될 수 없는 공유 값이나, 라이브러리 버전에 따라 바뀔 수 있는 public 값에는 static readonly를 쓰세요. const 값은 호출하는 어셈블리에 복사되므로, public const를 바꾸면 그것을 쓰는 모든 어셈블리를 다시 컴파일해야 합니다.

C#의 "use of unassigned local variable"은 무슨 뜻인가요?

CS0165 오류입니다. 컴파일러가 지역 변수에 값이 대입되기 전에 읽히는 경로를 찾았다는 뜻입니다. C#에서 지역 변수에는 기본값이 없습니다. 선언할 때 초기화하거나, if/switch의 모든 분기에서 사용 전에 대입되도록 하세요.

C#에서 var와 명시적 타입 중 무엇을 써야 하나요?

둘 다 괜찮고 팀마다 스타일을 정합니다. 흔한 규칙은 오른쪽에서 타입이 분명하면 var를 쓰고(var list = new List<string>();), 분명하지 않으면 타입을 쓰는 것입니다(decimal total = GetTotal();). .NET 런타임 코드베이스도 대략 이 규칙을 따릅니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기