30分钟掌握 C#6
1. 只讀自動屬性(Read-only auto-properties)
?C# 6之前我們構(gòu)建只讀自動屬性:
public string FirstName { get; private set; }public string LastName { get; private set; }
原理解析:就是編譯器在生成set訪問器時,它的修飾符是private,由上可知所謂的只讀只是針對類外部,在類內(nèi)部還是可以隨意修改屬性值的。
?C# 6中提供了真正的只讀自動屬性,寫法如下:
public string FirstName { get; }public string LastName { get; }
?原理解析:首先編譯器會生成一個readonly的私有字段而get訪問器就是返回該字段的值,由上可知該只讀自動屬性只能在構(gòu)造函數(shù)中為其賦值。
2. 自動屬性初始化器(Auto-Property Initializers)
?以前自動屬性的賦值操作我們只能寫在方法中,如構(gòu)造函數(shù):
public Student(string firstName, string lastName){
FirstName = firstName;
LastName = lastName;
}
?但在C# 6中我們可以把賦值操作當作聲明的一部份,如下所示:
public string FirstName { get; set; } = "Corleone";? public string LastName { get; set; } = "Mike";
?備注:其實C# 6和之前的版本都一樣賦值操作最終都是在方法中完成,但后者明顯更簡潔直觀,所以這是個不錯的語法糖。
3. 函數(shù)成員的表達式體(Expression-bodied function members)
?C# 6中提供的一個新語法:對于只有一條語句的方法體可以簡寫成表達式。如下面兩種情況:
?1. 方法(Methods)
? public Student Create() => new Student();?等同于:
public Student Create(){
return new Student();
}
?2. 只讀屬性(read only properties)
public string FullName => string.Format("{0},{1}", FirstName, LastName);?等同于:
public string FullName
? {
? ? ? get
? ? ? {
? ? ? ? ? return string.Format("{0},{1}", FirstName, LastName);
? ? ? }
? }
原理解析:上面的表達式在編譯后會生成最原始的方法體和訪問器,值得一提的是函數(shù)表達式體跟Lambda是兩個相似但不相同的東西,函數(shù)的表
達式體只能帶一句話且不能包含return關(guān)鍵字但Lambda 能帶語句塊和包含關(guān)鍵字。
4. 使用靜態(tài)(using static)
?C# 6中的一個新語法:使用類型的靜態(tài)成員時可以省略其類型,如下所示:
using static System.String;// 先導(dǎo)入對應(yīng)成員類型
public bool IsNull(string str) => IsNullOrEmpty(str);
?等同于:
public bool IsNull(string str) => string.IsNullOrEmpty(str);總結(jié):該語法糖的目的是使代碼變得更簡潔,但這個應(yīng)該是區(qū)分使用場景的,如:數(shù)學(xué)計算(Math類)使用此語法糖的確能夠簡潔代碼提高可讀
性,但在某處如果導(dǎo)入過多的類型那么不僅不能提高閱讀性反而會增加閱讀難度,因為你不知道這些成員具體屬于那個類型。還有若類型本身存在
同名成員使用時則會使用類型成員覆蓋。
注意:使用靜態(tài)這一語法糖并不適用擴展方法,因為擴展方法的設(shè)計理念就是不修改已有代碼且只能在一定范圍內(nèi)使用,所以在特殊情況下需要將
其當作靜態(tài)方法來使用,那么使用類名調(diào)用反而是比較明智的。
5. Null條件運算符(Null-conditional operators)
?稍有經(jīng)驗的童鞋都知道在Coding過程中經(jīng)常要判斷變量的值是否為null,類似這種if-else的操作還不少。這使得代碼看起來十分不簡潔,好在C#6
?中提供了解決方法:
var student = new Student();var firstName = student?.FirstName;
等同于:
var student = new Student();
? string firstName = null;
? if (student != null)
? {
? ? ? firstName = student.FirstName;
? }
使用方法:只需替換成員訪問符 . 為 ?. ,若 ?. 左邊為null則整個運算符的結(jié)果也為null,否則運算符的結(jié)果就等于其成員值。假如成員的類型為值
類型則整個表達式返回的類型是對應(yīng)類型的可空類型,如:
1 ? int? age = student?.Age;?原理解析: ?. 編譯后就是 if 或 三元運算符,非賦值操作(如:call)會編譯成 if,賦值操作一般會編譯成三元運算符。
6. 字符串插值(String Interpolation)
?C# 6中提供了一種新語法來構(gòu)建格式化字符串,如:
1 ? var fullName = $"{student.FirstName},{student.LastName}";?等同于:
var fullName = string.Format("{0},{1}", student.FirstName, student.LastName);?使用方法:只需在字符串前加上$符號,然后在大括號中填寫表達式(字段、方法、Lambdad...)即可。
?備注:
?1. 字符串插值語法支持以前所有字符串格式設(shè)置(此項僅支持 .net framework,不支持 .net core 1.0.1),如:
Console.WriteLine($"平均成績:{student.GPA:F2}");?注:因為 : 總被編譯器解釋為表達式與字符串格式的分隔符,所以表達式中若有條件運算符則我們需要用括號來強制編譯將其解析成當前語境所要
?表達的意義。如:
Console.WriteLine($"平均成績:{(student.GPA > 80 ? student.GPA : 0):F2}");?2. 字符串插值語法可以嵌套,如:
var score = $"我的各科成績:{ $"數(shù)學(xué):{student.MathScores};英語:{student.EnglishScore};"}";?原理解析:$"xxx{expression1}xxx{expression2}..." 編譯后就是string.Format()。
7. 異常過濾器(Exception Filters)
?C# 6中的一個新功能就是異常過濾器,它可以使我們在恰當?shù)臅r機來應(yīng)用Catch子句,如:
try
? {
? ? ? throw new WebException("Request timed out..", WebExceptionStatus.Timeout);
? }
? catch (WebException webEx) when (webEx.Status == WebExceptionStatus.Timeout)
? {
? ? ? // Exception handling
? }
使用方法:try-catch() when()。
?總結(jié):異常過濾器最大的亮點就是在使用恰當?shù)那闆r下可以不丟失異常引發(fā)點的堆棧信息,這對程序的排錯至關(guān)重要。另外它還有很多有意思的用
?法,大家可以上網(wǎng)查下。
8. nameof表達式(nameof Expressions)
?
public string FullName(Student student)
? {
? ? ? if (student == null)
? ? ? ? ? throw new ArgumentNullException(nameof(student));
? ? ? return $"{student.FirstName},{student.LastName}";
? }
優(yōu)點:nameof 表達式它能夠理解成員,當成員被重命名時nameof表達式中也重命名了,而常量字符串表示法是沒有這樣的優(yōu)勢。
缺點:nameof 表達式生成的是不完全限定名,若你需要完全限定名 nameof 就不能幫你了。
原理解析:nameof 是編譯期間就確定其(成員)字符串名稱的,即編譯后就是常量字符串的表現(xiàn)形式了。
9. 在Catch和Finally中使用Await(Await in Catch and Finally blocks)
?C# 5 提供的 async?和 await 使異步編程變得極為簡便,但它們也有著局限性:await在catch和finally塊中不能使用。但這個問題已在C# 6中得到
?了解決,如:
public static async Task<string> MakeRequestAndLogFailures()
? {
? ? ? await logMethodEntrance();
? ? ? try
? ? ? {
? ? ? ? ? // ....
? ? ? ? ? var responseText = await streamTask;
? ? ? ? ? return responseText;
? ? ? }
? ? ? catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
? ? ? {
? ? ? ? ? await logError("Recovered from redirect", e);
? ? ? ? ? return "Site Moved";
? ? ? }
? ? ? finally
? ? ? {
? ? ? ? ? await logMethodExit();
? ? ? }
? }
10.?Index初始化器(Index Initializers)
?這個功能并沒有什么新意,其實以前就支持集合/字典 初始化器了,如:
var list = new List<string>()
? {
? ? ? "Mike",
? ? ? "Jim"
? };
? ?
? var dic = new Dictionary<int, string>()
? {
? ? ? { 20, "Mike" },
? ? ? { 30, "Jim" ?}
? };
在C# 6中只是字典初始化器支持了新的寫法,如:
{
[20] = "Mike",
[30] = "Jim"
};
總結(jié):暫無發(fā)現(xiàn)特殊的用法。
11. 改進的重載解析—編譯器(Improved overload resolution)
? 這算不上是新語法,因為僅僅是編譯器的改進,之所以一提是想讓大家知道有這么一回事。以前的編譯器是識別不了?Task.Run(Func<Task>())
? 的,如下:
static Task DoThings()
? {
? ? ? return Task.FromResult(0);
? }
??
? Task.Run(DoThings); ?// 此處省略方法代碼...
上述代碼在老版本編譯器下是編譯不通過的,而在新版本編譯器是能編譯通過的。
備注:值得一提的是新版本編譯器也只是識別了Task.Run(Func<Task>()),Task.Run(Action) 還是識別不了,總的來說此功能對我們用處不大,
還不如乖乖的寫回Lambda表達式。
原文地址:http://www.cnblogs.com/VVStudy/p/6426923.html
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的30分钟掌握 C#6的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微软发布ReactXP:方便开发者构建跨
- 下一篇: 体验VS2017的Live Unit T