寫在前面
上篇文章介紹了c#6.0的using static,Auto Property Initializers,Index Initializers新的特性,這篇文章將把剩下的幾個學習一下。
原文地址:http://www.codeproject.com/Articles/1070659/All-About-Csharp-New-Features
上篇文章:c#6.0新特性(一)
String Interpolation
為了拼接字符串,我們通常會使用String.Format通過索引並對索引進行賦值來完成。當然,有時這種做法在有多個參數的時候有點麻煩,在c#6.0中,有一種新特性,可以不再使用索引就實現我們的目的。你可以通過以$ sign開始指定一個參數。下面的例子,通過first name和last name獲取full name。在這里,我們使用string.format並且為指定的索引指定值。
Before c#6.0
using System; using System.Collections.Generic; namespace CplusplusNewFeature { public class Program { static void Main(string[] args) { string firstName = "Mukesh"; string lastName = "Kumar"; Console.WriteLine("The Full Name of Employee " + string.Format("{0} {1}", firstName, lastName)); Console.ReadLine(); } } }
在c# 6.0中
我們不必像c#6.0之前那樣做了,我們只需在字符串前通過$符號標記該字符串,c#6.0就知道在該字符串遇到{}中的內容,將使用我們定義變量進行替換。看一個例子:
using System; using System.Collections.Generic; using static System.Console; namespace CplusplusNewFeature { public class Program { static void Main(string[] args) { string firstName = "Mukesh"; string lastName = "Kumar"; WriteLine($"The Full Name of Employee {firstName} {lastName}"); ReadLine(); } } }
The Full Name of Employee Mukesh Kumar
在這里{}內的內容也相當於占位符,只不過這里需要你使用你需要替換的變量名稱進行占位。
Expression Bodied Members
lambda表達式在linq查詢中是非常有幫助的。但在c#6.0中,你可以在屬性和方法中使用lambda表達式提升你的效率,寫更簡潔的代碼。
通過lambda表達式你可以使用一行代碼定義一個方法(只針對簡單短小邏輯的方法或者屬性)。我相信,當你在大的應用程序中,將使用expression bodied members來獲取基於條件的值。我們會直接創建一個方法,並在輸出參數中返回他們的值。
在c#6.0之前
之前我們創建一個單獨的方法去完成一些簡單的任務。它可能是一行或者更多行代碼。但是它是非常復雜和花費時間的。看一下下面的例子,有這樣的兩個方法GetFullName和AddTowNumber,它們只是拼接字符串和加兩個數字。但是為了完成這一的任務,我們需要定義兩個單獨的方法。
using System; using System.Collections.Generic; namespace CplusplusNewFeature { public class Program { public static string GetFullName(string firstName, string lastName) { return string.Format("{0} {1}", firstName, lastName); } public static int AddTwoNumber(int firstNumber, int secondNumber) { return firstNumber + secondNumber; } static void Main(string[] args) { string firstName = "Mukesh"; string lastName = "Kumar"; int firstNumber = 10; int secondNumber = 20; Console.WriteLine(GetFullName(firstName, lastName)); Console.WriteLine(AddTwoNumber(firstNumber, secondNumber)); Console.ReadLine(); } } }
在c#6.0中
在c#6.0中,我們可以在定義的時候完成這樣的任務,不再需要定義單獨的方法去做這樣的事情了。
using System; using System.Collections.Generic; using static System.Console; namespace CplusplusNewFeature { public class Program { public static string GetFullName(string firstName, string lastName) => firstName + " " + lastName; public static int AddTwoNumber(int firstNumber, int secondNumber) => firstNumber + secondNumber; static void Main(string[] args) { string firstName = "Mukesh"; string lastName = "Kumar"; int firstNumber = 10; int secondNumber = 20; WriteLine(GetFullName(firstName, lastName)); WriteLine(AddTwoNumber(firstNumber, secondNumber)); ReadLine(); } } }
Getter only Auto Properties
在你使用屬性的時候,getter和setter都是需要定義的。但是在c# 6.0中,你可以只定義屬性的gtter方法。在c#6.0之前,當創建屬性的時候,getter和setter是需要定義的。有時,我們並不需要創建setter,但是我們必須去定義它。但在c#6.0中,不再有這樣的限制去編寫這樣的代碼,你只需定義制度的屬性即可。
看一下下面的例子,fistname和lastname在只有getter的情況下,為他們賦值。
In C#6.0
using System; using System.Collections.Generic; namespace CplusplusNewFeature { public class Program { string FirstName { get; } = "Mukesh"; string LastName { get; } = "Kumar"; public string FullName = string.Empty; public Program() { FullName = FirstName + " " + LastName; } static void Main(string[] args) { Program prog = new Program(); Console.WriteLine("The Full Name is " + prog.FullName); Console.ReadLine(); } } }
在一些反編譯工具中,你會發現,你定義的只讀屬性,會在構造函數中為他們賦值。如果你在聲明變量的時候為他們賦值了,實際發生賦值的是在他們的構造函數中。
看一個例子
public class TestClass { public string TestProperty { get; } = "Test Property"; public readonly string TestField = "Test Field"; }
用反編譯工具進行查看,是在默認的構造函數中為他們賦值的。
public TestClass() { this.<TestProperty>k__BackingField = "Test Property"; this.TestField = "Test Field"; }
Exception Filters
在引入Roslyn編輯器,這個特性也加入了vb中了。過濾器被用在基於一些條件參數的catch塊中。通常,我們需要在一個catch苦熬中需要不同的條件拋出不同的異常類型。
但是在c#6.0中,你可以在每一個條件中校驗信息並拋出他們的異常信息。
c#6.0之前
using System; using System.Collections.Generic; namespace CplusplusNewFeature { public class Program { static void Main(string[] args) { int errorCode = 404; try { throw new Exception(errorCode.ToString()); } catch (Exception ex) { if (ex.Message.Equals("404")) Console.WriteLine("This is Http Error"); else if (ex.Message.Equals("401")) Console.WriteLine("This is Unathorized Error"); else Console.WriteLine("This is some different exception"); Console.ReadLine(); } } } }
在c#6.0中
通過c#6.0中,我們可以為不同的異常信息指定不同的拋出條件。看一個例子
using System; using System.Collections.Generic; using static System.Console; namespace CplusplusNewFeature { public class Program { static void Main(string[] args) { int errorCode = 404; try { throw new Exception(errorCode.ToString()); } catch (Exception ex) when (ex.Message.Equals("404")) { WriteLine("This is Http Error"); } catch (Exception ex) when (ex.Message.Equals("401")) { WriteLine("This is Unathorized Error"); } catch (Exception ex) when (ex.Message.Equals("403")) { WriteLine("Forbidden"); } ReadLine(); } } }
Null Conditional Operators
在編碼時,我們通常校驗null,我們檢驗對象是否為null,並且嘗試組織拋出NullReferenceExpression。但是為了這樣做,為了達到這一的目的,我們需要編寫額外的很長的代碼。
但在c#6.0中,你可以通過null條件操作符question mark[?]完成這一的操作。
在c#6.0之前
using System; using System.Collections.Generic; using System.Linq; namespace CplusplusNewFeature { public class Program { static void Main(string[] args) { List<Employee> employees = new List<Employee>(); Program prog = new Program(); if (employees.FirstOrDefault() != null) { //This code will not hit because of employees is null; Console.WriteLine(employees.First().Name); } else { Employee emp = new Employee(); emp.EmployeeId = 10; emp.Name = "Mukesh Kumar"; emp.Address = "New Delhi"; employees.Add(emp); Console.WriteLine(employees.First().Name); } Console.ReadLine(); } } public class Employee { public int EmployeeId { get; set; } public string Name { get; set; } public string Address { get; set; } } }
在c#6.0中
using System; using System.Collections.Generic; using System.Linq; using static System.Console; using static System.Console; namespace CplusplusNewFeature { public class Program { static void Main(string[] args) { List<Employee> employees = new List<Employee>(); Program prog = new Program(); //No need to check null in if condition //null operator ? will check and return null if value is not there WriteLine(employees.FirstOrDefault()?.Name); //set the default value if value is null WriteLine(employees.FirstOrDefault()?.Name ?? "My Value"); ReadLine(); } } public class Employee { public int EmployeeId { get; set; } public string Name { get; set; } public string Address { get; set; } } }
Declaration Expressions
使用這個特性,我們需要在表達式內部生命本地全局的變量。但是變量的作用域只在定義的塊中。
c#6.0之前
using System; using System.Collections.Generic; using System.Linq; namespace CplusplusNewFeature { public class Program { static void Main(string[] args) { int myValue = 10; if (int.TryParse("20", out myValue)) { Console.WriteLine(myValue); Console.ReadLine(); } } } }
In Preview C# 6.0 [Features is not added with C# 6.0 Final Version, it might be come with C# 7.0]
using System; using System.Collections.Generic; using System.Linq; using static System.Console; namespace CplusplusNewFeature { public class Program { static void Main(string[] args) { if (int.TryParse("20", out var result)) { return result; } return 0; // result is out of scope // A new feature in C# 6.0 allows to declare variable inside TryParse method. //Declaration expressions was cut from C# 6.0 and wasn't shipped in the final release. //You currently can't do that. There is a proposal for it on GitHub for C# 7. } }
總結
最后,我們已經學習了c#6.0的一些新特性,這些特性將改變我們編碼效率。它將使我們的編碼更簡單,並且可以提供簡單的途徑去完成復雜的事情。
這也是年前最后一篇文章了,提前祝大家2016年春節快樂。
