stanford-oval/wikipedia huggingface dataset:
C Sharp语法
C# 2.0的特性 > 分部類別

分部類別将類別的实现分在多个文件中。该概念于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# 2.0的特性 > 泛型

泛型，或参数化类型，是被C#支持的.NET 2.0特性。不同于C++模版，.NET参数化类型是在运行时被实例化，而不是编译时，因此它可以跨语言，而C++模版却不行。C#泛型类在编译时，先生成中间代码IL，通用类型符号T只是一个占位符；在实例化类时，根据实际数据类型代替T并由即时编译器（JIT）生成本地代码，其中使用了实际的数据类型，等同于用实际类型写的普通的类。
它支持的一些特性并不被C++模版直接支持，比如约束泛型参数实现一个接口。另一方面，C# 不支持无类型的泛型参数。不像Java中的泛型，在CLI虚拟机中，.NET generics使用具化生成泛型参数，它允许优化和保存类型信息。
泛型类中，可以用where关键字对参数类型实现约束。例如：
public class Node<T, V> where T : Stack, IComparable, new(),class where V: Stack,struct
 {...}
上述表示T和V必须是Stack类或其派生类，T必须继承了IComparable接口、有无参构造函数、是引用类型；V必须是值类型。
泛型不仅能作用在类上，也可单独用在类的方法上，称为“泛型方法”。
泛型类的静态成员变量在相同封闭类间共享，不同的封闭类间不共享。
泛型类中的方法重载，参数类型T和V在运行时确定，不影响这个类通过编译。C#的泛型是在实例的方法被调用时检查重载是否产生混淆，而不是在泛型类本身编译时检查。特别地，当一般方法与泛型方法具有相同的签名时，会覆盖泛型方法。
C# 2.0的特性 > 静态類別

静态類別它不能被实例化，并且只能有静态成员。这同很多过程语言中的模块概念相类似。
C# 2.0的特性 > 迭代器

一种新形式的迭代器它提供了函数式编程中的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等
C# 2.0的特性 > 匿名方法

匿名方法类似于函数式编程中的闭包。匿名方法是通过使用 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 == ...)
        { 
            // ... 
        }

        // ...
    });
}
C# 2.0的特性 > 委托的协变和逆变

委托签名的协变和逆变,
C# 2.0的特性 > 属性访问器可以被单独设置访问级别

例子：
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
}
C# 2.0的特性 > 可空类型

可空类型（跟个问号，如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)");
C# 2.0的特性 > ??運算子

（??）：如果左运算数表达式的值不为空值时回傳该值，如果为空值则返回右运算数表达式的值。
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的一部分，它的新特性灵感来自于函数式编程语言，如：Haskell和ML，并广泛地引入了Language Integrated Query（LINQ）模式到通用語言運行庫中e.
C# 3.0的特性 > Linq

语言集成查询（英語：，缩写：LINQ）：  上下文相关关键字"from, where, select"可用于查询SQL、XML、集合等。这些标识符在LINQ上下文中被作为关键字，但是它们的增加不会破坏原有的名为from、where或select的变量。
C# 3.0的特性 > 类型初始化器

Customer c = new Customer();
c.Name = "James";
可写作：
Customer c = new Customer() { Name="James" };
C# 3.0的特性 > 集合初始化器

MyList list = new MyList();
list.Add(1);
list.Add(2);
可写作
MyList list = new MyList { 1, 2 };
假设MyList实现了System.Collections.IEnumerable且有一个Add方法method
C# 3.0的特性 > 匿名類型

var x = new { Name="James" };
C# 3.0的特性 > 局部变量类型推断

局部变量类型推断：
var x = new Dictionary<string, List<float>>();
等同于
Dictionary<string, List<float>> x = new Dictionary<string, List<float>>();
它只是一个语法糖，这个特性被匿名类型声明时所需要
C# 3.0的特性 > 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委托。
C# 3.0的特性 > 自动化属性

编译器将自动生成私有变量和适当的getter（get访问器）和setter（set访问器），如：
public string Name
{
    get; 
    set; 
}
C# 3.0的特性 > 扩展方法

