어셈블리 바인딩 |
어셈블리 바인딩이 두 개의 어셈블리를 동일한 것으로 처리합니다. |
특정 참조 어셈블리의 .NET Framework 버전과 .NET Framework for Silverlight 버전을 동시에 참조하고 extern alias도 사용하는 C# 2010 응용 프로그램에서는 컴파일러 오류가 발생합니다. 기본적으로 어셈블리 바인딩은 두 개의 어셈블리를 동일한 것으로 처리합니다.
이 문제를 해결하려면 /appconfig 컴파일러 옵션을 사용하여 app.config 파일의 위치를 지정합니다. 이 파일은 <supportPortability> 태그를 사용하여 기본 동작을 사용하지 않도록 설정합니다. 자세한 내용은 /appconfig (C# 컴파일러 옵션)를 참조하십시오.
MSBuild(Microsoft Build Engine)를 사용하여 응용 프로그램을 빌드하는 경우에는 .csproj 파일에 적절한 태그를 추가합니다. |
공 분산 및 반공변성(Contravariance) |
IEnumerable<T> 및 Func<TResult>와 같은 제네릭 인터페이스와 대리자에 새로운 암시적 변환이 추가되었습니다. |
IEnumerable<T> 및 Func<TResult>와 같은 제네릭 인터페이스와 대리자에는 이제 제네릭 형식의 인수에 대한 암시적 변환이 포함됩니다. 예를 들어 C# 2010의 경우 IEnumerable<string>을 IEnumerable<object>로 암시적으로 변환할 수 있으므로 다음 시나리오에서 다른 동작이 발생할 수 있습니다.
자세한 내용은 공변성(Covariance) 및 반공변성(Contravariance)(C# 및 Visual Basic)을 참조하십시오. |
null 병합 연산자 |
null 병합 연산자(??)는 할당되지 않은 지역 변수를 허용하지 않습니다. |
C# 2010의 경우, 왼쪽의 피연산자가 null이 아님을 보장할 수 있더라도 null 병합 연산자의 오른쪽에서 할당되지 않은 지역 변수를 피연산자로 사용할 수 없습니다.
예를 들어 다음 코드는 C# 2008의 경우 컴파일되지만 C# 2010의 경우 컴파일러 오류 CS0165가 발생합니다.
int? i;
int? j;
int? x = (i = 2) ?? j;
|
메서드 그룹 형식 유추 |
컴파일러는 메서드 그룹에 대해 제네릭 대리자와 제네릭이 아닌 대리자를 모두 유추하므로 모호성이 발생할 수 있습니다. |
C# 2008에서 컴파일러는 메서드 그룹에 대해 제네릭 대리자를 유추할 수 없습니다. 따라서 제네릭 대리자가 있더라도 항상 제네릭이 아닌 대리자를 사용합니다.
C# 2010에서는 메서드 그룹에 대해 제네릭 대리자와 제네릭이 아닌 대리자가 모두 유추되며, 컴파일러가 둘 중 하나를 동일하게 유추할 수 있습니다. 따라서 제네릭 대리자와 제네릭이 아닌 대리자가 둘 다 있고 두 대리자 모두 요구 사항을 만족할 경우 모호성이 발생할 수 있습니다. 예를 들어 다음 코드는 C# 2008에서 컴파일되고 제네릭이 아닌 대리자를 사용하는 메서드를 호출합니다. C# 2010에서 이 코드를 컴파일하면 모호한 호출을 보고하는 컴파일러 오류가 발생합니다.
public class Sample
{
delegate string NonGenericDelegate();
delegate T GenericDelegate<T>();
string UseDelegate(NonGenericDelegate del)
{
return null;
}
T UseDelegate<T>(GenericDelegate<T> del)
{
return default(T);
}
public string Test()
{
// This line produces
// a compiler error in C# 2010.
return UseDelegate(Test);
}
}
|
선택적 매개 변수 |
C#에서는 이제 OptionalAttribute가 인식되어, 메서드 오버로드 확인이 달라질 수 있습니다. |
C# 2008에서는 C#에서 선택적인 매개 변수가 지원되지 않기 때문에 컴파일러가 OptionalAttribute를 무시합니다.
C# 2010에는 선택적인 매개 변수가 도입되었습니다. 새 언어 구문을 사용하거나 OptionalAttribute를 사용하여 선택적인 매개 변수를 선언할 수 있습니다. 선택적인 매개 변수를 지원하는 다른 언어(예: Visual Basic)와의 호환성을 위해 C# 2008에서 OptionalAttribute를 사용할 경우 C# 2008은 항상 메서드 호출에 모든 매개 변수가 나열된 메서드만 선택합니다. C# 2010은 메서드 호출에 매개 변수가 지정되어 있지 않더라도 선택적인 매개 변수가 포함된 메서드를 선택할 수 있습니다.
다음 코드는 선택적인 특성이 무시되고 파생된 클래스의 메서드에 항상 문자열 매개 변수가 필요한 것처럼 컴파일러가 작동하기 때문에 C# 2008의 기본 클래스에서 메서드를 호출합니다. C# 2010에서는 이 메서드 시그니처가 메서드 호출과 일치하기 때문에 코드가 파생된 클래스에서 메서드를 호출합니다.
class Program
{
public static void Main(string[] args)
{
var obj = new Derived();
obj.Method();
}
}
class Base
{
public void Method()
{
Console.WriteLine(
"Base class + no optional parameters");
}
}
class Derived : Base
{
public void Method(
[Optional][DefaultParameterValue("Hello")]
string s)
{
Console.WriteLine(
"Derived class + an optional parameter");
}
}
// Prints different results.
// C# 2008: Base class + no optional parameters
// C# 2010: Derived class + an optional parameter
자세한 내용은 명명된 인수와 선택적 인수(C# 프로그래밍 가이드)를 참조하십시오. |
포함된 Interop 형식 |
CoClass를 사용하여 포함된 COM 형식의 인스턴스를 만들려고 하면 컴파일러 오류가 발생합니다. |
C# 2010의 경우 Microsoft.Office.Interop.Word 또는 Microsoft.Office.Interop.Excel과 같은 interop 어셈블리에 참조를 추가하면 이 어셈블리의 형식이 포함됩니다. 자세한 내용은 연습: 관리되는 어셈블리의 형식 포함(C# 및 Visual Basic) 및 /link(C# 컴파일러 옵션)를 참조하십시오.
코드에서 포함된 COM 형식의 인스턴스를 만들려면 적합한 인터페이스를 사용하여 인스턴스를 만들어야 합니다. CoClass를 사용하여 포함된 COM 형식의 인스턴스를 만들려고 하면 컴파일러에서 오류가 보고됩니다.
// Add the following statement
// at the beginning of the file:
// using Word = Microsoft.Office.Interop.Word;
// This statement does not compile in C# 2010.
Word.Application wordClass =
new Word.ApplicationClass();
// Use the following code instead.
Word.Application wordInterface =
new Word.Application();
|
포함된 Interop 형식 |
인덱싱된 속성은 get_ 및 set_ 메서드에서 액세스할 수 없습니다. |
COM 형식을 포함하면 COM 개체에 대한 모든 호출이 동적으로 디스패치됩니다. 다음 코드 예제에서와 같이 get_Range 메서드를 사용하여 인덱싱된 속성 Range에 액세스하려고 하면 C# 런타임 바인더가 클래스에서 사용자 정의된 get_Range 메서드를 조회하지만, 이 메서드가 존재하지 않습니다. 이 문제를 방지하려면 인덱싱된 속성에 대해 C# 2010 구문을 사용합니다. 자세한 내용은 방법: Visual C# 2010 기능을 사용하여 Office Interop 개체에 액세스(C# 프로그래밍 가이드)를 참조하십시오.
// Add the following statement
// at the beginning of the file:
// using Excel = Microsoft.Office.Interop.Excel;
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = true;
excelApp.Workbooks.Add(
Excel.XlWBATemplate.xlWBATWorksheet);
Excel.Worksheet sheet =
excelApp.ActiveSheet as Excel.Worksheet;
// The following statement throws
// a run-time excpetion in C# 2010.
Excel.Range rangeOld =
sheet.get_Range(
sheet.Cells[1, 1], sheet.Cells[2, 2]);
// Use the following syntax instead.
Excel.Range rangeNew =
sheet.Range[sheet.Cells[1, 1],
sheet.Cells[2, 2]];
|
이벤트 동기화 |
컴파일러에서 생성된 추가 및 제거 메서드에서 이벤트의 지원 필드에 쓰기를 동기화하는 작업은 이제 CompareExchange 메서드를 사용하여 수행됩니다. 이 경우 경합 상태가 발생할 수 있습니다.
|
C# 2010의 경우 컴파일러에서 생성된 추가 및 제거 메서드에 대해 지원 필드를 변경하기 위한 동기화 작업은 MethodImplAttribute 대신 CompareExchange 메서드를 사용하여 수행됩니다.
이 경우 다음 코드 예제에서와 같이 C# 2008에서 발생하지 않은 경합 상태가 발생할 수 있습니다.
using System;
using System.Threading;
class Sample
{
public event Action sampleEvent;
static void Main()
{
new Sample().Loop();
}
void Loop()
{
new Thread(() => Test.Method(this)).Start();
while (true)
{
lock (this)
{
if (sampleEvent != null)
{
// In C# 2010, sampleEvent
// can be null here,
// which causes
// a run-time exception.
sampleEvent();
}
}
}
}
}
class Test
{
public static void Method(Sample arg)
{
while (true)
{
arg.sampleEvent += Method;
arg.sampleEvent -= Method;
}
}
static void Method() { }
}
경합 상태를 방지하려면 다음 코드 예제에서와 같이 Loop 메서드를 수정합니다.
void Loop()
{
new Thread(() => Test.Method(this)).Start();
while (true)
{
lock (this)
{
// Create a local copy of the delegate.
Action local = sampleEvent;
if (local != null)
{
local();
}
}
}
}
|