Visual C# 2008의 주요 변경 사항
업데이트: 2008년 7월
Visual C# 2008 서비스 팩 1의 주요 변경 사항
다음 표에서는 Visual C# 2008의 최초 릴리스 버전 또는 Visual C# 2005에서 만든 응용 프로그램에 영향을 미칠 수 있는 Visual C# 2008 서비스 팩 1의 모든 주요 변경 사항을 보여 줍니다.
변경 번호 |
범주 |
문제 |
설명 |
---|---|---|---|
1 |
오버로드 확인 |
이제 메서드 오버로드 확인에서 포인터 형식의 배열에 형식 유추가 포함됩니다. |
Visual C# 2008 및 그 이전 버전에서는 형식 유추 때문에 메서드 오버로드 확인 과정에서 포인터 형식의 배열이 제외되었습니다. 다음 코드에서 Visual C# 2005 컴파일러는 Test의 제네릭이 아닌 버전을 선택하는데 그 이유는 Test의 제네릭 버전이 형식 매개 변수 int*[]로 인해 고려되지 않기 때문입니다. Visual C# 2008에서는 Test의 제네릭 버전이 선택됩니다.
|
2 |
인덱서 |
컴파일러에서 이제 메서드 뿐만 아니라 인덱서와 속성에 대해서도 오류 CS0466을 생성합니다. |
Visual C# 2008 최초 릴리스 버전 및 그 이전 버전에서는 구현에는 params 매개 변수가 있지만 인터페이스 정의에는 없는 명시적인 인덱서 구현을 정의할 수 있는데 이러한 구문은 사양에 맞지 않습니다. Visual C# 2008 SP1에서는 이 경우 다음 코드에서 보듯이 컴파일러 오류 CS0466이 생성됩니다.
} |
3 |
Nullable 형식 및 ?? 식 |
컴파일러에서 이제 nullable 변수가 자신과 비교되는 식을 올바르게 계산합니다. |
Visual C# 2008의 최초 릴리스 버전에서 다음 코드는 컴파일되고 런타임에 "false"가 출력됩니다. Visual C# 2008 서비스 팩 1에서는 컴파일러 경고(수준 3) CS1718이 생성되고 "true"가 출력됩니다.
|
4 |
반복기의 try-finally |
break 문이 있는 반복기에서 중첩된 finally 블록을 실행하는 방식이 변경되었습니다. |
Visual C# 2008의 최초 릴리스 버전에서 다음 코드는 바깥쪽 finally를 두 번 실행합니다. Visual C# 2008 SP1에서는 바깥쪽 finally가 한 번 실행됩니다.
|
5 |
식 트리 |
식 트리에서 메서드 식을 잘못 boxing하는 일은 더 이상 발생하지 않습니다. |
Visual C# 2008의 최초 릴리스 버전에서 다음 코드는 7, 0을 출력합니다. 즉 Console.WriteLine(e.Compile()(default(T))); 줄에서 S가 잘못 boxing되어 0이 출력됩니다. Visual C# 2008 SP1에서는 boxing이 일어나지 않으므로 7, 7이 출력됩니다.
|
6 |
개체 이니셜라이저 |
개체 이니셜라이저의 값 형식 초기화가 수정되었습니다. |
Visual C# 2008의 최초 릴리스 버전에서 다음 예제의 지역 변수 b는 올바르게 초기화되지 않으며 해당 멤버 X는 0 값을 가집니다. Visual C# 2008 SP1에서 S.X는 두 new 식에서 모두 1로 올바르게 초기화됩니다.
|
7 |
형식 변환 |
Null 리터럴을 더 이상 열거형 값으로 변환할 수 없습니다. |
Visual C# 2008의 최초 릴리스 버전에서는 일부 경우에 null 리터럴을 열거형 값으로 변환할 수 있습니다. Visual C# 2008 SP1에서는 다음 예제에서 보듯이 이 경우 컴파일러 오류 CS1502 및 컴파일러 오류 CS1503이 생성됩니다.
|
8 |
식 트리 |
잘못된 식 트리에서 이제 올바른 예외를 throw합니다. |
Visual C# 2008의 최초 릴리스 버전에서는 지정된 형식이 아닌 메서드에 대한 메서드 호출을 포함하는 식 트리에서 System.Security.VerificationException을 throw합니다. Visual C# 2008 SP1에서는 다음 코드에서 보듯이 System.ArgumentException이 throw됩니다.
|
9 |
특성 |
CharSet.Unicode는 이제 C#이 고정 배열 필드에 대해 생성하는 도우미 형식으로 전파됩니다. |
C# 컴파일러는 고정 배열을 캡슐화하는 도우미 형식을 생성합니다. Visual C# 2008의 최초 릴리스 버전 및 이전 버전에서 배열의 레이아웃은 StructLayout 특성에 CharSet.Unicode가 지정된 경우에도 항상 ANSI입니다. C# 소스 코드에서 이를 바꿀 수 있는 방법은 없었습니다. Visual C# 2008 SP1에서는 다음 코드에서 보듯이 StructLayout 특성에 지정된 CharSet 값을 사용하여 도우미 클래스가 생성됩니다.
|
10 |
오버플로 검사 |
stackalloc에서는 이제 오버플로를 검사합니다. |
Visual C# 2008의 최초 릴리스 버전에서는 예외를 발생시키지 않으면서 stackalloc 할당이 실패할 수 있습니다. 그 이유는 생성된 MSIL(Microsoft Intermediate Language)에서 배열의 길이를 각 요소의 크기로 곱할 때 확인되지 않는 mul 명령을 사용하기 때문입니다. Visual C# 2008 SP1에서는 mul 대신 mul.ovf 명령이 생성되므로 런타임에 할당을 시도할 때 오버플로가 발생하면 System.OverflowEx ception이 생성됩니다.
|
11 |
표준 쿼리 연산자 |
제네릭이 아닌 컬렉션에 대한 쿼리에서 이제 표준 C# 캐스팅 의미 체계를 사용합니다. |
System.Collections.ArrayList와 같은 제네릭이 아닌 컬렉션에 대한 LINQ 쿼리 식에서 컴파일러는 Cast<T> 연산자에 대한 호출을 포함하도록 쿼리의 from 절을 다시 씁니다. Cast<T>는 모든 요소 형식을 쿼리의 from 절에 지정된 형식으로 변환합니다. 또한 Visual C# 2008의 최초 릴리스 버전에서는 Cast<T> 연산자가 일부 값 형식 변환 및 사용자 정의 변환도 수행합니다. 하지만 이러한 변환은 표준 C# 의미 체계를 사용하는 대신 System.Convert 클래스를 사용하여 수행됩니다. 이러한 변환은 또한 특정 시나리오에서 심각한 성능 문제를 일으킬 수 있습니다. Visual C# 2008 SP1에서는 Cast<T> 연산자가 숫자 값 형식 및 사용자 정의 변환에 대해 InvalidCastException을 throw하도록 수정되었습니다. 이러한 변경을 통해 비표준 C# 캐스팅 의미 체계 및 성능 문제가 모두 제거될 수 있습니다. 다음 예제에서는 이러한 변경 내용을 보여 줍니다.
|
Visual C# 2008 최초 릴리스 버전의 주요 변경 사항
다음 표에서는 Visual C# 2005에서 만든 응용 프로그램의 컴파일을 방해하거나 런타임 동작을 변경할 수 있는 Visual C# 2008 최초 릴리스 버전의 모든 주요 변경 사항을 보여 줍니다.
변경 번호 |
범주 |
문제 |
설명 |
---|---|---|---|
12 |
형식 변환 |
이제 값이 0인 모든 상수 식을 열거형으로 변환할 수 있습니다. |
리터럴 0은 암시적으로 모든 열거형 형식으로 변환될 수 있습니다. Visual C# 2005 및 이전 버전의 컴파일러에서도 0으로 계산되는 상수 식 중 암시적으로 열거형 형식으로 변환될 수 있는 식이 있지만 어떠한 식이 변환 가능한지 결정하는 규칙이 명확하지 않습니다. Visual C# 2008에서는 0과 일치하는 모든 상수 식은 암시적으로 열거형 형식으로 변환될 수 있습니다. 이로 인해 암시적 변환이 없다는 가정 아래 수행되는 메서드 오버로드 확인 등 기존 코드의 동작이 변경될 수도 있습니다. 다음 코드의 경우 Visual C# 2005 및 그 이전 컴파일러에서는 short 값에 대한 메서드 호출이 int 오버로드로만 확인되므로 문제 없이 컴파일됩니다. Visual C# 2008에서는 short 값이 E로도 암시적으로 변환될 수 있으므로 이 호출은 모호합니다. Visual C# 2008에서는 0으로 계산되는 모든 상수 식의 변환이 허용되도록 동작이 변경되었습니다.
|
13 |
특성 |
하나의 어셈블리에 동일한 TypeForwardedTo 특성이 두 번 나타나는 경우 이제 오류가 발생합니다. |
Visual C# 2005에서는 어셈블리에 동일한 형식의 두 System.Runtime.CompilerServices.TypeForwardedTo 특성이 있어도 오류가 발생하지 않습니다. Visual C# 2008에서는 컴파일러 오류 CS0739가 다음 예제에서처럼 생성됩니다.
} |
14 |
형식 오류 |
구조체에서 참조 형식 멤버를 사용하는 것에 대한 새로운 경고가 추가되었습니다. |
구조체에 대한 확정 할당 규칙에 따르면 구조체는 해당 형식의 기존 인스턴스로 설정되거나 참조되기 전에 모든 멤버가 할당되어야 합니다. Visual C# 2005에서는 구조체의 할당되지 않은 참조 형식 멤버가 사용될 때 경고나 오류가 발생하지 않습니다. Visual C# 2008에서는 컴파일러 경고(수준 1) CS1060이 다음 예제에서처럼 생성됩니다.
|
15 |
오버플로 검사 |
const decimal 형식에 대한 범위 검사가 수정되었습니다. |
Visual C# 2005에서는 const decimal 형식을 캐스팅할 때 범위 검사 문제로 인해 잘못된 컴파일러 오류가 생성될 수 있습니다. Visual C# 2008에서 다음 코드는 올바른 오류인 컴파일러 오류 CS0031을 생성합니다.
|
16 |
오버플로 검사 |
범위를 벗어나는 long으로의 변환을 수행할 때 이제 올바른 컴파일러 오류가 발생합니다. |
Visual C# 2005에서 다음 코드는 컴파일러 오류를 생성하지 않습니다. Visual C# 2008에서는 컴파일러 오류 CS0031이 생성됩니다.
|
17 |
고정 크기 버퍼 |
버퍼에 값을 할당하기 전에 안전하지 않은 구조체의 고정 크기 버퍼에 액세스하면 이제 컴파일러 오류가 발생합니다. |
안전하지 않은 포인터에 대한 확정 할당 규칙에 따르면 포인터의 참조를 해제하기 전에 먼저 포인터를 설정해야 합니다. Visual C# 2005에서는 안전하지 않은 구조체에 배열에 대한 포인터가 포함되어 있는 경우 이 포인터에 값을 할당하기 전에 액세스해도 컴파일러 오류가 발생하지 않았습니다. Visual C# 2008에서는 다음 코드에서 보듯이 컴파일러 오류 CS0165가 발생합니다.
|
18 |
이제 null 결합 식에서 파생 작업이 유지됩니다. |
확정 할당 및 ?? 연산자 |
Visual C# 2005에서는 null 병합 식의 왼쪽에서 발생하는 파생 작업이 유지되지 않는 경우가 있습니다. 이러한 경우 다음 예제의 두 번째 Console.WriteLine 문에서 b가 할당되지 않았다는 잘못된 컴파일러 오류가 발생합니다. Visual C# 2008에서는 같은 코드가 오류 없이 올바르게 컴파일됩니다.
} |
19 |
반복기의 try-finally |
이제 try 블록의 반복기가 continue 또는 goto로 이스케이프될 때 finally 블록이 실행됩니다. |
Visual C# 2005에서는 try-finally 구문의 try 블록에서 goto 또는 continue 문을 통해 제어가 반복기 블록을 빠져 나오는 경우 finally 블록이 실행되지 않습니다. Visual C# 2008에서는 이 경우 finally 블록이 실행됩니다.
} |
20 |
기본 클래스 및 인터페이스 |
이제 클래스를 생성할 때 기본 클래스의 동일한 인터페이스 멤버에 대한 명시적인 구현이 무시됩니다. |
Visual C# 2005에서는 클래스가 인터페이스 멤버에 대한 구현을 제공하지 않는 경우 기본 클래스 구현이 명시적인 인터페이스 구현으로 선언되어 있는 경우에도 컴파일러가 이 구현으로 대체합니다. 이 동작은 ECMA(European Computer Manufacturers Association) 사양에 맞지 않습니다. Visual C# 2008에서는 이 사양을 올바르게 구현합니다. 다음 예제의 경우 Visual C# 2005에서는 "B.Test"가 인쇄되지만 Visual C# 2008에서는 "A.Test"가 올바르게 출력되며 명시적인 인터페이스 구현인 클래스 B의 Test 메서드가 무시됩니다.
} |
21 |
특성 |
더 이상 사용되지 않는 멤버를 사용하면 이제 컴파일러 경고가 생성됩니다. |
메서드가 호출될 때 컴파일 타임에 오류 또는 경고가 발생하게 하려면 메서드를 Obsolete 특성으로 표시합니다. 가상 메서드에 이 특성을 사용하는 경우 기본 메서드에 사용해야 합니다. Obsolete 특성을 재정의 메서드에 배치하면 호출 시 컴파일러 오류나 경고가 발생하지 않습니다. Visual C# 2005에서는 Obsolete 특성을 재정의 메서드에 배치하면 아무런 효과가 없음에도 불구하고 컴파일러에서 이를 허용했습니다. Visual C# 2008에서는 "사용되지 않는 'A.Filename' 멤버가 사용되는 'Error.Filename' 멤버를 재정의합니다."라는 컴파일러 경고 컴파일러 경고(수준 1) CS0809가 생성됩니다. 다음 예제에서는 이 경고가 발생합니다.
|
22 |
빌드 오류 |
/debug를 사용하지 않고 /pdb 컴파일러 옵션을 사용하면 이제 오류가 발생합니다. |
Visual C# 2005에서는 /pdb 옵션을 지정하고 /debug 옵션을 지정하지 않아도 경고나 오류가 표시되지 않습니다. Visual C#에서는 .pdb 파일을 생성하지 않고 릴리스 빌드를 만듭니다. Visual C# 2008의 최초 릴리스 버전에서는 /debug를 지정하지 않고 /pdb를 지정하면 컴파일러에서 컴파일러 오류 CS2036을 표시합니다. |
23 |
형식 오류 |
switch 조건이 void이면 이제 오류가 생성됩니다. |
Visual C# 2005에서는 switch 문에서 void 메서드 호출이 사용될 때 오류가 생성되지 않습니다. Visual C# 2008에서는 컴파일러 오류 CS0151이 생성됩니다.
} |
24 |
오버플로 검사 |
상수 decimal을 정수로 변환하면 이제 다른 컴파일러 오류가 발생합니다. |
Visual C# 2005에서 다음 코드는 "'b'에 할당할 식은 상수여야 합니다."라는 컴파일러 오류 CS0133을 생성합니다.
Visual C# 2008에서는 "'256M' 상수 값을 'byte'(으)로 변환할 수 없습니다."라는 컴파일러 오류 CS0031이 생성됩니다. 이 오류는 unchecked 한정자가 적용되어 있는 경우에도 생성됩니다. |
25 |
상수 식 |
상수 식과 관련된 사양이 더 엄격하게 준수됩니다. |
Visual C# 2008에서는 Visual C# 2005에서 상수 식에 잘못된 연산자 및 변수를 허용하던 몇 가지 문제가 수정되었습니다. Visual C# 2005에서 다음 코드는 오류 없이 컴파일됩니다. Visual C# 2008에서는 컴파일러 오류 CS0165, 컴파일러 경고(수준 1) CS0184 및 컴파일러 경고(수준 3) CS1718이 발생합니다.
|
26 |
형식 오류 |
이제 정적 형식을 대리자 또는 람다 식에 매개 변수로 사용하면 오류가 발생합니다. |
Visual C# 2005에서는 정적 형식을 대리자 또는 무명 메서드에 매개 변수로 사용해도 오류가 발생하지 않습니다. 정적 형식은 인스턴스화할 수 없으므로 메서드 매개 변수의 형식으로 사용할 수 없습니다. Visual C# 2005 버전의 컴파일러는 대리자 및 무명 메서드 선언 내부에서 매개 변수 형식으로 정적 형식을 허용합니다. null을 매개 변수로 전달하면 해당 대리자가 호출될 수 있습니다. Visual C# 2008에서는 다음 예제에서 보듯이 정적 형식을 대리자 또는 무명 메서드에 매개 변수로 사용하면 컴파일러 오류 CS0721이 발생합니다.
} |
27 |
Nullable 형식 및 ?? 식 |
상수를 더 넓은 형식의 nullable에 할당하기 전에 nullable 형식으로 캐스팅해도 경고가 발생하지 않습니다. |
Visual C# 2005에서 다음 코드는 컴파일러 경고(수준 3) CS0219를 생성합니다. Visual C# 2008에서는 경고가 생성되지 않습니다.
|
28 |
오버로드 확인 |
이제 무명 메서드에서 모호한 오버로드 확인이 발생하면 오류가 생성됩니다. |
오버로드된 메서드에 대한 메서드 호출이 발생하면 호출할 특정 오버로드를 컴파일러에서 확인해야 합니다. 호출의 매개 변수 형식이 부분적으로 유추되는 경우 호출할 특정 오버로드가 모호해질 수 있습니다. 이 경우 컴파일러 오류가 발생합니다. 무명 메서드가 대리자 매개 변수로 전달되는 경우 무명 메서드의 대리자 형식은 부분적으로 유추됩니다. 이 경우 컴파일러가 올바른 오버로드를 선택할 때 모호성이 발생할 수 있습니다. Visual C# 2005에서는 무명 메서드에 대한 최적의 단일 오버로드가 없을 때 컴파일러에서 오류를 생성하지 않는 경우도 있습니다. Visual C# 2008에서는 컴파일러 오류 CS0121이 다음 예제에서처럼 생성됩니다.
|
29 |
형식 오류 |
이제 관리되는 형식에 대한 포인터 배열을 선언하면 오류가 발생합니다. |
참조 형식에 대한 안전하지 않은 포인터는 허용되지 않으며 컴파일러 오류가 발생합니다. Visual C# 2005에서는 관리되는 형식에 대한 포인터 배열을 선언할 수 있습니다. Visual C# 2008에서는 "관리되는 형식('T')의 주소 또는 크기를 가져오거나 해당 형식에 대한 포인터를 선언할 수 없습니다."라는 컴파일러 오류 CS0208이 발생합니다.
} |
30 |
오버로드 확인 |
오버로드 확인 후보 메서드에서 ref 또는 out만 다를 경우 이제 경고가 발생합니다. |
Visual C# 2005에서는 C# 컴파일러가 제네릭 형식에 대해 오버로드 확인을 수행할 때 형식 인수로 인해 후보 메서드에서 ref 또는 out만 다르게 되는지 확인하지 않습니다. 따라서 메서드 선택은 런타임에 CLR(공용 언어 런타임)에 맡겨지며 CLR은 목록에서 첫 번째 메서드를 선택합니다. Visual C# 2008에서는 오버로드 확인 대상 두 후보 메서드에서 ref 또는 out만 다르게 된다는 것을 컴파일러가 감지하면 컴파일러 경고(수준 1) CS1956이 발생합니다. 다음 예제에서는 이러한 경우에 대해 보여 줍니다.
} |
31 |
Nullable 형식 및 ?? 식 |
왼쪽이 null인 null 병합 식은 더 이상 null 상수로 계산되지 않습니다. |
Visual C# 2005에서 왼쪽이 null인 null 병합 식은 null 상수로 계산됩니다. Visual C# 2008에서는 그렇지 않습니다. 이러한 Visual C# 2005의 동작으로 인해 변수가 확정 할당 변수로 잘못 처리되는 경우가 발생할 수 있습니다. 다음 코드는 Visual C# 2005에서 오류 없이 컴파일되고 실행되지만 Visual C# 2008에서는 "할당되지 않은 'x' 지역 변수를 사용했습니다."라는 컴파일러 오류 CS0165가 발생합니다.
|
참고 항목
기타 리소스
변경 기록
날짜 |
변경 내용 |
이유 |
---|---|---|
2008년 7월 |
항목이 추가되었습니다. |
SP1 기능 변경 |