扩展方法能够使现有的类型添加方法，而无需创建新的派生类型、重新编译或以其它方式修改原始类型。
使用扩展方法，必须在一个非嵌套、非泛型的静态类中定义一个静态方法，方法第一个参数必须附加this关键字作为前缀，第一个参数不能有其它修饰符（如ref或者out），这个方法将被编译器添加到该this的类型中。
public static class IntExtensions
{
    public static void PrintPlusOne(this int x) 
    {
        Console.WriteLine(x + 1);
    }
}
 
int foo = 0;
foo.PrintPlusOne();
注意事项：
扩展方法只会增加编译器的工作，但不会影响程序运行性能（用继承的方式为一个类型增加特性反而会影响性能）
如果原来的类中有一个方法，跟扩展方法一样，那么扩展方法不会被调用，编译器也不会提示
C# 3.0的特性 > 分部方法

允许代码生成器生成方法声明作为扩展点，如果有人在另一个部分类实现了它才会被包含于原代码编译。
分部方法（Partial methods）必须定义在分部类（partial classes）中
定义分部方法需要用partial做修饰符
分部方法不一定总是有执行内容的，也就是说定义的方法可以一句操作语句都没有
分部方法返回值必须是void
分部方法可以是静态（static）方法
分部方法可以包含参数，参数可以包含以下修饰词：this,ref,params
分部方法必须是私有（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, Python或Ruby。
dynamic关键字标记的实例被处理成一个特殊包装的object对象，取消了CLI的编译时类型检查，编译时被假定支持任何操作，但如果并不实际支持则运行时报错。
dynamic calc = GetCalculator();
int sum = calc.Add(10, 20);
C# 4.0的特性 > 具名參數與可選參數

public StreamReader OpenFile(
    string path,
    int bufferSize = 1024)
{
...
}
呼叫OpenFile時，順序可以完全顛倒：
OpenFile(bufferSize: 4096, path: "foo.txt");
C# 4.0的特性 > 與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的特性 > 泛型的协变和逆变

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的特性 > Async

async和await是一对语法糖，允许开发人员非常轻松的调用基于TASK的异步编程。async-await关键字并不会真的创建一个线程池任务，完成这个动作依赖于被调用方法中的函数。
C# 5.0的特性 > Caller info attributes

CallerInfoAttributes用于调试时访问调用者的信息。包括三个主要的类：
[CallerMemberName] ：返回调用函数的名称。
[CallerFilePath] ：返回调用函数所在源文件全路径信息 。
[CallerLineNumber] ：返回调用函数调用具体行号。
using System;
using System.Runtime.CompilerServices;

namespace TestPro
{
    class Program
    {
        public static void Main()
        {
            Log("Test.");
        } 

        // 对日志消息进行记录，同时所有内容均有默认值，如果获取失败，则使用默认值。
        public static void Log(string message,
            [CallerMemberName] string callerName = "unknown", 
            [CallerFilePath] string callerFilePath = "unknown", 
            [CallerLineNumber] int callerLineNumber = -1)
        {
            Console.WriteLine("Message: {0}", message);
            Console.WriteLine("Caller's Name: {0}", callerName);
            Console.WriteLine("Caller's FilePath: {0}", callerFilePath);
            Console.WriteLine("Caller's LineNumber: {0}", callerLineNumber);
        }
    }
}
/*
程序执行以后会显示以下内容。
Message: Test.
Caller Name: Main
Caller FilePath: C:UsersAdministratorsource
eposTestProProgram.cs
Caller Line number: 10
请按任意键继续. . .*/
C# 5.0的特性 > 绑定运算符

comboBox1.Text :=: textBox1.Text; //将文本框的内容绑定到下拉框。
C# 5.0的特性 > 带参数的泛型构造函数

这个的加入给一些设计增加了强大功能，泛型早在C#2.0加入后就有着强大的应用，一般稍微设计比较好的框架，都会用到泛型，C#5.0加入带参数泛型构造函数，则在原有基础上对C#泛型完善了很多。
class MyClass<T>
    where T : class, new ()
{
    public MyClass()
    {
        this.MyObject = new T();
    }

    T MyObject { get; set; }
}
C# 5.0的特性 > case支持表达式

以前case里只能写一个具体的常量，而现在可以加表达式
switch(myobj){
  case string.IsNullorEmpty(myotherobj):
 ..... 
  case myotherobj.Trim().Lower: 
 ....
}
C# 5.0的特性 > 扩展属性

