C# 與 .NET Framework 對應關系
下表中列出 C#、.NET、VS版本對應關系
C#版本 | 釋出時間 | .NET 版本 | VS版本 | CLR版本 |
C#1.0 | 2002-02-13 | .NET Framework 1.0 | VS.NET 2002 | 1.0 |
C#1.1 C#1.2 | 2003-04-24 | .NET Framework 1.1 | VS.NET 2003 | 1.1 |
C#2.0 C#3.0(除Linq) | 2005-11-07 | .NET Framework 2.0 | VS2005 | 2.0 |
C#3.0(除Linq) | 2006-11 | .NET Framework 3.0 | VS2008 | 2.0 |
C#3.0 | 2007-11-19 | .NET Framework 3.5 | VS2008 | 2.0 |
C#4.0 | 2010-4-12 | .NET Framework 4.0 | VS2010 | 4 |
C#5.0 | 2012-02-20 | .NET Framework 4.5 | VS2012 | 4 |
C#5.0 | 2013-10-17 | .NET Framework 4.5.1 | VS2013 | 4 |
C#5.0 | 2014-05-05 | .NET Framework 4.5.2 | VS2013 | 4 |
C#6.0 | 2015-07-26 | .NET Framework 4.6 | VS2015(v14) | 4 |
C#6.0 | 2015-11-30 | .NET Framework 4.6.1 | VS2015(v14) | 4 |
C#7.0 | 2016-08-02 | .NET Framework 4.6.2 | VS2017(v15) | 4 |
C#7.1 | 2017-04-05 | .NET Framework 4.7 | VS2017(v15.3) | 4 |
C#7.2 | 2017-10-17 | .NET Framework 4.7.1 | VS2017(v15.5) | 4 |
C#7.3 | 2018-04-30 | .NET Framework 4.7.2 | VS2017(v15.7) | 4 |
C#8.0 | 2019-04-18 | .NET Framework 4.8 | VS2019(v16) | 4 |
C#9.0 | 2020-11-11 | .NET 5 | VS2019(16.8) |
c#6.0文法
//1.隻讀自動屬性
{
Student student = new Student("Richard", "Richard01");
string fullName = student.ToString();
string fullName1 = student.FullName;
}
//2.using static
{
StaticClass.Next();
StaticClass.NextTo();
Next();
NextTo();
}
//3.Null 條件運算符
{
Student student = null;
// student.FirstName; //如果student為null 未将對象引用至對象的執行個體
//if (student!=null)
//{
// string fullName = student.FullName;
//}
string fullName = student?.FullName; //得到的結果一定是要支援null
int? id = student?.Id; //? 隻能為可空類型服務
student = new Student("AB", "CD");
fullName = student?.FullName;
string testName = student?.TestName ?? "朝夕教育";
student.TestName = "Zhaoxi教育";
testName = student?.TestName ?? "朝夕教育";
}
//4.字元串内插
{
//string.Format();
//stringBuilder
//string+
string firstName = "朝夕";
string lastName = "教育";
var strs = $"{{{firstName}}}-{lastName}-{firstName}-{firstName};{firstName}";
}
//5.異常篩選器
{
之前都是自定義不同的Exception 繼承Exception父類
//StaticClass.ExceptionShow();
}
//6.nameof 表達式
{
string clasName= "StaticClass";
string className1 = nameof(StaticClass);
Console.WriteLine(className1);
string className2 = nameof(SharpSixInfo);
Console.WriteLine(className2);
string className3 = nameof(Student);
Console.WriteLine(className3);
//7.什麼是事件?
NotifyPropertyChanged notifyPropertyChanged = new NotifyPropertyChanged();
notifyPropertyChanged.PropertyChanged += (object o, PropertyChangedEventArgs b) =>
{
};
notifyPropertyChanged.LastName = "朝夕教育";
}
//8.使用索引器初始化關聯集合
{
Dictionary<int, string> messages = new Dictionary<int, string>
{
{ 404, "Page not Found"},
{ 302, "Page moved, but left a forwarding address."},
{ 500, "The web server can't come out to play today."}
};
messages.Add(405,"朝夕教育");
messages.Remove(405, out string obj);
Console.WriteLine(obj);
Dictionary<int, string> webErrors = new Dictionary<int, string>
{
[404] = "Page not Found",
[302] = "Page moved, but left a forwarding address.",
[500] = "The web server can't come out to play today."
};
webErrors.Add(405, "朝夕教育");
webErrors.Remove(405, out string strResult);
}
c#7.0文法
#region Out變量
{
不需要聲明
//string input = Console.ReadLine();
//int.TryParse(input, out int result);
//Console.WriteLine(result);
out 修改是可以是var類型聲明
//int.TryParse("456", out var result1);
//Console.WriteLine(result1);
//Console.WriteLine("****************Out*****************");
out 變量
//DInfo dInfo = new DInfo(123);
}
#endregion
#region 元組
{
(string Alpha, string Beta) namedLetters = ("a", "b");
namedLetters.Alpha = "aa";
namedLetters.Beta = "bb";
Console.WriteLine($"{namedLetters.Alpha}, {namedLetters.Beta}");
var alphabetStart = (Alpha: "a", Beta: "b");
alphabetStart.Beta = "B+B";
alphabetStart.Alpha = "A+A";
Console.WriteLine($"{alphabetStart.Alpha}, {alphabetStart.Beta}");
(int max, int min) = Range();
Console.WriteLine(max);
Console.WriteLine(min);
}
{
var p = new Point(12, 13);
Console.WriteLine(p.X);
Console.WriteLine(p.Y);
p.Deconstruct(out double xx, out double yy);
Console.WriteLine(xx);
Console.WriteLine(yy);
}
#endregion
#region 棄元
{
var (_, _, _, pop1, _, pop2) = QueryCityDataForYears("New York City", 1960, 2010);
(string, double, int, int, int, int) result = QueryCityDataForYears("New York City", 1960, 2010);
}
#endregion
#region 模式
{
int input = 123;
int sum = 234;
if (input is int count)
sum += count;
}
{
//IEnumerable<object> enumerablelist = new List<object>()
//{
// 0,
// new List<int>(){ 0,1,2,3,4,5,6 },
// 100,
// null
//};
//int iResult = SumPositiveNumbers(enumerablelist);
/// <summary>
/// 模式
/// </summary>
/// <param name="sequence"></param>
/// <returns></returns>
public static int SumPositiveNumbers(IEnumerable<object> sequence)
{
int sum = 0;
foreach (var i in sequence)
{
switch (i)
{
case 0:
break;
case IEnumerable<int> childSequence:
{
foreach (var item in childSequence)
sum += (item > 0) ? item : 0;
break;
}
case int n when n > 0:
sum += n;
break;
case null:
throw new NullReferenceException("Null found in sequence");
default:
throw new InvalidOperationException("Unrecognized type");
}
}
return sum;
}
}
#region 本地方法
LocalFunction("朝夕教育");
public static string LocalFunction(string name)
{
return ZhxiToString(name);
string ZhxiToString(string name)
{
return name;
}
}
#endregion
#region 預設文本表達式
//Func<string, bool> whereClause = default(Func<string, bool>);
//Func<string, bool> whereClause1 = default;
//string str = default;
//int i = default;
#endregion
#region 數字文本文法改進
//二進制數形式寫入
//誤讀的數值常量可能使第一次閱讀代碼時更難了解。 位掩碼或其他符号值容易産生誤解。 C# 7.0 包括兩項新功能,可用于以最可讀的方式寫入數字來用于預期用途:二進制文本和數字分隔符 。
//在建立位掩碼時,或每當數字的二進制表示形式使代碼最具可讀性時,以二進制形式寫入該數字
int Sixteen = 0b0001_0000;
Console.WriteLine(Sixteen);
int ThirtyTwo = 0b0010_0000;
Console.WriteLine(ThirtyTwo);
int SixtyFour = 0b0100_0000;
Console.WriteLine(SixtyFour);
int OneHundredTwentyEight = 0b1000_0000;
Console.WriteLine(OneHundredTwentyEight);
//long類型
//常量開頭的 0b 表示該數字以二進制數形式寫入。 二進制數可能會很長,是以通過引入 _ 作為數字分隔符通常更易于檢視位模式,如前面示例中的二進制常量所示。 數字分隔符可以出現在常量的任何位置。 對于十進制數字,通常将其用作千位分隔符。 十六進制和二進制文本可采用 _ 開頭:
long BillionsAndBillions = 100_000_000_000;
Console.WriteLine(BillionsAndBillions);
//decimal、float 和 double
//數字分隔符也可以與 decimal、float 和 double 類型一起使用:
double AvogadroConstant = 6.022_140_857_747_474e23;
Console.WriteLine(AvogadroConstant);
decimal GoldenRatio = 1.618_033_988_749_894_848_204_586_834_365_638_117_720_309_179M;
Console.WriteLine(GoldenRatio);
#endregion
#region 命名實參
// 該方法可以通過使用位置參數以正常方式調用。
PrintOrderDetails("Gift Shop", 31, "Red Mug");
// 可以按任何順序為參數提供命名參數。
PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");
PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31);
// 與位置參數混合的命名參數有效
// 隻要它們被使用在正确的位置。
PrintOrderDetails("Gift Shop", 31, productName: "Red Mug");
PrintOrderDetails(sellerName: "Gift Shop", 31, productName: "Red Mug"); // C# 7.2 onwards
PrintOrderDetails("Gift Shop", orderNum: 31, "Red Mug"); // C# 7.2 onwards
但是,如果使用順序錯誤,則混合參數無效。
以下語句将導緻編譯器錯誤。
//PrintOrderDetails("Gift Shop", 31, productName: "Red Mug");
//PrintOrderDetails(31, sellerName: "Gift Shop", "Red Mug");
//PrintOrderDetails(31, "Red Mug", sellerName: "Gift Shop");
#endregion
#region private protected 通路修飾符---新複合通路修飾符
// 通路修飾符是關鍵字,用于指定成員或類型已聲明的可通路性。 本部分介紹四個通路修飾符:
//可使用通路修飾符指定以下六個可通路性級别:
//public:通路不受限制。
//protected:通路限于包含類或派生自包含類的類型。
//internal:通路限于目前程式集。
//protected internal:通路限于目前程式集或派生自包含類的類型。
//private:通路限于包含類。
//C#7特有
//private protected:通路限于包含類或目前程式集中派生自包含類的類型。
#endregion
#region 增強的泛型限制
///之前講的泛型限制有幾種?
//枚舉做基類限制
GerenicInfo<EnumInfo> info = new GerenicInfo<EnumInfo>();
info.Show(EnumInfo.ONE);
//限制不能為空
GerenicInfoUnmanaged<int> gerenicInfoUnmanaged = new GerenicInfoUnmanaged<int>();
//GerenicInfoUnmanaged<string> gerenicInfoUnmanaged = new GerenicInfoUnmanaged<string>();
public class GerenicInfo<T> where T : Enum
{
public void Show(T t)
{
}
}
public enum EnumInfo
{
ONE,
TOWN,
THREE
}
/// <summary>
/// 限制不能為空
/// </summary>
/// <typeparam name="T"></typeparam>
public class GerenicInfoUnmanaged<T> where T : unmanaged
{
public void Show(T t)
{
}
}
#endregion
#region 通用的異步傳回類型
//ValueTask<int> task = Func();
//await foreach (var item in task)
//{
//}
public static async ValueTask<int> Func()
{
await Task.Delay(100);
return 5;
}
#endregion
c#8.0文法
#region 預設接口方法
CustomInterface interface1 = new CustomClass();
interface1.Show();
interface1.ShowInfo();
#endregion
#region switch 表達式
//老玩法
string week3 = WeekToStringSwitch(WeekInfo.Monday);
string week4 = WeekToStringSwitch(WeekInfo.Tuesday);
string week5 = WeekToStringSwitch(WeekInfo.Wednesday);
//新玩法
string week = WeekToString(WeekInfo.Monday);
string week1 = WeekToString(WeekInfo.Tuesday);
string week2 = WeekToString(WeekInfo.Wednesday);
/// <summary>
/// C#8新文法
/// </summary>
/// <param name="week"></param>
/// <returns></returns>
public static string WeekToString(WeekInfo week) => week switch
{
WeekInfo.Monday => "周一",
WeekInfo.Tuesday => "周二",
WeekInfo.Wednesday => "周三",
WeekInfo.Thursday => "周四",
WeekInfo.Friday => "周五",
WeekInfo.Saturday => "周六",
WeekInfo.Sunday => "周七",
_ => throw new NotImplementedException("枚舉不存在"),
};
/// <summary>
///switch 經典switch
/// </summary>
/// <param name="week"></param>
/// <returns></returns>
public static string WeekToStringSwitch(WeekInfo week)
{
switch (week)
{
case WeekInfo.Monday:
return "周一";
case WeekInfo.Tuesday:
return "周二";
case WeekInfo.Wednesday:
return "周三";
case WeekInfo.Thursday:
return "周四";
case WeekInfo.Friday:
return "周五";
case WeekInfo.Saturday:
return "周六";
case WeekInfo.Sunday:
return "周七";
default:
throw new NotImplementedException("枚舉不存在");
}
}
#endregion
#region 屬性模式
PropertyPattern product = new PropertyPattern()
{
ProductName = "朝夕架構班",
Price = 5499
};
PropertyPattern product1 = new PropertyPattern()
{
ProductName = "朝夕進階班",
Price = 4299
};
double price = PropertyPatternShow(product);
/// <summary>
///switch 屬性模式
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
public static double PropertyPatternShow(PropertyPattern pattern) => pattern
switch
{
{ ProductName: "朝夕架構班" } => pattern.Price * 0.5,
{ Price: 234 } => pattern.Price * 0.5,
_ => throw new NotImplementedException(),
};
#endregion
#region 元組模式
string strResult = RockPaperScissors("朝夕", "教育1");
string strResult1 = RockPaperScissors("朝夕", "教育");
string strResult3 = RockPaperScissors("朝夕", "教育3");
/// <summary>
/// switch 元組模式
/// </summary>
/// <param name="first"></param>
/// <param name="second"></param>
/// <returns></returns>
public static string RockPaperScissors(string first, string second)
=> (first, second) switch
{
("朝夕", "教育1") => $"{first}-{second}",
("朝夕", "教育2") => $"{first}-{second}",
("朝夕", "教育3") => $"{first}-{second}",
(_, _) => "不比對"
};
#endregion
#region 位置模式
PointInfo point = new PointInfo(123, 234);
int i = 11;
int j = 12;
point.Deconstruct(out i, out j);
public class PointInfo
{
public int X { get; }
public int Y { get; }
public PointInfo(int x, int y) => (X, Y) = (x, y);
public void Deconstruct(out int x, out int y) =>
(x, y) = (X, Y);
}
#endregion
#region 靜态本地函數
M();
static int M()
{
int y = 5;
int x = 7;
return Add(x, y);
static int Add(int left, int right) => left + right;
}
#endregion
#region 可空引用類型
//string? str = null;
//string str1 = null;
#endregion
#region 異步流
AsyncIEnumerableShow();
/// <summary>
/// 異步流
/// </summary>
public async static void AsyncIEnumerableShow()
{
Console.WriteLine("********************異步流*********************");
IAsyncEnumerable<int> asynclist = GenerateSequence();
await foreach (var item in asynclist)
{
Console.WriteLine(item);
}
Console.WriteLine("********************異步流*********************");
}
public static async IAsyncEnumerable<int> GenerateSequence()
{
for (int i = 0; i < 20; i++)
{
await Task.Delay(1000).ContinueWith(s =>
{
Console.WriteLine($"線程ID:{Thread.CurrentThread.ManagedThreadId.ToString("000")}");
});
yield return i;
}
}
#endregion
c# 9 文法
//Init是針對于類内部的字段而言;
FooInfo003 fooInfo003 = new FooInfo003()
{
PropA = "FooInfo003",
PropB = "FooInfo003_1"
};
//fooInfo003.PropA = "";//報錯
//fooInfo003.PropB = "";//報錯
string propa3 = fooInfo003.PropA;
string propb3 = fooInfo003.PropB;
public class FooInfo003
{
public string PropA { get; init; }
public string PropB { get; init; }
}
//Record關鍵字
Person person = new Person("朝夕", "教育");
string firstName = person.FirstName;
string lastName = person.LastName;
//person.FirstName = "";
//person.LastName = "教育訓練";//報錯
var otherPerson = person with { FirstName = "武漢朝夕" };
Console.WriteLine(object.ReferenceEquals(person, otherPerson));
Teacher teacher = new Teacher("朝夕", "教育", "科技有限公司");
string firstname1 = teacher.FirstName;
//teacher.FirstName = "";//報錯了
var teachernew = teacher with { }; //with 表達式訓示編譯器建立記錄的副本
Console.WriteLine(object.ReferenceEquals(teacher, teachernew));
public record Person
{
public Person(string first, string last) => (FirstName, LastName) = (first, last);
public string LastName { get; init; }
public string FirstName { get; init; }
}
public record Teacher : Person
{
public string Subject { get; }
public Teacher(string first, string last, string sub)
: base(first, last) => Subject = sub;
}
//頂級語句
//見控制台輸出語句
不需要在program中定義Main方法,可直接在在Program中寫程式
#endregion
//簡化new()用法
#region 對象聲明
{
FooInfo foo = new FooInfo();
FooInfo fooInfo1 = new(); //文法糖
FooInfo fooInfo2 = new() { PropA = "123", PropB = "234" };
}
#endregion
#region 方法調用
{
var result = ForecastFor(1, "Richard", new());
private static SharpNineInfo ForecastFor(int id, string name, FooInfo fooInfo)
{
return new();
}
}
#endregion
#region 靜态修飾
{
Func<int> func1 = () => 1;
Func<int> func = static () => 1;
}
#endregion
#region 模式比對
public class SharpNineInfo
{
public static void Show()
{
char a = 'A';
bool bResult = a.IsLetterNew();
}
}
public static class SharpNineInfoExtension
{
public static bool IsLetterNew(this char c)
=> c is (>= 'a' and <= 'z') or >= 'A' and <= 'Z';
}
#endregion
#region 為空判斷
string name = "Ricahrd";
if (string.IsNullOrWhiteSpace(name))
{
}
if (name is not null)
{
}
#endregion
#region 協變式傳回值(Covariant returns)
{
public abstract class Animal
{
public abstract Food GetFood();
}
public class Food
{
}
public class Meat : Food
{
}
/// <summary>
/// 在C#9中覆寫父類的方法,可以傳回類型的子類
/// </summary>
public class Tiger : Animal
{
public override Meat GetFood()
{
return new Meat();
}
}
}
#endregion
#region nint
{
// 原生大小的數字類型
//這次引入一組新類型(nint,nuint,nfloat等)'n'表示native(原生),該特性允許聲明一個32位或64位的資料類型,這取決于作業系統的平台類型。
//nint nativeInt = 55; //在32位主機中編譯時,需要4個位元組。
//nint nativeInt1 = 55; //使用x64編譯設定在64位主機中編譯時需要8個位元組。
//uint;
}
#endregion
#region Lambda 參數棄元
{
// C# 9 之前
Func<int, int, int> zero = (a, b) => 0;
Func<int, int, int> func = delegate (int a, int b) { return 0; };
}
// C# 9
{
Func<int, int, int> zero = (_, _) => 0;
Func<int, int, int> func = delegate (int _, int _) { return 0; };
}