1. 自动的属性初始化器Auto Property initialzier
之前的方式:
public class AutoPropertyBeforeCsharp6 { private string _postTitle = string.Empty; public AutoPropertyBeforeCsharp6() { //assign initial values PostID = 1; PostName = "Post 1"; } public long PostID { get; set; } public string PostName { get; set; } public string PostTitle { get { return _postTitle; } protected set { _postTitle = value; } } }
C# 6 自动实现的带有初始值的属性可以不用编写构造器就能被初始化. 我们可以用下面的代码简化上面的示例:
public class AutoPropertyInCsharp6 { public long PostID { get; } = 1; public string PostName { get; } = "Post 1"; public string PostTitle { get; protected set; } = string.Empty; }
2. 主构造器
之前的方式:
public class PrimaryConstructorsBeforeCSharp6 { public PrimaryConstructorsBeforeCSharp6(long postId, string postName, string postTitle) { PostID = postId; PostName = postName; PostTitle = postTitle; } public long PostID { get; set; } public string PostName { get; set; } public string PostTitle { get; set; } }
有了这个特性之后的方式
public class PrimaryConstructorsInCSharp6(long postId, string postName, string postTitle) { public long PostID { get; } = postId; public string PostName { get; } = postName; public string PostTitle { get; } = postTitle; }
在 C# 6 中, 主构造器为我们提供了使用参数定义构造器的一个简短语法. 每个类只可以有一个主构造器.
如果你观察上面的示例,会发现我们将参数初始化移动到了类名的旁边.
你可能会得到下面这样的错误“Feature ‘primary constructor’ is only available in ‘experimental’ language version.”(主构造器特性只在实验性质的语言版本中可用), 为了解决这个问题,我们需要编辑 SolutionName.csproj 文件,来规避这个错误 . 你所要做的就是在 WarningTag 后面添加额外的设置
<LangVersion>experimental</LangVersion>
‘主构造器’只在‘实验’性质的语言版本中可用
3. 字典初始化器
之前的方式:
public class DictionaryInitializerBeforeCSharp6 { public Dictionary<string, string> _users = new Dictionary<string, string>() { {"users", "Venkat Baggu Blog" }, {"Features", "Whats new in C# 6" } }; }
可以像数组里使用方括号的方式那样定义一个字典初始化器
public class DictionaryInitializerInCSharp6 { public Dictionary<string, string> _users { get; } = new Dictionary<string, string>() { ["users"] = "Venkat Baggu Blog", ["Features"] = "Whats new in C# 6" }; }
4. 声明表达式
之前的方式:
public class DeclarationExpressionsBeforeCShapr6() { public static int CheckUserExist(string userId) { //Example 1 int id; if (!int.TryParse(userId, out id)) { return id; } return id; } public static string GetUserRole(long userId) { ////Example 2 var user = _userRepository.Users.FindById(x => x.UserID == userId); if (user!=null) { // work with address ... return user.City; } } }
这个特性之后的方式
public class DeclarationExpressionsInCShapr6() { public static int CheckUserExist(string userId) { if (!int.TryParse(userId, out var id)) { return id; } return 0; } public static string GetUserRole(long userId) { ////Example 2 if ((var user = _userRepository.Users.FindById(x => x.UserID == userId) != null) { // work with address ... return user.City; } } }
5. 静态的 Using
之前的方式:
StaticUsingBeforeCSharp6.TestMethod(); public class StaticUsingBeforeCSharp6 { public void TestMethod() { Console.WriteLine("Static Using Before C# 6"); } }
在 C# 6 中,你不用类名就能使用 静态成员 . 你可以在命名空间中引入静态类.
这个特性之后的方式
using System.Console; namespace newfeatureincsharp6 { public class StaticUsingInCSharp6 { public void TestMethod() { WriteLine("Static Using Before C# 6"); } } }
6. catch块里面的await
之前catch和finally块中是不能用 await 关键词的. 在 C# 6 中,我们终于可以再这两个地方使用await了
try { //Do something } catch (Exception) { await Logger.Error("exception logging") }
7. 异常过滤器
异常过滤器可以让你在catch块执行之前先进行一个 if 条件判断.
看看这个发生了一个异常的示例,现在我们想要先判断里面的Exception是否为null,然后再执行catch块
//示例 1 try { //Some code } catch (Exception ex) if (ex.InnerException == null) { //Do work } //Before C# 6 we write the above code as follows //示例 1 try { //Some code } catch (Exception ex) { if(ex.InnerException != null) { //Do work; } }
8. 用于检查NULL值的条件访问操作符?.
之前的方式:
if(UserID != null) { userRank = Rank; } //or var userRank = UserID != null ? Rank : "No Rank"
这个特性之后:
var userRank = UserID?.Rank ?? "No Rank";
此特性不光是可以用于取值,也可以用于方法调用
9. 字符串插值
之前的方式:
var Name = "Jack"; var results = "Hello" + Name; //或者 var Name = "Jack"; var results = string.Format("Hello {0}", Name);
这个特性之后:
var Name = "Jack"; var results = $"Hello {Name}"; //不光是可以插简单的字符串,还可以直接插入代码 Console.WriteLine($"Jack is saying { new Tools().SayHello() }"); var info = $"Your discount is {await GetDiscount()}";
10. NameOf
之前的方式:
public string Name { get { return name; } set { name= value; RaisePropertyChanged("Name"); } }
这个特性之后:
public string Name { get { return name; } set { name= value; RaisePropertyChanged(NameOf(Name)); } } static void Main(string[] args) { Console.WriteLine(nameof(User.Name)); // output: Name Console.WriteLine(nameof(System.Linq)); // output: Linq Console.WriteLine(nameof(List)); // output: List Console.ReadLine(); }
注意: NameOf只会返回Member的字符串,如果前面有对象或者命名空间,NameOf只会返回 . 的最后一部分, 另外NameOf有很多情况是不支持的,比如方法,关键字,对象的实例以及字符串和表达式