C♯

維基百科,自由的百科全書
(重新導向自C Sharp 3.0
跳至導覽 跳至搜尋
C#
File:C Sharp Logo 2023.svg
編程範型結構化物件導向泛型
語言家族C
設計者微軟
實作者微軟
面市時間2000年,​25年前​(2000
目前版本
    Module:EditAtWikidata第29行Lua錯誤:attempt to index field 'wikibase' (a nil value)
    作業系統WindowsLinuxMac OS XAndroid
    許可證
    副檔名.cs, .csx
    網站{{URL|example.com|可选的显示文本}}Module:EditAtWikidata第29行Lua錯誤:attempt to index field 'wikibase' (a nil value)
    主要實作產品
    .NET.NET框架MonoDotGNU
    衍生副語言
    Spec#英語Spec SharpPolyphonic C#英語Polyphonic C sharp
    受影響於
    C++JavaEiffelModula-3Object Pascal
    影響語言
    Clojure[3]D語言F#Java 5、NemerleVala

    C#微軟推出的一種基於.NET框架和後來的.NET的、物件導向的進階程式語言。C#衍生自C和C++,繼承了C和C++的強大功能,同時去掉了一些複雜特性,使其成為C語言家族中高效強大的程式語言。C#以.NET類別程式庫作為基礎,擁有類似Visual Basic的快速開發能力。C#由安德斯·海爾斯伯格主持開發,微軟在2000年發布了這種語言,希望藉助這種語言來取代Java。C#已經成為Ecma國際國際標準組織的標準規範。

    設計目標[編輯]

    ECMA標準列出的C#設計目標:

    • C#旨在設計成為一種「簡單、現代、通用」,以及物件導向的程式設計語言
    • 此種語言的實現,應提供對於以下軟體工程要素的支援:強型別檢查、陣列維度檢查、未初始化的變數參照檢測、自動垃圾收集(Garbage Collection,指一種記憶體自動釋放技術)。軟體必須做到強大、持久,並具有較強程式開發的生產力。
    • 此種語言為在分散式環境中的開發提供適用的組件開發應用。
    • 為使程式設計師容易遷移到這種語言,原始碼的可移植性十分重要,尤其是對於那些已熟悉C和C++的程式設計師而言。
    • 對國際化的支援非常重要。
    • C#適合為獨立和嵌入式的系統編寫程式,從使用複雜作業系統的大型系統到特定應用的小型系統均適用。

    歷史[編輯]

    Borland公司的首席研發設計師安德斯·海爾斯伯格(Anders Hejlsberg)在微軟開發了Visual J++ 1.0,很快的Visual J++由1.1版本升級到6.0版。SUN公司認為Visual J++ 違反了Java開發平台的中立性,對微軟提出了訴訟。2000年6月26日微軟在奧蘭多舉行的「職業開發人員技術大會」(PDC 2000)上,發表新的語言C#。C#語言取代了Visual J++,語言本身深受Visual Basic、Java、C和C++ 的影響。

    版本[編輯]

    版本 語言規格 日期 .NET框架版本 Visual Studio的版本
    ECMA ISO/IEC Microsoft
    C# 1.0 2002年12月頁面存檔備份,存於網際網路檔案館 2003年4月頁面存檔備份,存於網際網路檔案館 2002年1月頁面存檔備份,存於網際網路檔案館 2002年1月 .NET Framework 1.0 Visual Studio .NET 2002
    C# 1.1
    C# 1.2
    2003年10月頁面存檔備份,存於網際網路檔案館 2003年4月 .NET Framework 1.1英語.NET Framework 1.1 Visual Studio .NET 2003
    C# 2.0 2006年6月 2006年9月頁面存檔備份,存於網際網路檔案館 2005年9月頁面存檔備份,存於網際網路檔案館 2005年11月 .NET Framework 2.0 Visual Studio 2005
    C# 3.0 2007年8月頁面存檔備份,存於網際網路檔案館 2007年11月

    .NET Framework 2.0 (Except LINQ)[4]
    .NET Framework 3.0 (Except LINQ)[4]
    .NET Framework 3.5

    Visual Studio 2008
    Visual Studio 2010
    C# 4.0 2010年4月 2010年4月 .NET Framework 4 Visual Studio 2010
    C# 5.0 2017年12月頁面存檔備份,存於網際網路檔案館 2018年12月頁面存檔備份,存於網際網路檔案館 2013年6月頁面存檔備份,存於網際網路檔案館 2012年8月 .NET Framework 4.5 Visual Studio 2012
    Visual Studio 2013
    C# 6.0 2022年6月 草案頁面存檔備份,存於網際網路檔案館 2015年7月/2016-06-27 .NET Framework 4.6/.NET Core 1.0 Visual Studio 2015
    C# 7.0 2023年12月 2023年9月 建議草案頁面存檔備份,存於網際網路檔案館 2017年3月 .NET Framework 4.6.2 Visual Studio 2017
    C# 7.1 建議草案頁面存檔備份,存於網際網路檔案館 2017年8月/2016-08-14 .NET Framework 4.7英語.NET Framework 4.7/.NET Core 2.0 Visual Studio 2017 version 15.3[5]
    C# 7.2 建議草案 2017年11月 .NET Framework 4.7.1 Visual Studio 2017 version 15.5[6]
    C# 7.3 建議草案頁面存檔備份,存於網際網路檔案館 2018年5月/2018-05-30/2018-12-04 .NET Framework 4.7.2/.NET Core 2.1/.NET Core 2.2 Visual Studio 2017 version 15.7[6]
    C# 8 建議草案頁面存檔備份,存於網際網路檔案館 2019年9月/2019-09-23/2019-12-03 .NET Framework 4.8/.NET Core 3.0/.NET Core 3.1 Visual Studio 2019 version 16.3[6]
    C# 9 建議草案頁面存檔備份,存於網際網路檔案館 2020年11月 .NET 5 Visual Studio 2019 version 16.8[6]
    C# 10[7] 建議草案頁面存檔備份,存於網際網路檔案館 2021年11月 .NET 6 Visual Studio 2022 version 17.0[8]
    C# 11[7] 建議草案頁面存檔備份,存於網際網路檔案館 2022年11月 .NET 7 Visual Studio 2022 version 17.4[9]
    C# 12[10] 建議草案頁面存檔備份,存於網際網路檔案館 2023年11月 .NET 8 Visual Studio 2022 version 17.8[11]
    C# 13[12] 建議草案頁面存檔備份,存於網際網路檔案館 2024年9月 .NET 9 Visual Studio 2022 version 17.12[13]

    語言特性[編輯]

    相對於CC++,這個語言在許多方面進行了限制和增強:

    • 指標(Pointer)只能用於不安全模式之中。大多數對象訪問透過安全的參照實現,以避免無效的調用,並且有許多演算法用於檢查溢位,指標只能用於調用值類型,以及受垃圾收集控制的代管對象。
    • 對象不能被顯式釋放,代替為當不存在被參照時透過垃圾回收器回收。
    • 只允許單一繼承(single inheritance),但是一個類可以實現多個介面(interfaces)。
    • C#比C++更加類型安全。預設的安全轉換是隱含轉換,例如由短整型轉換為長整型和從衍生類轉換為基本類。而介面布林數同整型,及枚舉型同整型不允許隱含轉換,非空指標(透過參照相似對象)同使用者定義類型的隱含轉換欄位被顯式的確定,不同於C++的複製構造函式。
    • 陣列宣告的語法不同("int[] a = new int[5]"而不是"int a[5]")。
    • 枚舉位於其所在的命名空間中。
    • C#中沒有模版(Template),但是在C# 2.0中引入了泛型(Generic programming),並且支援一些C++模版不支援的特性。比如泛型參數中的類型約束。另一方面,表達式不能像C++模版中被用於類型參數。
    • 屬性支援,使用類似訪問成員的方式調用。
    • 完整的反射支援。

    C# 2.0的特性[編輯]

    針對於.NET SDK 2.0(相對應於ECMA-334標準第三版),C# 的新特性有:

    部分類[編輯]

    分部類別將類別的實現分在多個檔案中。該概念於C# 中首次出現,除了能將一個類別的成員分開存放,還使ASP.NET中的代碼後置得以實現。代碼後置實現了HTML代碼和後台互動代碼的分離。

    file1.cs:

    public partial class MyClass1
    {
        public void MyMethod1()
        {
            // implementation
        }
    }
    

    file2.cs:

    public partial class MyClass1
    {
        public void MyMethod2()
        {
            // implementation
        }
    }
    

    分部類別這個特性允許將一個類別的編寫工作分配給多個人,一人寫一個檔案,便於版本控制。它又可以隔離自動生成的代碼和人工書寫的代碼,例如設計表單應用程式時。

    泛型[編輯]

    泛型,或參數化類型,是被C#支援的.NET 2.0特性。不同於C++模版,.NET參數化類型是在執行時被實例化,而不是編譯時,因此它可以跨語言,而C++模版卻不行。C#泛型類在編譯時,先生成中間代碼IL,通用類型符號T只是一個預留位置;在實例化類時,根據實際資料類型代替T並由即時編譯器(JIT)生成本地代碼,其中使用了實際的資料類型,等同於用實際類型寫的普通的類。

    它支援的一些特性並不被C++模版直接支援,比如約束泛型參數實現一個介面。另一方面,C# 不支援無類型的泛型參數。不像Java中的泛型,在CLI虛擬機器中,.NET generics使用具化生成泛型參數,它允許最佳化和儲存類型資訊。[14]

    泛型類中,可以用where關鍵字對參數類型實現約束。例如:

    class Node<T, V>
        where T : Stack, IComparable, new(), class
        where V : Stack, struct
    {...}
    

    上述表示T和V必須是Stack類或其衍生類別,T必須繼承了IComparable介面、有無參建構函式、是參照類型;V必須是值類型。

    泛型不僅能作用在類上,也可單獨用在類的方法上,稱為「泛型方法」。

    泛型類的靜態成員變數在相同封閉類間共享,不同的封閉類間不共享。

    泛型類中的方法多載,參數類型T和V在執行時確定,不影響這個類通過編譯。C#的泛型是在實例的方法被呼叫時檢查多載是否產生混淆,而不是在泛型類本身編譯時檢查。特別地,當一般方法與泛型方法具有相同的簽章時,會覆蓋泛型方法。

    靜態類別[編輯]

    靜態類別它不能被實例化,並且只能有靜態成員。這同很多過程語言中的模組概念相類似。

    迭代器[編輯]

    一種新形式的迭代器它提供了函數式程式設計中的generator,使用yield return

    類似於Python中使用的yield

    // Method that takes an iterable input (possibly an array)
    // and returns all even numbers.
    public static IEnumerable<int> GetEven(IEnumerable<int> numbers)
    {
        foreach (int i in numbers)
        {
            if (i % 2 == 0) yield return i;
        }
    }
    

    注意事項:

    • foreach迴圈時考慮執行緒安全性,不要試圖對被遍歷的集合進行remove和add等操作
    • IEnumerable介面是LINQ特性的核心介面。只有實現了IEnumerable介面的集合,才能執行相關的LINQ操作,比如select,where等

    匿名方法[編輯]

    匿名方法類似於函數式程式設計中的閉包[15]匿名方法是通過使用 delegate 關鍵字建立委託實例來聲明的。例如:

    delegate void NumberChanger(int n);
     
    NumberChanger nc = delegate(int x)
    {
        Console.WriteLine("Anonymous Method: {0}", x);
    };
    
    public void Foo(object parameter)
    {
        // ...
    
        ThreadPool.QueueUserWorkItem(delegate
        {
            // anonymous delegates have full access to local variables of the enclosing method
            if(parameter == ...)
            { 
                // ... 
            }
    
            // ...
        });
    }
    

    委託的協變和逆變[編輯]

    委託簽章的協變和逆變[16]

    屬性訪問器可以被單獨設定訪問級別[編輯]

    例子:

    string status = string.Empty;
    
    public string Status
    {
        get { return status; }             // anyone can get value of this property,
        protected set { status = value; }  // but only derived classes can change it
    }
    

    可空類型[編輯]

    可空類型(跟個問號,如int? i = null;)允許設定null給任何類類型。

    int? i = null;
    object o = i;
    if(o == null)
        Console.WriteLine("Correct behaviour - runtime version from September 2005 or later");
    else
        Console.WriteLine("Incorrect behaviour - pre-release runtime (from before September 2005)");
    

    ??運算子[編輯]

    ??):如果左運算數表達式的值不為空值時回傳該值,如果為空值則返回右運算數表達式的值。

    object nullObj = null; 
    object obj = new Object(); 
    return nullObj ?? obj; // returns obj
    

    主要用作將一個可空類型賦值給不可空類型的簡便語法

    int? i = null;
    int j = i ?? 0; // Unless i is null, initialize j to i. Else (if i is null), initialize j to 0.
    

    C# 3.0的特性[編輯]

    C# 3.0發布於2007年10月17日,是.NET Framework 3.5的一部分,它的新特性靈感來自於函數式程式設計語言,如:HaskellML,並廣泛地引入了Language Integrated Query(LINQ)模式到通用語言運行庫中e.[17]

    Linq[編輯]

    語言整合查詢(英語:Language Integrated Query,縮寫:LINQ):[18]上下文相關關鍵字"from, where, select"可用於查詢SQL、XML、集合等。這些識別碼在LINQ上下文中被作為關鍵字,但是它們的增加不會破壞原有的名為fromwhereselect的變數。

    類型初始化器[編輯]

    Customer c = new Customer();
    c.Name = "James";
    

    可寫作:

    Customer c = new Customer() { Name = "James" };
    

    集合初始化器[編輯]

    MyList list = new MyList();
    list.Add(1);
    list.Add(2);
    

    可寫作

    MyList list = new MyList { 1, 2 };
    

    假設MyList實現了System.Collections.IEnumerable且有一個Add方法method[19]

    匿名類型[編輯]

    var x = new { Name = "James" };
    

    局部變數類型推斷[編輯]

    局部變數類型推斷

    var x = new Dictionary<string, List<float>>();
    

    等同於

    Dictionary<string, List<float>> x = new Dictionary<string, List<float>>();
    

    它只是一個語法糖,這個特性被匿名類型聲明時所需要

    Lambda表達式[編輯]

    Lambda表達式(無函式名稱的物件方法在程式語言中的表達語法):

    listOfFoo.Where(
        delegate(Foo x)
        {
            return x.Size > 10; 
        }
    )
    
    可寫作
    listOfFoo.Where(x => x.Size > 10);
    

    編譯器翻譯Lambda表達式為強型別委託或強型別表達式樹

    注意事項:

    • 如果只有一個參數,可以省略括號(),例如 item=>{Console.WriteLine("只有一個參數{0}的Lambda表達式",item); };
    • 如果只有一個返回值的語句,可以省略花括號{}、return關鍵字、分號,例如 item => {return item % 2 == 0;};覆寫成:item =>item %2 == 0;
    • Lambda表達式可以分配給Func,Action或Predicate委託。

    自動化屬性[編輯]

    編譯器將自動生成私有變數和適當的getter(get訪問器)和setter(set訪問器),如:

    public string Name
    {
        get; 
        set; 
    }
    

    擴充方法[編輯]

    擴充方法能夠使現有的類型添加方法,而無需新增的衍生類型、重新編譯或以其它方式修改原始類型。

    使用拓展方法,必須在一個非巢狀、非泛型的靜態類中定義一個靜態方法,方法第一個參數必須附加this關鍵字作為字首,第一個參數不能有其它修飾詞(如ref或者out),這個方法將被編譯器添加到該this的類型中。

    public static class IntExtensions
    {
        public static void PrintPlusOne(this int x) 
        {
            Console.WriteLine(x + 1);
        }
    }
     
    int foo = 0;
    foo.PrintPlusOne();
    

    注意事項:

    • 擴充方法只會增加編譯器的工作,但不會影響程式執行效能(用繼承的方式為一個類型增加特性反而會影響效能)
    • 如果原來的類中有一個方法,跟擴充方法一樣,那麼擴充方法不會被呼叫,編譯器也不會提示

    分部方法[編輯]

    允許碼產生器生成方法聲明作為擴充點,如果有人在另一個部分類實現了它才會被包含於原代碼編譯。[20]

    1. 分部方法(Partial methods)必須定義在分部類(partial classes)中
    2. 定義分部方法需要用partial做修飾詞
    3. 分部方法不一定總是有執行內容的,也就是說定義的方法可以一句操作語句都沒有
    4. 分部方法返回值必須是void
    5. 分部方法可以是靜態(static)方法
    6. 分部方法可以包含參數,參數可以包含以下修飾詞:this,ref,params
    7. 分部方法必須是私有(private)方法

    例子:

    partial class C
    {
        static partial void M(int i); // defining declaration
    }
    partial class C
    {
        static partial void M(int i)
        {
            dosomething();
        }
    }
    

    C# 4.0的特性[編輯]

    dynamic類型[編輯]

    C# 4.0新增dynamic關鍵字,提供動態編程(dynamic programming),把既有的靜態物件標記為動態物件,類似javascript, PythonRuby

    dynamic關鍵字標記的實例被處理成一個特殊包裝的object對象,取消了CLI的編譯時型別檢查,編譯時被假定支援任何操作,但如果並不實際支援則執行時報錯。

    dynamic calc = GetCalculator();
    int sum = calc.Add(10, 20);
    

    具名參數與可選參數[編輯]

    public StreamReader OpenFile(string path, int bufferSize = 1024)
    { ... }
    

    呼叫OpenFile時,順序可以完全顛倒:

    OpenFile(bufferSize: 4096, path: "foo.txt");
    

    與COM組件互動[編輯]

    在C#中打開一個Word檔案:

    static void Main(string[] args)
    {
        Word.Application wordApplication = new Word.Application() { Visible = true };
        wordApplication.Documents.Open(@"C:\plant.docx", ReadOnly: true);
    }
    

    在C#中指定Excel的某一格文字:

    excelObj.Cells[5, 5].Value = "This is sample text";
    

    泛型的協變和逆變[編輯]

    C# 4.0支援協變和逆變,例如在泛型介面可以加上in、out修饰字。

    public interface IComparer<in T>  
    {  
        int Compare(T left, T right);  
    }
    
    public interface IEnumerable<out T> : IEnumerable
    {
        IEnumerator<T> GetEnumerator();
    }
    

    C# 5.0的特性[編輯]

    1. C# Evolution Matrix
    2. Async Feature (補充: async和await是一對語法糖,允許開發人員非常輕鬆的呼叫基於TASK的非同步編程)async-await關鍵字並不會真的建立一個執行緒池任務,完成這個動作依賴於被呼叫方法中的函式。這一點在許多C#的中文教程中被忽略,導致許多學習的新手誤以為await關鍵字會直接建立一個新的執行緒池任務。
    3. Caller Information

    C# 6.0的特性[編輯]

    1. 唯讀 Auto 屬性
    2. Auto 屬性初始設定式
    3. 使用靜態
    4. Null - 條件運算子
    5. 字串插值
    6. 例外狀況篩選條件
    7. nameof 運算式
    8. Catch 和 Finally 區塊中的 Await
    9. 索引初始設定式
    10. 集合初始設定式的擴充方法
    11. 改進的多載解析

    表達式主體(Expression-bodied)用於類的方法和唯讀屬性[編輯]

    using System;
    
    public class Person
    {
       public Person(string firstName, string lastName)
       {
          fname = firstName;
          lname = lastName;
       }
    
       private string fname;
       private string lname;
    
       public override string ToString() => $"{fname} {lname}".Trim(); //返回值类型string
       public void DisplayName() => Console.WriteLine(ToString()); //返回值类型void
       public string Name => $"{fname} {lname}".Trim();//只读属性
    }
    

    C# 7.0的特性[編輯]

    out 變數[編輯]

    能夠直接宣告一個變數在它要傳入的地方,當成一個 out 的引數[21]

    棄元[編輯]

    元組/對象的解構:

    var tuple = (1, 2, 3, 4, 5);
    (_, _, _, _, var fifth) = tuple;
    

    使用 is/switch 的模式匹配:

    var obj = CultureInfo.CurrentCulture.DateTimeFormat;
    switch (obj)
    {
    case IFormatProvider fmt:
        Console.WriteLine($"{fmt} object");
        break;
    case null:
        Console.Write("A null object reference");
        break;
    case object _:
        Console.WriteLine("Some object type without format information");
        break;
    }
    
    if (obj is object _) { ... }
    

    對具有 out 參數的方法的呼叫:

    var point = new Point(10, 10);
    // 只要 x, 不关心 y
    point.GetCoordinates(out int x, out _);
    

    範疇內獨立使用場景:

    void Test(Dto dto)
    {
        _ = dto ?? throw new ArgumentNullException(nameof(dto));
    }
    

    表達式主體(Expression-bodied)用於類的屬性、構造器、終端子、索引器[編輯]

    using System;
    public class Location
    {
       private string locationName;
    
       public Location(string name) => Name = name; //构造函数
    
       public string Name
       {
          get => locationName;   //get属性
          set => locationName = value;  //set属性
       }
    
       public override string ToString() => GetType().Name;
    
       ~Location() => Console.WriteLine($"The {ToString()} finalizer is executing."); //析构函数
    
       private string[] types = { "Baseball", "Basketball", "Football",
                                  "Hockey", "Soccer", "Tennis",
                                  "Volleyball" };
    
       public string this[int i] 
       {
          get => types[i];            //索引器
          set => types[i] = value;
       }
    }
    

    C# 7.1的特性[編輯]

    1. async``Main方法
    2. default常值運算式
    3. 推斷的 tuple 項目名稱

    C# 7.2的特性[編輯]

    1. 具備實值型別的參考語意
    2. 無後置具名引數
    3. 數值常值中的前置底線
    4. private protected 存取修飾詞

    C# 8.0的特性[編輯]

    1. 可空參照類型
    2. await yield return可非同步返回的迭代器
    3. Index 索引類型和Range區間類型
    4. 允許在聲明介面時為介面成員提供預設實現
    5. 遞迴的模式匹配
    6. 表達式形式的Switch關鍵字
    7. 在編譯器可做類型推斷的情況下,允許進一步省略類型聲明

    C# 9的特性[編輯]

    新的「Record」類型[編輯]

    記錄類型, 是一種參照類型, 預設是不可變的。 記錄類型的相等判斷可以通過參照或者結構進行判斷的。

    • 優點:記錄類型是輕量級的不可變類型,可以減少大量的代碼, 可以按照結構和參照進行比較;
    • 缺點:需要實例化大量的對象;
    // 默认不可变的记录类型
    public record Person(string Name, int Age);
    
    // 可变记录类型
    public record MutablePerson(string Name, int Age)
    {
        public string Name { get; set; } = Name;
        public int Age { get; set; } = Age;
    }
     
    var person1 = new Person("Alice", 40);
    var person2 = new Person("Alice", 40);
     
    Console.WriteLine(person1 == person2); // True 结构相同
    Console.WriteLine(person1.Equals(person2)); // True 结构相同
    Console.WriteLine(ReferenceEquals(person1, person2)); // False, 引用不同
     
    // 改变默认的记录! --> 创建一个新的记录。
    var person3 = person1 with { Age = 43 };
    Console.WriteLine(person3 == person1); // False 结构不同
     
    // 解构 (Destruct) 一个记录, 将记录的属性提取为本地变量
    var (name, age) = person3;
     
    var person4 = new MutablePerson("Alice", 40);
    person4.Age = 43;
     
    // 记录类型也可以被继承
    public record Citizen(string Name, int Age, string Country) : Person(Name, Age);
    var citizen = new Citizen("Alice", 40, "China");
    Console.WriteLine(person1 == citizen); // False 类型不同;
    

    「init」存取子[編輯]

    init存取子表示該屬性所屬類型僅能在建構函式(Constructor)中或是屬性初始化式子中賦予其值,如果嘗試在其他地方設定該屬性的值,在編譯時便會遭編譯器阻止。

    範例如下:在這個範例中,建立了一個Student類型,並且屬性StudentNameStudentID只能在初始化時賦予其值。

    public class Student
    {
    	public Student()
        {
    	}
    
    	public Student(string studentName,string studentID)
    	{
    		StudentName = studentName;
    		StudentID = studentID;
    	}
    
    	public string StudentName { get; init; } = "Default Name";
    	public string StudentID { get; init; } = "00000000";
    }
    

    如果在此時撰寫以下程式碼:

    Student DemoStudent = new Student();
    DemoStudent.StudentName = "Test Name";
    

    編譯器便會無法編譯並且擲回錯誤。

    而如果要建立學生名稱為「Test Name」,學生ID為「0001」的學生,則需要寫成:

    Student DemoStudent = new Student() //物件初始化運算式
    {
        StudentName = "Test Name";
        StudentID = "0001"
    };
    

    或是

    Student DemoStudent = new Student("Test Name","0001"); //藉由類型的建構式初始化StudentName以及StudentID。
    

    最上層語句或稱頂級語句[編輯]

    在以前的版本,開發者在撰寫最上層語句(如Program.cs)程式碼時,需要包含完整的namespace與class架構,因此如果要撰寫Hello World程式時,程式碼就會是:

    using System;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello World!");
            }
        }
    }
    

    但是在C# 9之後,最上層語句的程式碼不需要包含namespace以及class,可將其簡化為:

    using System;
    
    Console.WriteLine("Hello World!");
    //或者简化为一行语句:
    System.Console.WriteLine("Hello World!");
    

    注意, 一個程式中, 只能有一個檔案使用頂級語句, 並且頂級語句必須位於命名空間或類型定義之前。

    lambda棄元參數[編輯]

    Func<int, int, int> zero = (_, _) => 0;
    Func<int, int, int> func = delegate (int _, int _) { return 0; };
    

    在 C# 9 之前,即便不使用的 Lambda 參數也需要給它命名。C# 9 支援棄元參數一方面簡化了命名,另一方面也節省了主記憶體分配。更重要的是它使得編程的意圖更明確,讓人一看就知道這個參數是不用的,增強了代碼的可讀性和可維護性。

    只能初始化的設定器[編輯]

    Init only setters,只能通過對象初始化進行賦值的屬性。

    public class InitDemo
    {
        public string Start { get; init; }
        public string Stop { get; init; }
    }
     
    // initDemo.Start = "Now"; // Error
    // initDemo.End = "Tomorrow"; // Error
     
    var initDemo = new InitDemo
    {
        Start = "Now",
        Stop = "Tomorrow"
    };
    

    函式指標[編輯]

    使用 delegate* 可以聲明函式指標。

    unsafe class FunctionPointer {
     static int GetLength(string s) => s.Length;
     delegate*<string, int> functionPointer = &GetLength;
    }
     
    public void Test() {
     Console.WriteLine(functionPointer("test")); // 4;
    }
    

    跳過本地初始化[編輯]

    [System.Runtime.CompilerServices.SkipLocalsInit]
    static unsafe void DemoLocalsInit() {
     int x;
     // 注意, x 没有初始化, 输出结果不确定;
     Console.WriteLine(*&x);
    }
    

    原生整數類型[編輯]

    兩個新的整數類型 nint 和 nunit , 依賴宿主機以及編譯設定。

    協變返回類型[編輯]

    協變返回類型為重寫方法的返回類型提供了靈活性。覆蓋方法可以返回從被覆蓋的基礎方法的返回類型衍生的類型。

    class Person
    {
        public virtual Person GetPerson() { return new Person(); }
    }
    
    class Student : Person
    {
        public override Student GetPerson() { return new Student(); }
    }
    

    模組初始化代碼[編輯]

    ModuleInitializerAttribute 為組件 (assembly) 定義初始化代碼, 當初始化/載入時執行, 可以類比類的靜態建構函式, 但是是組件級別的。

    • 必須是靜態的、無參數的、無返回值的方法;
    • 不能是範式方法,也不能包含在範式類中;
    • 不能是私有函式,必須是公開 (public) 或者內部 (internal) 的函式;

    靜態 lambda 表達式[編輯]

    static 修飾詞添加到 lambda 表達式或匿名方法 。這將無法擷取局部變數或實例狀態,從而防止意外擷取其他變數。

    分部方法擴充[編輯]

    移除了分部方法的下述限制:

    • 必須具有 void 返回類型。
    • 不能具有 out 參數。
    • 不能具有任何可訪問性(隱式 private )。

    初始化表達式的簡化[編輯]

    如果建立對象的類型已知時,可以在new表達式中省略該類型。

    Point p = new(1, 1);
    Dictionary<string, int> dict = new();
     
    Point[] points = { new(1, 1), new (2, 2), new (3, 3) };
    var list = new List<Point> { new(1, 1), new(2, 2), new(3, 3)};
    

    在本地函式上添加標記[編輯]

    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    namespace CoreApp2
    {  
        class Program
        {
            static void Main(string[] args)
            {
                [Conditional("DEBUG")]
                static void DoSomething([NotNull] string test)
                {
                    System.Console.WriteLine("Do it!");
                }
                DoSomething("Doing!");
            }
       }
    }
    

    GetEnumerator 擴充[編輯]

    可以為任意類型添加一個 GetEnumerator 擴充方法, 返回一個 IEnumerator 或者 IAsyncEnumerator 實例, 從而在 foreach 迴圈中使用。

    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    namespace CoreApp2
    {
        public static class Extensions
        {
            public static IEnumerator<T> GetEnumerator<T>(this IEnumerator<T> enumerator) => enumerator;
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                IEnumerator<string> enumerator = new Collection<string> {"A", "B", "C"}.GetEnumerator();
                foreach (var item in enumerator)
                {
                    Console.WriteLine(item);
                }
            }
        }
    }
    

    模式匹配增強[編輯]

    Type patterns 類型匹配,判斷一個變數的類型

    object obj = new int();
    var type = obj switch
    {
        string => "string",
        int => "int",
        _ => "obj"
    };
    Console.WriteLine(type); // int
    

    Relational patterns 關係匹配:

    class Person
    { 
        public string name; 
        public int age; 
        public Person(string a, int b) { name = a;age = b; }
        public void Deconstruct(out string a,out int b){a = name;b = age; }
    }
    
    class Program
    {        
        static void Main(string[] args)
        {
            var person1 = new Person("Alice", 40);
            var inRange = person1 switch
            {
                (_, < 18) => "less than 18",
                (_, > 18) => "greater than 18",
                (_, 18) => "18 years old!"
            };
            Console.WriteLine(inRange); // greater than 18
        }
    }
    

    Conjunctive and patterns 邏輯合取匹配:

    // And pattern
    var person1 = new Person("Alice", 40);
    var ageInRange = person1 switch
    {
        (_, < 18) => "less than 18",
        ("Zhang Zhimin", _) and (_, >= 18) => "Alice is greater than 18"
    };
    Console.WriteLine(ageInRange); // Alice is greater than 18
    

    Disjunctive or patterns 邏輯析取匹配:

    // Or pattern
    var person1 = new Person("Alice", 40);
    var ageInRange = person1 switch
    {
        (_, < 18) => "less than 18",
        (_, 18) or (_, > 18) => "18 or greater"
    };
    Console.WriteLine(ageInRange); // 18 or greater
    

    Negated not patterns 邏輯非匹配

    // Not pattern
    var person1 = new Person("Alice", 40);
    var meOrNot = person1 switch
    {
        not ("Alice", 40) => "Not me!",
        _ => "Me :-)"
    };
    Console.WriteLine(meOrNot); // Me :-)
    

    Parenthesized patterns 帶括號的優先級匹配:

    // Parenthesized patterns
    var is10 = new IsNumber(true, 10);
    var n10 = is10 switch
    {
        ((_, > 1 and < 5) and (_, > 5 and < 9)) or (_, 10) => "10",
        _ => "not 10"
    };
    Console.WriteLine(n10); // 10
    

    C# 10的特性[編輯]

    record struct[編輯]

    解決了 record 只能給 class 而不能給 struct 用的問題:

    record struct Point(int X, int Y);
    

    sealed record ToString 方法[編輯]

    可以把 record 里的 ToString 方法標記成 sealed

    struct 無參建構函式[編輯]

    無參建構函式使得new struct() 和 default(struct) 的語意不一樣

    用with新增的匿名類型對象[編輯]

    var x = new { A = 1, B = 2 };
    var y = x with { A = 3 };
    

    這裡 y.A 將會是 3 。

    全域的 using[編輯]

    可以給整個專案啟用 using,不需要每個檔案都寫一份。

    檔案範圍的 namespace[編輯]

    以前寫 namespace 還得帶一層大括號。現在如果一個檔案里只有一個 namespace 的話,直接在檔案開頭寫:namespace MyNamespace;

    常數字串插值[編輯]

    const string x = "hello";
    const string y = $"{x}, world!";
    

    lambda的改進[編輯]

    lambda 可以帶 attributes[編輯]

    f = [Foo] (x) => x; // 给 lambda 设置
    f = [return: Foo] (x) => x; // 给 lambda 返回值设置
    f = ([Foo] x) => x; // 给 lambda 参数设置
    

    指定返回值類型[編輯]

    此前 C# 的 lambda 返回值類型靠推導,C# 10允許在參數列之前顯式指定 lambda 返回值類型:

    f = int () => 4;
    

    支援 ref 、in 、out 等修飾[編輯]

    f = ref int (ref int x) => ref x; // 返回一个参数的引用
    

    頭等函式[編輯]

    函式可以隱式轉換到 delegate,於是函式上升為頭等函式(first function):

    void Foo() { Console.WriteLine("hello"); }
    var x = Foo;
    x(); // hello
    

    自然委託類型[編輯]

    lambda 可自動建立自然委託類型,於是不再需要寫出類型:

    var f = () => 1; // Func<int>
    var g = string (int x, string y) => $"{y}{x}"; // Func<int, string, string>
    var h = "test".GetHashCode; // Func<int>
    

    CallerArgumentExpression[編輯]

    使用CallerArgumentExpression這個attribute,編譯器會自動填充呼叫參數的表達式字串,例如:

    void Foo(int value, [CallerArgumentExpression("value")] string? expression = null)
    {
        Console.WriteLine(expression + " = " + value);
    }
    

    當你呼叫 Foo(4 + 5) 時,會輸出 4 + 5 = 9。這對測試框架極其有用

    tuple 的混合定義和使用[編輯]

    int y = 0;
    (var x, y, var z) = (1, 2, 3);
    

    於是 y 就變成 2 了,同時還建立了兩個變數 x 和 z,分別是 1 和 3 。

    介面支援抽象靜態方法[編輯]

    .NET 6中這個特性為preview特性。

    泛型 attribute[編輯]

    在方法上指定 AsyncMethodBuilder[編輯]

    在方法上用 [AsyncMethodBuilder(...)],來使用自己實現的 async method builder,代替內建的 Task 或者 ValueTask 的非同步方法構造器。有助於實現零開銷的非同步方法。

    line 指示器支援行列和範圍[編輯]

    以前 #line 只能用來指定一個檔案中的某一行,現在可以指定行列和範圍:

    #line (startLine, startChar) - (endLine, endChar) charOffset "fileName"
    // 比如 #line (1, 1) - (2, 2) 3 "test.cs"
    

    巢狀屬性模式匹配改進[編輯]

    以前在匹配巢狀屬性的時候需要這麼寫:

    if (a is { X: { Y: { Z: 4 } } }) { ... }
    

    現在只需要簡單的:

    if (a is { X.Y.Z: 4 }) { ... }
    

    改進的字串插值[編輯]

    實現接近零開銷的字串插值。

    Source Generator v2[編輯]

    包括強型別的代碼構建器,以及增量編譯的支援等

    C# 11的特性[22][編輯]

    泛型屬性[編輯]

    C# 11 開始支援屬性(attribute)為泛型類,即允許聲明基礎類別為System.Attribute的泛型類:

    public class GenericAttribute<T> : Attribute { }
    

    靜態介面方法[編輯]

    C# 11 開始允許介面中定義靜態方法(包括運算子多載方法),實現該介面的類必須包含該靜態方法[23]

    public interface IGetNext<T> where T : IGetNext<T>
    {
        static abstract T operator ++(T other);
    }
    

    無符號右移運算子 >>>[編輯]

    新增無符號右移運算子 >>>,用於對帶符號數進行邏輯右移[24]

    泛型數學支援[編輯]

    對泛型及其對象進行數學操作的支援。基於靜態介面方法特性,自 .NET 8.0 起,在System命名空間中提供數學運算相關泛型介面,以支援泛型的運算操作[25]

    public static TResult Sum<T, TResult>(IEnumerable<T> values)
        where T : INumber<T>
        where TResult : INumber<TResult>
    {
        TResult result = TResult.Zero;
    
        foreach (var value in values)
        {
            result += TResult.Create(value);
        }
    
        return result;
    }
    

    字串內插中的換行符[編輯]

    允許內插字串中{}內的文字跨多個行

    原始字串文字[編輯]

    原始字串文字以 """ 開始並以 """ 結束,允許多行字串,若為多行字串則以單獨的一行 """ 結束,且字串的縮排以末尾的 """ 的起始位置為基準。原始字串文字不進行任何跳脫操作,但允許字串內插(開頭的 $ 數量代表內插所需要的花括號數)[26]

    var x = 1;
    var y = 2;
    var code1 = """int i = 0;""";
    var code2 = $"""int x = {x};""";
    var code3 = $$"""
        #include <stdio.h>
        int main(void) {
            const char *s = "{y} = {{y}}";  // {y} = 2
            return 0;
        }
        """;
    Console.WriteLine($"code1:\n{code1}\n");
    Console.WriteLine($"code2:\n{code2}\n");
    Console.WriteLine($"code3:\n{code3}\n");
    

    UTF-8 字串字面量[編輯]

    可以對字串字面量指定 u8 字尾來指定 UTF-8 字元編碼的字串字面量,其類型為ReadOnlySpan<byte>[27]

    列表模式[編輯]

    使用[]可以定義列表模式,用於模式匹配

    int[] numbers = { 1, 2, 3 };
    
    Console.WriteLine(numbers is [1, 2, 3]);             // True
    Console.WriteLine(numbers is [1, 2, 4]);             // False
    Console.WriteLine(numbers is [1, 2, 3, 4]);          // False
    Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]);  // True
    

    數值 IntPtrUIntPtr[編輯]

    C# 11 起 nintnuint 類型的別名分別為 IntPtrUIntPtr(C# 9 中它們僅被認為是「相似」的[28])。

    改進了方法組向委託的轉換[編輯]

    最佳化了方法組向委託轉換的效能。例如下述代碼中,在 C# 11 前,SumSumMethodGroup 效能更高[29]

    static readonly List<int> Numbers = Enumberable.Range(0, 100).ToList();
    
    public int Sum()
    {
        return Numbers.Where(x => Filter(x)).Sum(); // <- faster
    }
    
    public int SumMethodGroup()
    {
        return Numbers.Where(Filter).Sum();         // <- slower
    }
    
    static bool Filter(int number)
    {
        return number > 50;
    }
    

    C# 13的特性[30][編輯]

    params 集合[編輯]

    params 修飾詞不再僅限於陣列類型。現在可以將 params 用於任何已辨識的集合類型,包括 System.Span<T>System.ReadOnlySpan<T> 以及實現 System.Collections.Generic.IEnumerable<T> 並具有 Add 方法的類型。除了具體類型外,介面 System.Collections.Generic.IEnumerable<T>System.Collections.Generic.IReadOnlyCollection<T>System.Collections.Generic.IReadOnlyList<T>System.Collections.Generic.ICollection<T>System.Collections.Generic.IList<T> 也可以使用。[31]

    當使用介面類型時,編譯器會合成提供的參數的儲存。詳情請參考Params collections的功能規範頁面存檔備份,存於網際網路檔案館)。

    新的鎖對象[編輯]

    .NET 9 執行時引入了一種新的執行緒同步類型 System.Threading.Lock,該類型通過其 API 提供了更好的執行緒同步。Lock.EnterScope() 方法進入一個排他範疇,返回的 ref struct 支援 Dispose() 模式以退出排他範疇。C# 的 lock 語句辨識 Lock 對象,並使用更新的 API,而不是傳統的 System.Threading.Monitor API。如果將 Lock 對象轉換為其他類型,編譯器會生成基於 Monitor 的代碼。[32]詳情請參考該對象的功能規範頁面存檔備份,存於網際網路檔案館)。

    新的ESCAPE跳脫序列[編輯]

    可以使用 \e 作為 ESCAPE 字元 ( Unicode U+001B ) 的字面值跳脫序列。 在該版本以前,ESCAPE使用的是 \u001b\x1b[33]

    不建議使用 \x1b,因為如果 1b 後面的下一個字元是有效的十六進制數位,則那些字元會成為跳脫序列的一部分。[33]

    方法組自然特性[編輯]

    該特性對涉及方法組的多載解析進行了小幅最佳化。方法組是指具有相同名稱的所有多載方法。此前,編譯器會構建方法組的完整候選方法集,並從中確定自然類型。新的行為是在每個範疇修剪候選方法集,移除不適用的方法(通常是具有錯誤泛型參數或不滿足約束的泛型方法)。如果在給定範疇中找到的所有候選方法都不匹配,則方法組沒有自然類型。[34]

    以下是新行為的具體改進:

    概述[35][編輯]

    最佳化了方法組自然類型的確定:

    1. 按範疇逐步考慮候選方法(首先是實例方法,然後是每個後續範疇的擴充方法)。
    2. 修剪沒有成功機會的候選方法,以免它們干擾確定唯一簽章:
      • 當沒有提供類型參數時,修剪泛型實例方法(如 var x = M;)。
      • 基於是否能減少擴充和約束來修剪泛型擴充方法。

    背景[36][編輯]

    在 C# 10 中,方法組獲得了一種弱自然類型。這種類型是「弱型別」,僅在方法組未被目標類型化時才會發揮作用(即它在 System.Action a = MethodGroup; 中不起作用)。這種弱自然類型允許諸如 var x = MethodGroup; 的場景。[37]

    方法組在所有候選方法具有共同簽章時具有自然類型。如果方法組可能包含擴充方法,則候選方法包括包含類型和所有擴充方法範疇。

    應用[36][編輯]

    在實踐中,這意味著我們將:

    1. 構建所有候選方法的集合:
      • 如果方法在相關類型上,如果它們是靜態的且接收者是類型,或者它們是非靜態的且接收者是值,則這些方法在集合中。
      • 可以減少的所有範疇中的擴充方法也在集合中。
    2. 如果所有候選方法的簽章不匹配,則方法組沒有自然類型。
    3. 如果結果簽章的參數數量與提供的類型參數數量不匹配,則方法組沒有自然類型。
    4. 否則,結果簽章將用作自然類型。

    提案[38][編輯]

    原則是按範疇逐步進行,並儘早修剪我們知道無法成功的候選方法(與多載解析中使用的原則相同)。

    對於每個範疇,我們構建所有候選方法的集合:

    • 對於初始範疇,如果方法在相關類型上且其參數數量與提供的類型參數數量匹配,並且滿足提供的類型參數的約束,則這些方法在集合中;如果它們是靜態的且接收者是類型,或者它們是非靜態的且接收者是值。
    • 對於後續範疇,如果擴充方法可以用提供的類型參數替換,並使用接收者的值進行減少,同時滿足約束,則這些方法在集合中。
    1. 如果在給定範疇中沒有候選方法,則繼續到下一個範疇。
    2. 如果所有候選方法的簽章不匹配,則方法組沒有自然類型。
    3. 否則,結果簽章將用作自然類型。
    4. 如果所有範疇都已耗盡,則方法組沒有自然類型。

    隱式索引訪問[編輯]

    現在可以在對象初始化表達式中使用隱式「從末尾」索引運算子 ^[39]

    例如,可以在對象初始化器中初始化陣列:

    var countdown = new TimerRemaining()
    {
        buffer =
        {
            [^1] = 0,
            [^2] = 1,
            [^3] = 2,
            [^4] = 3,
            [^5] = 4,
            [^6] = 5,
            [^7] = 6,
            [^8] = 7,
            [^9] = 8,
            [^10] = 9
        }
    };
    

    上述範例建立了一個從 9 到 0 遞減的陣列。

    在 C# 13 之前,^ 運算子不能在對象初始化器中使用,必須從前面索引元素。

    迭代器和非同步方法中的 refunsafe[編輯]

    在 C# 13 之前,迭代器方法(使用 yield return 的方法)和非同步方法不能聲明本地 ref 變數,也不能有 unsafe 上下文。在 C# 13 中,非同步方法可以聲明本地 ref 變數或 ref struct 類型的本地變數,但這些變數不能跨越 await 邊界訪問。同樣,它們也不能跨越 yield return 邊界訪問。這一放寬的限制使編譯器能夠在更多地方允許可驗證的安全使用 ref 本地變數和 ref struct 類型。你可以在這些方法中安全地使用 System.ReadOnlySpan<T> 等類型。如果違反了安全規則,編譯器會發出警告。[40]

    ref struct 介面[編輯]

    在 C# 13 之前,ref struct 類型不能實現介面。從 C# 13 開始,它們可以實現介面。為了確保 ref 安全規則,ref struct 類型不能轉換為介面類型。這是一種裝箱轉換,可能違反 ref 安全。[41]

    allows ref struct[編輯]

    在 C# 13 之前,ref struct 類型不能作為泛型類型或方法的類型參數聲明。現在,泛型類型聲明可以添加反約束 allows ref struct。這種反約束聲明該類型參數提供的類型參數可以是 ref struct 類型。編譯器在該類型參數的所有實例上強制執行 ref 安全規則。這使得 System.Span<T>System.ReadOnlySpan<T> 等類型可以在適用的地方與泛型演算法一起使用。[42]

    詳情請參閱 where 更新頁面存檔備份,存於網際網路檔案館)和泛型約束編程指南頁面存檔備份,存於網際網路檔案館)文章。

    更多的 partial 成員[編輯]

    在 C# 13 中,可以聲明 partial 屬性和 partial 索引器。partial 修飾的屬性和索引器通常遵循與partial方法相同的規則:建立一個聲明聲明和一個實現聲明。兩個聲明的簽章必須匹配。一個限制是自動屬性聲明無法被用來實現partial 屬性。未聲明主體的屬性被視為聲明聲明[43]詳情請參閱Partial members頁面存檔備份,存於網際網路檔案館)文章。

    多載解析優先級[編輯]

    在 C# 13 中,編譯器辨識 OverloadResolutionPriorityAttribute 以優先選擇一個多載而不是另一個。庫作者可以使用此屬性確保新的、更好的多載優先於現有多載。例如,你可能會添加一個效能更高的新多載。你不希望破壞使用你庫的現有代碼,但希望使用者在重新編譯時更新到新版本。你可以使用多載解析優先級來通知編譯器應優先選擇哪個多載。優先級最高的多載會被優先選擇。此功能旨在幫助庫作者在添加新多載時避免歧義。庫作者應謹慎使用此屬性以避免混淆。[44]

    程式的執行[編輯]

    C#通常不被編譯成為能夠直接在電腦上執行的二進制本地代碼。與Java類似,它被編譯成為中間代碼(Microsoft Intermediate Language),然後通過.NET Framework虛擬機器——被稱為通用語言執行層——執行。

    所有的.Net程式語言都被編譯成這種被稱為通用中間語言的中間代碼。因此雖然最終的程式在表面上仍然與傳統意義上的可執行檔都具有「.exe」的字尾名。如果電腦上沒有安裝.Net Framework,那麼這些程式會彈出對話方塊,要求使用者下載.net framework。

    在程式執行時,.Net Framework將中間代碼翻譯成為二進制機器碼,從而使它得到正確的執行。最終的二進制代碼被儲存在一個緩衝區(Buffer)中。所以一旦程式使用了相同的代碼,那麼將會呼叫緩衝區中的版本。這樣如果一個.Net程式第二次被執行,那麼這種翻譯不需要進行第二次,速度明顯加快。

    標準化[編輯]

    微軟公司已經向ECMA申請將C#作為一種標準。在2001年12月,ECMA發布了ECMA-334 C#語言規範。C#在2003年成為一個ISO標準(ISO/IEC 23270)。現在有一些獨立的實現正在進行,包括:

    範例[編輯]

    C# 的Hello World程式[編輯]

    下面是一個在命令提示字元上輸出Hello World的小程式,這種程式通常作為開始學習程式語言的第一個步驟:

    using System;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello World!");
            }
        }
    }
    

    實現[編輯]

    微軟正在引領開源參考 C# 編譯器和工具集的開發。 第一個編譯器 Roslyn編譯成中間語言(IL),第二個編譯器 RyuJIT,[45]是一個 JIT(即時)編譯器,它是動態的,進行動態最佳化並編譯將 IL 轉換為 CPU 前端的本機代碼。[46]RyuJIT 是開源的,用 C++ 編寫。[47]Roslyn 完全是用 受控代碼 (C#)編寫的,已經開放並且功能以 API 的形式出現。因此,它使開發人員能夠建立重構和診斷工具。[1][48]官方實現的兩個分支是 .NET Framework(閉源,僅限 Windows)和 .NET Core(開源,跨平台);它們最終融合為一個開源實現:.NET 5.0。[49]在 .NET Framework 4.6 中,新的 JIT 編譯器取代了前者。[45][50]

    其他 C# 編譯器(其中一些包括公共語言基礎結構和 .NET 類別程式庫的實現):

    遊戲引擎 Unity 使用C# 作為其主要手稿語言。由於Microsoft 捐贈了 24,000 美元, Godot 遊戲引擎實現了一個可選的 C# 模組。

    參考文獻[編輯]

    1. ^ 1.0 1.1 The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.: dotnet/roslyn. November 13, 2019 [2021-08-16]. (原始內容存檔於2021-02-22) –透過GitHub. 
    2. ^ CoreCLR is the runtime for .NET Core. It includes the garbage collector, JIT compiler, primitive data types and low-level classes.: dotnet/coreclr. November 13, 2019 [2021-08-16]. (原始內容存檔於2019-10-14) –透過GitHub. 
    3. ^ Rich Hickey Q&A by Michael Fogus. [2017-01-11]. 原始內容存檔於2017-01-11. 
    4. ^ 4.0 4.1 Using C# 3.0 from .NET 2.0. Danielmoth.com. 2007-05-13 [2012年10月4日]. (原始內容存檔於2012-09-29). 
    5. ^ 存档副本. [2018-09-06]. (原始內容存檔於2018-01-22). 
    6. ^ 6.0 6.1 6.2 6.3 存档副本. [2018-09-06]. (原始內容存檔於2018-01-22). 
    7. ^ 7.0 7.1 What's new in C# 10. docs.microsoft.com. [2021-11-10]. (原始內容存檔於2022-02-08) (en-us). 
    8. ^ Visual Studio 2022 version 17.0 Release Notes. docs.microsoft.com. [2022-06-24]. (原始內容存檔於2022-08-06). 
    9. ^ DeDiv-VR. Visual Studio 2022 version 17.4 Release Notes. learn.microsoft.com. 2024-06-11 [2024-07-15]. (原始內容存檔於2023-08-06) (en-us). 
    10. ^ BillWagner. What's new in C# 12. learn.microsoft.com. 2024-06-04 [2024-07-15]. (原始內容存檔於2023-07-20) (en-us). 
    11. ^ Murphy, Adrian. Visual Studio 17.8 now available!. Visual Studio Blog. 2023-11-14 [2024-07-15]. (原始內容存檔於2025-01-14) (en-US). 
    12. ^ BillWagner. What's new in C# 13. learn.microsoft.com. 2024-09-14 [2024-09-20]. (原始內容存檔於2024-11-13) (en-us). 
    13. ^ DeDiv-VR. Visual Studio 2022 Preview Release Notes. learn.microsoft.com. 2024-09-19 [2024-09-20]. (原始內容存檔於2024-12-26) (en-us). 
    14. ^ An Introduction to C# Generics. [2020-09-25]. (原始內容存檔於2019-09-24). 
    15. ^ Anonymous Methods (C#). [2008-10-24]. (原始內容存檔於2008-04-17). 
    16. ^ Covariance and Contravariance in Delegates (C#). [2008-10-24]. (原始內容存檔於2008-10-12). 
    17. ^ Tim Anderson. C# pulling ahead of Java - Lead architect paints rosy C# picture. Reg Developer. The Register. 2006-11-14 [2007-01-20]. (原始內容存檔於2007-01-21). 
    18. ^ LINQ. Microsoft MSDN. 2007 [2007-08-13]. (原始內容存檔於2007-01-16) (English). 
    19. ^ The Mellow Musings of Dr. T : What is a collection?. [2008-10-24]. (原始內容存檔於2008-12-18). 
    20. ^ Partial Methods. [2007-10-06]. (原始內容存檔於2007-10-16). 
    21. ^ 一覽 C# 7.0 中的新功能. [2016-09-14]. (原始內容存檔於2018-10-02). 
    22. ^ C# 11 中的新增功能. learn.microsoft.com. [2024-3-19]. (原始內容存檔於2024-03-19) (中文(中國大陸)). 
    23. ^ 教程:探索 C# 11 功能 - 接口中的静态虚拟成员. learn.microsoft.com. [2024-3-20]. (原始內容存檔於2024-03-19) (中文(中國大陸)). 
    24. ^ 位运算符和移位运算符(C# 参考). learn.microsoft.com. [2024-3-20]. (原始內容存檔於2024-03-19) (中文(中國大陸)). 
    25. ^ Preview Features in .NET 6 – Generic Math. devblogs.microsoft.com. [2024-3-20]. (原始內容存檔於2024-02-01) (en-us). 
    26. ^ C# 程序设计基础. docs.eesast.com. [2024-3-20]. (原始內容存檔於2024-03-19) (中文(中國大陸)). 
    27. ^ Utf8 Strings Literals. learn.microsoft.com. [2024-3-20]. (原始內容存檔於2024-03-04) (en-us). 
    28. ^ Introducing C# 11: Numeric IntPtr and UIntPtr. anthonygiretti.com. [2024-3-20]. (原始內容存檔於2023-11-30) (en-us). 
    29. ^ C# 11 - Improved Method Group. prographers.com. [2024-3-20]. (原始內容存檔於2023-09-30) (en-us). 
    30. ^ BillWagner. C# 13 中的新增功能 - C# 指南 - C#. learn.microsoft.com. 2024-03-25 [2024-09-20]. (原始內容存檔於2024-12-17) (中文(中國大陸)). 
    31. ^ BillWagner. What's new in C# 13. learn.microsoft.com. 2024-09-14 [2024-09-20]. (原始內容存檔於2024-11-13) (en-us). 
    32. ^ BillWagner. What's new in C# 13. learn.microsoft.com. 2024-09-14 [2024-09-20]. (原始內容存檔於2024-11-13) (en-us). 
    33. ^ 33.0 33.1 BillWagner. C# 13 中的新增功能 - C# 指南 - C#. learn.microsoft.com. 2024-03-25 [2024-09-20]. (原始內容存檔於2024-12-17) (中文(中國大陸)). 
    34. ^ BillWagner. What's new in C# 13. learn.microsoft.com. 2024-09-14 [2024-09-20]. (原始內容存檔於2024-11-13) (en-us). 
    35. ^ dotnet-bot. Method group natural type improvements. learn.microsoft.com. 2024-09-17 [2024-09-20]. (原始內容存檔於2025-01-14) (en-us). 
    36. ^ 36.0 36.1 dotnet-bot. Method group natural type improvements. learn.microsoft.com. 2024-09-17 [2024-09-20]. (原始內容存檔於2025-01-14) (en-us). 
    37. ^ csharplang/proposals/csharp-10.0/lambda-improvements.md at main · dotnet/csharplang. GitHub. [2024-09-20]. (原始內容存檔於2025-01-11) (English). 
    38. ^ dotnet-bot. Method group natural type improvements. learn.microsoft.com. 2024-09-17 [2024-09-20]. (原始內容存檔於2025-01-14) (en-us). 
    39. ^ BillWagner. What's new in C# 13. learn.microsoft.com. 2024-09-14 [2024-09-20]. (原始內容存檔於2024-11-13) (en-us). 
    40. ^ BillWagner. What's new in C# 13. learn.microsoft.com. 2024-09-14 [2024-09-20]. (原始內容存檔於2024-11-13) (en-us). 
    41. ^ BillWagner. What's new in C# 13. learn.microsoft.com. 2024-09-14 [2024-09-20]. (原始內容存檔於2024-11-13) (en-us). 
    42. ^ BillWagner. What's new in C# 13. learn.microsoft.com. 2024-09-14 [2024-09-20]. (原始內容存檔於2024-11-13) (en-us). 
    43. ^ BillWagner. What's new in C# 13. learn.microsoft.com. 2024-09-14 [2024-09-20]. (原始內容存檔於2024-11-13) (en-us). 
    44. ^ BillWagner. What's new in C# 13. learn.microsoft.com. 2024-09-14 [2024-09-20]. (原始內容存檔於2024-11-13) (en-us). 
    45. ^ 45.0 45.1 The RyuJIT transition is complete!. microsoft.com. June 19, 2018 [July 20, 2021]. (原始內容存檔於July 19, 2019). 
    46. ^ Managed Execution Process. microsoft.com. [July 20, 2021]. (原始內容存檔於December 23, 2017). 
    47. ^ coreclr/src/jit/. github.com. [July 20, 2021]. (原始內容存檔於January 9, 2019). 
    48. ^ C# Guide. docs.microsoft.com. [2017-11-20]. (原始內容存檔於2022-08-13). 
    49. ^ 5.0.8. microsoft.com. [July 20, 2021]. (原始內容存檔於April 23, 2020). 
    50. ^ Mitigation: New 64-bit JIT Compiler. microsoft.com. [July 20, 2021]. (原始內容存檔於April 5, 2018). 

    外部連結[編輯]

    Module:Authority_control第183行Lua錯誤:attempt to index field 'wikibase' (a nil value)