已不再支援此瀏覽器。
請升級至 Microsoft Edge,以利用最新功能、安全性更新和技術支援。
下表列出 Visual C# 2010 的重大變更,這些變更可能造成以 Visual C# 2008 建立的應用程式無法編譯,或導致執行階段行為改變。
分類
問題
描述
組件繫結
組件繫結會將兩個組件視為相等。
參考特定參考組件之 .NET Framework 版本和 .NET Framework for Silverlight 版本並同時使用 extern alias 的 C# 2010 應用程式會造成編譯器錯誤。 根據預設,組件繫結會將兩個組件視為相等。
若要解決錯誤,請使用 /appconfig 編譯器選項指定 app.config 檔的位置,這個檔案會停用使用 <supportPortability> 標記的預設行為。 如需詳細資訊,請參閱 /appconfig (C# 編譯器選項)。
如果您使用 Microsoft Build Engine (MSBuild) 繫結應用程式,請將適當的標記加入至 .csproj 檔。
共變數和反變數
泛型介面及委派 (例如 IEnumerable<T> 和 Func<TResult>) 中加入了新的隱含轉換。
泛型介面及委派 (例如 IEnumerable<T> 和 Func<TResult>) 現在已有泛型型別引數的隱含轉換。 例如,在 C# 2010 中,IEnumerable<string> 可以隱含轉換為 IEnumerable<object>,這樣可能在下列情節中造成不同的行為。
使用 is 關鍵字檢查型別相容性。
IEnumerable<string> strings = new List<string>(); if (strings is IEnumerable<object>) Console.WriteLine("True"); else Console.WriteLine("False"); // Prints different results. // C# 2008: False // C# 2010: True
多載解析。 C# 2010 會挑選擁有能夠滿足變異數規則之泛型引數的方法,而 C# 2008 會固定選擇非泛型引數。
class Program { public static void Test(IEnumerable e) { Console.WriteLine("IEnumerable"); } public static void Test(IEnumerable<object> e) { Console.WriteLine("IEnumerable<object>"); } static void Main(string[] args) { Test(new List<string>()); // Prints different results. // C# 2008: IEnumerable // C# 2010: IEnumerable<object> } }
如需詳細資訊,請參閱共變數和反變數 (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 中,編譯器會忽略 OptionalAttribute,因為 C# 不支援選擇性參數。
C# 2010 則採用選擇性參數。 您可以使用新的語言語法或使用 OptionalAttribute 來宣告選擇性參數。 如果您在 C# 2008 中使用 OptionalAttribute 與其他支援選擇性參數的語言互通 (例如 Visual Basic),則 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 中,當您加入 Interop 組件的參考 (例如 Microsoft.Office.Interop.Word 或 Microsoft.Office.Interop.Excel) 時,就會內嵌此組件的型別。 如需詳細資訊,請參閱逐步解說:從 Managed 組件內嵌型別 (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();
get_ 和 set_ 方法無法存取索引的屬性。
當您內嵌 COM 型別時,所有 COM 物件的呼叫都會動態分派。 如下列程式碼範例所示,如果您嘗試使用 get_Range 方法存取索引的屬性 Range,C# 執行階段繫結器會在類別中尋找使用者定義的 get_Range 方法,而這個方法並不存在。 為避免發生這個問題,請針對索引的屬性使用 C# 2010 語法。 如需詳細資訊,請參閱 HOW TO:使用 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 中,現在可以透過使用 CompareExchange 方法而非 MethodImplAttribute,同步變更編譯器產生之加入和移除方法的支援欄位。
這樣可能造成 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(); } } } }
Visual C# 使用者入門
MSBuild