[Associate(string)]
public static int MyExtensionProperty { get;set;}
C# 5.0的特性 > 支持null类型运算

int x? = null;
int y? = x + 40;

Myobject obj = null;
Myotherobj obj2 = obj.MyProperty ??? new Myotherobj();
C# 6.0的特性 > 只读自动属性

不必使用完整属性语法定义属性。可以在声明属性的位置或类型的构造函数中初始化属性。
class Person
    {
        //新语法
        private string Name { get; } = "Fanguzai";  //不用带上 private set;

        //旧语法
        public int Age { get; private set; } ;
    }
C# 6.0的特性 > 自动屬性初始化

class MyClass
       {
           public string Name { get; set; } = "Fanguzai";
       }
C# 6.0的特性 > 具有表达式体的函数成员

可以采用与用于 lambda 表达式相同的轻量语法，声明代码为单个表达式的成员。具有立即仅返回表达式结果，或单个语句作为方法主体。C# 6.0支持方法和属性get。C# 7.0扩展支持了构造函数、终结器、属性set、索引器。
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# 6.0的特性 > 使用靜態类

可以导入静态类型的可访问静态成员，以便可以在不使用类型名限定访问的情况下引用成员。
using System;
using static System.Console;

namespace _usingStatic
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hi,Fanguzai!");
            WriteLine("Hi,Fanguzai!");  // 使用了 using static System.Console;
        }
    }
}
C# 6.0的特性 > nameof 運算符

class Program
    {

        private static void Func1(int x) { }
         private string F<T>() => nameof(T);
        private void Func2(string msg) { }
 
         static void Main(string[] args)
         {
             var program = new Program();
 
             Console.WriteLine(nameof(System.Text));
             Console.WriteLine(nameof(Func1));
             Console.WriteLine(nameof(Program));
             Console.WriteLine(nameof(program));
             Console.WriteLine(nameof(F));
 
             Console.Read();
         }
    }
C# 6.0的特性 > 内插字符串

以$为前缀构造字符串。 内插字符串表达式类似于包含表达式的模板字符串。内插字符串表达式通过将包含的表达式替换为表达式结果的ToString表现形式来创建字符串。
var name = "Fanguzai";
            Console.WriteLine($"Hello, {name}");
想要在内插字符串中包含大括号“{” 或 “}”，使用两个大括号，即 “Template:” 或 “”。
C# 6.0的特性 > NULL 条件运算符

用于在执行成员访问 ?. 或索引 ?[ 操作之前，测试是否存在 NULL 值。
static void Main(string[] args)
         {
            string name = null;
            Console.WriteLine($"1：{name?.Length}");
            
            name = "Fanguzai";
            Console.WriteLine($"2：{name?.Length}");
            Console.WriteLine($"3: {name?[0]}");
        }

//普通的委托调用
             Func<int> func = () => 0;
             if (func!=null)
             {
                 func();
             }
 
             //简化调用
             func?.Invoke();
C# 6.0的特性 > Catch 和 Finally 區塊中的 Await

async Task Test()
         {
             var wc = new WebClient();
             try
             {
                 await wc.DownloadDataTaskAsync("");
             }
             catch (Exception)
             {
                 await wc.DownloadDataTaskAsync("");　　//OK
             }
             finally
             {
                 await wc.DownloadDataTaskAsync("");　　//OK
             }
         }
C# 6.0的特性 > 索引初始設定

var nums = new Dictionary<int, string>
            {
                [7] = "seven",
                [9] = "nine",
                [13] = "thirteen"
            };

            //这是旧的方式
            var otherNums = new Dictionary<int, string>()
            {
                {1, "one"},
                {2, "two"},
                {3, "three"}
            };
C# 6.0的特性 > 异常过滤器 (Exception filters)

try
            {
                var numbers = new Dictionary<int, string> {[7] = "seven",[9] = "nine",[13] = "thirteen" };
            }
            catch (ArgumentNullException e)
            {
                if (e.ParamName == "customer")
                {
                    Console.WriteLine("customer can not be null");
                }
            }
C# 7.0的特性 > 具有表达式体的函数成员

可以采用与用于 lambda 表达式相同的轻量语法，声明代码为单个表达式的成员。具有立即仅返回表达式结果，或单个语句作为方法主体。C# 6.0支持方法和属性get。C# 7.0扩展支持了构造函数、终结器、属性set、索引器。
class MyClass
        {
           public string this[int i] //索引器
           {
             get => types[i];
             set => types[i] = value;
            }

            private string[] types = { "Baseball", "Basketball", "Football","Hockey", "Soccer", "Tennis","Volleyball" };

            public MyClass(string name) => Name = name; //构造函数
            private string locationName;

            ~Destroyer() => Console.WriteLine($"The {ToString()} destructor is executing.");//终结器

             public string Name => locationName; //属性get

             public string Name{
                 get => locationName;
                 set => locationName = value; //属性set
             }
        }
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.0的特性 > out 變數

能夠直接宣告一個變數在它要傳入的地方，當成一個 out 的引數
static void AssignVal(out string strName)
        {
            strName = "I am from OUT";
        }
static void Main(string[] args)
        {
            AssignVal(out var szArgu); //无需提前声明该变量
        }
C# 7.0的特性 > 弃元

元组/对象的解构：
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));
}
C# 7.0的特性 > 元组

