C#6.0新特性
0. 导言
这篇文章涵盖C#6.0的新语言特性,一个代码名为“Roslyn”的新编译器被引入。这个编译器的源码是开源的,可以在Codeplex 网站下载(https://roslyn.codeplex.com/)
C#6.0新特性列表
我们可以一个一个讨论这些新特性,但首先,下面列出C#6.0的新特性:
- 自动属性初始化器
- 主构造函数
- 字典初始化器
- 申明表达式
- 静态Using
- catch块中的await
- 异常过滤器
- 检查NULL值的条件访问操作符
1. 自动属性初始化器
Before
初始化一个自动属性的唯一方法是实现一个显式的构造函数,在里面设置属性。
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;
}
}
}
After
在C#6.0中,带初始值的自动实现属性初始化不需要必须写构造体,我们能简化上面的例子:
public class AutoPropertyInCsharp6
{
public long PostID { get; } = 1;
public string PostName { get; } = "Post 1";
public string PostTitle { get; protected set; } = string.Empty;
}
2. 主构造函数
我们主要用构造函数初始化里面的值(接受参数值并赋值这些参数到实例属性)
Before
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; }
}
After
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.0中,主构造函数给我们一个简写语法来定义带参数的构造函数,每个类仅允许一个主构造函数。
如果你仔细看上面的例子,会发现我们把参数初始化移动到了类名旁边。
你可能得到以下错误“Feature ‘primary constructor’ is only available in ‘experimental’ language version.”解决这个问题,我们需要编辑SolutionName.csproj文件来去除这个错误,你不得不做的是在WarningTag后面添加额外的设置。
<LangVersion>experimental</LangVersion>
Feature 'primary constructor' is only available in 'experimental' language version
3. 字典初始化器
Before
写一个dictionary
初始化器的旧方法是:
public class DictionaryInitializerBeforeCSharp6
{
public Dictionary<string, string> _users = new Dictionary<string, string>()
{
{"users", "Venkat Baggu Blog" },
{"Features", "Whats new in C# 6" }
};
}
After
我们可以像定义数组那样用方括号定义dictionary
初始化器
public class DictionaryInitializerInCSharp6
{
public Dictionary<string, string> _users { get; } = new Dictionary<string, string>()
{
["users"] = "Venkat Baggu Blog",
["Features"] = "Whats new in C# 6"
};
}
4. 声明表达式
Before
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;
}
}
}
在C#6.0中,你能在表达式中声明一个本地变量。使用声明表达式我们也可以在if语句和各种循环语句中声明变量
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
Before
对于静态成员,你不需要为了调用方法而弄一个对象实例,你用如下语法:
TypeName.MethodName
public class StaticUsingBeforeCSharp6
{
public void TestMethod()
{
Console.WriteLine("Static Using Before C# 6");
}
}
After
在C#6.0中,你能够不用类型名就使用静态成员,你能够在namespaces
中引入静态类
如果你看下面的例子,我们移动静态Console
类到namespace
中:
using System.Console;
namespace newfeatureincsharp6
{
public class StaticUsingInCSharp6
{
public void TestMethod()
{
WriteLine("Static Using Before C# 6");
}
}
}
6. 在catch块中用await
在C#6.0之前,await关键字不允许在catch
和inally
块中,在C#6.0中,我们终于能在catch
和finally
块中用await
关键字。
try
{
//Do something
}
catch (Exception)
{
await Logger.Error("exception logging")
}
7. 异常过滤器
异常过滤器允许你在catch
块执行前检查if条件
考虑一个例子,现在我们有一个异常,要检查是否InnerException null,然后执行catch
块
//Example 1
try
{
//Some code
}
catch (Exception ex) if (ex.InnerException != null)
{
//Do work
}
//Before C# 6 we write the above code as follows
//Example 1
try
{
//Some code
}
catch (Exception ex)
{
if(ex.InnerException != null)
{
//Do work;
}
}
8. 检查NULL值的条件访问操作符
考虑一个例子,我们想要基于UserID
的UserRanking
是否为null
Before
var userRank = "No Rank";
if(UserID != null)
{
userRank = Rank;
}
//or
var userRank = UserID != null ? Rank : "No Rank"
After
var userRank = UserID?.Rank ?? "No Rank";