( string, string, string, string) getEmpInfo()
{
    //read EmpInfo from database or any other source and just return them
    string strFirstName = "abc";
    string strAddress = "Address";
    string strCity= "City";
    string strState= "State";
     return (strFirstName, strAddress, strCity, strState); // tuple literal
}
 
//Just call above method and it will return multiple values 
 var empInfo= getEmpInfo();
Console.WriteLine($"Emp info as  {empInfo .Item1} {empInfo .Item2} {empInfo .Item3} {empInfo .Item4}.");

//也可以给元组中各项命名：
(string strFName, string strAdd, string strC, string strSt) getEmpInfo_named()
{
    //code goes here
    //直接在元组文字中返回其名称，如下所示
    return (strFName: strFirstName, strAdd: strAddress, strCity: strC, strState: strSt);
} 
//Now when you call method get values with specific name as below 
var empInfo1= getEmpInfo();
Console.WriteLine($"Emp info as {empInfo1.strFName} {empInfo1.strAdd} {empInfo1.strC} {empInfo1.strSt}.");
.NET有Tuple类型，但是它是一个引用类型，会导致性能问题，但是C＃7.0带来了具有值类型的Tuple，该类型具有更快的性能和可变的类型。
大多数时候，不想访问整个元组包，或者只需要内部值，那么可以使用元组解构并获取所需的值
( string strFName,  string strAdd,  string strC, string strSt) = getEmpInfo(); 
    Console.WriteLine($"Address: { strAdd }, Country: { strC }");
C# 7.0的特性 > 记录类型

记录类型只不过是属性和变量的容器。借助记录类型可以减少工作量。
//一个带有属性，构造函数和变量的类，因此访问和声明变量需要编写更多代码:
    class studentInfo
    {
        string _strFName;
        string _strMName;
        string _strLName;
        studentInfo(string strFN, string strMN, string strLN){
            this._strFName = strFN;
            this._strMName = strMN;
            this._strLName = strLN;
        }
        public string StudentFName {get{ return this._strFName;}}
        public string StudentMName {get{ return this._strMName;}}
        public string StudentLName {get{ return this._strLName;}}
    }

//具有相同功能的记录类型:
class studentInfo(string StudentFName, string StudentMName, string StudentLName);
C# 7.0的特性 > 不可为空的引用类型

int objNullVal;     //non-nullable value type
int? objNotNullVal;    //nullable value type
string! objNotNullRef; //non-nullable reference type 不可为空的引用类型
string objNullRef;  //nullable reference type
C# 7.0的特性 > 本地方法

可以在其中使用out或ref。
private static void Main(string[] args)
{
    int local_var = 100;
    int LocalFunction(int arg1)
    {
        return local_var * arg1;
    } 
    Console.WriteLine(LocalFunction(100));
}
C# 7.0的特性 > 数值字面量中包含下划线分隔符以提高可读性

static void Main(string[] args)
        {
            var lit1 = 478_1254_3698_44;
            var lit2 = 0Xab_bc47;
            //C# also come with binary literal for bunary values
            var binLit = 0b1_00;
        }
C# 7.0的特性 > 模式匹配

允许在IS语句和SWITCH语句中把模式与任何数据类型匹配。模式可以是常量模式、类型模式、变量模式。
public  void Method1( object obj)
    {
        //following null is constant pattern
         if (obj  is null)  return;
        //datatype pattern, string is datatype that we check directly     
         if (obj  is  string st)
        { //code goes here }
        else
        return; 
    }

class Calculate();
class Add(int a, int b, int c) : Calculate;
class Substract(int a, int b) : Calculate;
class Multiply(int a, int b, int c) : Calculate;
 
Calculate objCal = new Multiply(2, 3, 4);
switch (objCal)
{
    case Add(int a, int b, int c):
        //code goes here
        break;
    case Substract(int a, int b):
        //code goes here
        break;
    case Multiply(int a, int b, int c):
        //code goes here
        break;
    default:
        //default case
        break;
}
C# 7.0的特性 > 变量作为Ref从方法返回

通过Ref传递一个变量，将它作为Ref返回，并将它们存储为Ref
class Program
    {
        static string emptyString;
        static ref string getFromList(string strVal, string[] Values)
        {            
            var kk = Values.GetLength(0);
            for (int i = 0; i < Values.GetLength(0); i++)
            {
                if (strVal == Values[i])
                    return ref Values[i]; //return location as ref not actual value
            }
            return ref emptyString;
        }
        static void Main(string[] args)
        {
            string[] values = { "a", "b", "c", "d" };
            ref string strSubstitute = ref getFromList("b", values);
            strSubstitute = "K"; // replaces 7 with 9 in the array
            Console.WriteLine(values[1]); // it prints "K"
        }
    }
在上面的示例中，我们通过从方法返回Ref找到并替换了字符串。
C# 7.0的特性 > 从表达式中抛出异常

public string getEmpInfo( string EmpName)
    {
        string[] empArr = EmpName.Split(",");
        return (empArr.Length > 0) ? empArr[0] : throw new Exception("Emp Info Not exist");
    }
C# 7.1的特性 > async Main方法

static async Task Main()//注意返回Task
{
    await AsyncMethod1();
}
C# 7.1的特性 > default常值運算式

Func<int, string> whereClause = default;
C# 7.1的特性 > 推斷的 tuple 項目名稱

int count = 3;
string colors = "colors of the flag";
var tupleCol = (count,colors); // here syntax gets trimmed
C# 7.2的特性 > 有条件的“ref”

ref var finalVal = ref (value1 != null ? ref val1_arr[0] : ref val2_arr[0]);
C# 7.2的特性 > 无需名称的非尾部命名参数

如果参数的顺序正确，则无需为参数配上名称
//suppose I have written a function and used below named arguments
EmpDetails(EmpID: 3, firstName: "Manavya", City: "Daswel");
 
//here in C#7.2, I can write the above code line as
EmpDetails(EmpID: 3, "Manavya", City: "Daswel");
 
//if you observed that firstName: "Manavya" is replaced by only "manavya" 
// and it is the beauty of the C#7.2
C# 7.2的特性 > 數值常值中的前置下划线分隔符

// 在C# 7.2中，_可以用在`0x`或`0b`之后
0x_1_2 // C# 7.2及更高版本可用
0b_1_0_1 // C# 7.2及更高版本可用
C# 7.2的特性 > 私有保护访问修饰符

只有当前项目里的继承关系才能用，出了这个程序集就没办法用了，即 private protected 为私有继承（protected 且 internal）。
C# 7.3的特性 > 改进stackalloc运算符

int* Array1 = stackalloc int[3] {5, 6, 7};//老语法

Span<int> Array = stackalloc [] {10, 20, 30};//新语法
C# 7.3的特性 > 固定语句支持更多类型

固定语句是防止垃圾回收器清除可移动变量的语句，可以使用fixed关键字创建这些语句。从C＃7.3开始，固定语句支持具有以下内容的任何类型：GetPinnableReference()方法，返回的ref T是固定的。
C# 7.3的特性 > 非托管约束

一个成员是一个非托管型，如果它是byte，short，sbyte，int，long，char，bool类型。可以使用非托管约束来显示类型参数必须是具有非指针的非托管类型。
unsafe public static byte[] convert_to_byte<T>(this T argument) where T : unmanaged
    {
        var size = sizeof(T);
        var result = new Byte[size];
        return result1;
    }
还可以使用System.Enum和System.Delegate作为基类约束。
C# 7.3的特性 > 元组支持等于和不等于运算符

var exp1 = (val1: 100, val2: 20);
    var exp2 = (val1: 100, val2: 20);
    exp1 == exp2; //it will return displays as 'true'
C# 7.3的特性 > 重载的“in”方法的更改

为“按引用”和“按值”方法命名相同的方法时，它会抛出歧义异常，为避免此错误，C＃7.3使用了“in”方法：
static void calculateArea(var1 arg);
    static void calculateArea(in var1 arg);
C# 7.3的特性 > 扩展参数边界

可以在构造函数初始值设定项、属性初始值设定项中定义out参数。
//here, we have defined the out parameter in constructor
    public class parent
    {
       public parent(int Input, out int Output)
       {
          Output = Input;
       }
    }
     
    //now let's use the above class in the following class
    public class Child : parent
    {
       public Child(int i) : base(Input, out var Output)
       {
          //"The value of 'Output' is " + Output
       }
    }
C# 7.3的特性 > 多个编译器选项

使用公钥签名程序集：添加参数作为-public签名。
从构建环境替换路径：用较早的映射源路径替换构建中的源路径：-pathmap:path1=sourcePath1,path2=sourcePath2
C# 8.0的特性

递归的模式匹配
在编译器可做类型推断的情况下，允许进一步省略类型声明
C# 8.0的特性 > 可释放的引用结构

声明为ref 的struct 无权实现任何接口，因为无权实现IDisposable 接口。必须使我们需要使用可释放的ref结构来访问void Dispose()方法。也可以配置readonly ref结构。
C# 8.0的特性 > 表达式形式的Switch关键字

switch用于模式匹配的表达式及其语法有所变化。
public enum RandomNum
    {
        One,
        Three,
        Five,
        Seven,
        Six,
    }

    public static string getRandomNum(RandomNum iNum) =>
        iNum switch //switch关键字在变量之后使用
        {
            RandomNum.One => return "1",
            RandomNum.Three => return "3",
            RandomNum.Five => return "5",
            RandomNum.Seven => return "7",
            RandomNum.Six => return "6",
            _              => throw new Exception("invalid number value"), //默认关键字由_（下划线）符号代替
        };
C# 8.0的特性 > 空值结合赋值运算符

??=空值结合赋值运算符（null-coalescing）：
some_Value ??= some_Value2;
以代替啰嗦的写法：
some_Value = some_Value ?? some_Value2;
List<int> lstNum = null;
    int? a = null;
     
    (lstNum ??= new List<int>()).Add(100);
    Console.WriteLine(string.Join(" ", lstNum)); 
     
    // the output would be : 100
     
    lstNum.Add(a ??= 0);
    Console.WriteLine(string.Join(" ", numbers));  // output: 100 0
    // the output would be : 100 0
C# 8.0的特性 > 局部静态函数

将局部函数设为static函数，可证明局部函数不包含内部封闭循环中的变量。
int Add()
    {
        int A = 5;
        return Sum(A);
     
        static int Sum(int val) => val + 3;
    }
C# 8.0的特性 > 默认接口方法

允许在声明接口时为接口成员提供默认实现。
=将结构成员设为只读

现在可以将struct成员设为只读，而不是将整个struct成员设置为只读。
public readonly struct getSqure1 //老的实现
    {
        public int InputA { get; set; }
        public int InputB { get; set; }
        public int output => Math.Pow(A,B);
     
        public override string ToString() =>
            $"The answer is : {output} ";
    }

    public struct getSqure //新的实现
    {
        public int InputA { get; set; }
        public int InputB { get; set; }
        public readonly int output => Math.Pow(A,B);
     
        public override string ToString() =>
            $"The answer is : {output} ";
    }
=将结构成员设为只读 > 插值字符串的增强

string以$开头，这样的string则称为插值string，可包含插值表达式：
string szName = "ABC";
    int iCount = 15;
     
    // String interpolation:
    Console.WriteLine($"Hello, {szName}! You have {iCount} apples");//输出将为“ Hello, ABC! You have 15 apples”
逐字字符串以@"开头。在C＃8中，$@""或者@$""表示可以通过@或$来开始string。在早期版本的C＃中，@仅在$之后被允许。