背水一战 Windows 10 (43) - C# 7.0 新特性
背水一战 Windows 10 (43) - C# 7.0 新特性
作者:webabcd
介绍
背水一战 Windows 10 之 C# 7.0 新特性
- out 变量, 数字语法改进, 值类型的异步返回
- 值类型变量的引用和值类型返回值的引用, 模式匹配, 元组
- 表达式抛出异常, lambda 表达式作用于构造函数或属性, 局部函数(本地函数)
示例
1、C# 7.0 示例 1: out 变量, 数字语法改进, 值类型的异步返回
CSharp7/Demo1.xaml.cs
/* * C# 7 示例 1 * out 变量, 数字语法改进, 值类型的异步返回 */ using System; using System.Threading.Tasks; using Windows.UI.Xaml.Controls; namespace Windows10.CSharp7 { public sealed partial class Demo1 : Page { public Demo1() { this.InitializeComponent(); sample1(); sample2(); sample3(); } // out 变量(out-variables) private void sample1() { // 这是之前的写法,需要预先声明变量 string s; OutSample(out s); lblMsg.Text += s; lblMsg.Text += Environment.NewLine; // 这是 c#7 的写法,不用预先声明变量了 OutSample(out string ss); lblMsg.Text += ss; lblMsg.Text += Environment.NewLine; // 这是 c#7 的写法,不用预先声明变量了,并且可以使用 var OutSample(out var sss); lblMsg.Text += sss; lblMsg.Text += Environment.NewLine; } private void OutSample(out string str) { str = "xyz"; /* * 注: * 1、对于 out 类型来说,是在方法内部初始化的,在 c#7 之前需要在方法外部声明(这显得没有必要,所以有了如今的改进) * 2、对于 ref 类型来说,是不可能改成 out 这种新方式的,因为 ref 是引用,其作用是方法外部初始化,方法内部改之 */ } // 数字语法改进(numeric literal syntax improvements) private void sample2() { int a1 = 123456; int a2 = 123_456; // 允许数字中出现“_”来提高可读性 lblMsg.Text += a1.ToString(); lblMsg.Text += Environment.NewLine; lblMsg.Text += a2.ToString(); lblMsg.Text += Environment.NewLine; int b1 = 0xABCDEF; int b2 = 0xAB_CD_EF; // 允许数字中出现“_”来提高可读性 lblMsg.Text += b1.ToString(); lblMsg.Text += Environment.NewLine; lblMsg.Text += b2.ToString(); lblMsg.Text += Environment.NewLine; } // 值类型的异步返回(generalized async return types) private async void sample3() { lblMsg.Text += (await GetNumber1()).ToString(); lblMsg.Text += Environment.NewLine; lblMsg.Text += (await GetNumber2()).ToString(); lblMsg.Text += Environment.NewLine; } // 在 c#7 之前异步返回 int 是这么写的,Task 是引用类型 private async Task<int> GetNumber1() { await Task.Delay(100); return 1; } // 在 c#7 中异步返回 int 可以这么写,ValueTask 是值类型,提高了效率 // 注:需要通过 nuget 引用 System.Threading.Tasks.Extensions private async ValueTask<int> GetNumber2() { await Task.Delay(100); return 1; } } }
2、C# 7.0 示例 2: 值类型变量的引用和值类型返回值的引用, 模式匹配, 元组
CSharp7/Demo2.xaml.cs
/* * C# 7 示例 2 * 值类型变量的引用和值类型返回值的引用, 模式匹配, 元组 */ using System; using Windows.UI.Xaml.Controls; namespace Windows10.CSharp7 { public sealed partial class Demo2 : Page { public Demo2() { this.InitializeComponent(); sample1(); sample2(); sample3(); } // 值类型变量的引用和值类型返回值的引用(ref locals and returns) private void sample1() { // 值类型变量变为引用类型的示例 int a = 1; ref int b = ref a; // 值类型变量 b 引用了值类型变量 a a = 2; lblMsg.Text = a.ToString(); lblMsg.Text += Environment.NewLine; // 值类型返回值变为引用类型的示例 int[] array = { 1, 2, 3, 4, 5 }; ref int x = ref GetByIndex(array, 2); // 值类型变量 x 引用了 GetByIndex(array, 2) x = 99; lblMsg.Text += array[2].ToString(); lblMsg.Text += Environment.NewLine; } // 返回的值类型变为引用类型 private ref int GetByIndex(int[] array, int index) { return ref array[index]; } // 模式匹配(pattern matching) private void sample2() { object a = 1; // 声明 int b,如果 a 是 int 类型则将 a 赋值给 b if (a is int b) { lblMsg.Text += b.ToString(); lblMsg.Text += Environment.NewLine; } switch (a) { // 声明 int c,如果 a 是 int 类型则将 a 赋值给 c,如果 c 大于 0 则执行此 case case int c when c > 0: lblMsg.Text += "case int c when c > 0: " + c; lblMsg.Text += Environment.NewLine; break; // 声明 string c,如果 a 是 string 类型则将 a 赋值给 c case string c: lblMsg.Text += "case string c: " + c; lblMsg.Text += Environment.NewLine; break; } } // 元组(Tuples) // 注:需要通过 nuget 引用 System.ValueTuple private void sample3() { // Tuples 特性是从 System.Tuple<T1, T2, T3...> 进化而来的 // 注:当有多个返回值时,使用 Tuples 特性是非常方便的 var user1 = GetUser1(); lblMsg.Text += $"{user1.UserId}, {user1.UserName}, {user1.CreateTime}"; lblMsg.Text += Environment.NewLine; var user2 = GetUser2(); lblMsg.Text += $"{user2.UserId}, {user2.UserName}, {user2.CreateTime}"; lblMsg.Text += Environment.NewLine; var user3 = GetUser3(); lblMsg.Text += $"{user3.Item1}, {user3.Item2}, {user3.Item3}"; lblMsg.Text += Environment.NewLine; (int UserId, string UserName, DateTime CreateTime) = GetUser1(); lblMsg.Text += $"{UserId}, {UserName}, {CreateTime}"; lblMsg.Text += Environment.NewLine; var obj1 = (UserId: 1, UserName: "webabcd"); lblMsg.Text += $"{obj1.UserId}, {obj1.UserName}"; lblMsg.Text += Environment.NewLine; var obj2 = (1, "webabcd"); lblMsg.Text += $"{obj2.Item1}, {obj2.Item2}"; lblMsg.Text += Environment.NewLine; (int id, string name) = (1, "webabcd"); lblMsg.Text += $"{id}, {name}"; lblMsg.Text += Environment.NewLine; } private (int UserId, string UserName, DateTime CreateTime) GetUser1() { return (1, "webabcd", DateTime.Now); } private (int UserId, string UserName, DateTime CreateTime) GetUser2() { return (UserId: 1, UserName: "webabcd", CreateTime: DateTime.Now); } private (int, string, DateTime) GetUser3() { return (1, "webabcd", DateTime.Now); } } }
3、C# 7.0 示例 3: 表达式抛出异常, lambda 表达式作用于构造函数或属性, 局部函数(本地函数)
CSharp7/Demo3.xaml.cs
/* * C# 7 示例 3 * 表达式抛出异常, lambda 表达式作用于构造函数或属性, 局部函数 */ using System; using Windows.UI.Xaml.Controls; namespace Windows10.CSharp7 { public sealed partial class Demo3 : Page { public Demo3() { this.InitializeComponent(); sample1(); sample2(); sample3(); } // 表达式抛出异常(throw expressions) private void sample1() { try { string a = null; // 支持在表达式中抛出异常 string b = a ?? throw new Exception("ex"); } catch (Exception ex) { lblMsg.Text += ex.ToString(); lblMsg.Text += Environment.NewLine; } } // lambda 表达式作用于构造函数或属性(more expression-bodied members) // 注:在 c#6 中已经支持了 lambda 表达式作用于字段或方法 private void sample2() { MyClass obj = new MyClass("webabcd"); lblMsg.Text += obj.Text; lblMsg.Text += Environment.NewLine; } public class MyClass { private string _text; public MyClass(string text) => _text = text; // lambda 表达式作用于构造函数 public string Text // lambda 表达式作用于属性 { get => _text; set => _text = value ?? "default text"; } } // 局部函数(local functions) private void sample3() { int a = GetNumber(); lblMsg.Text += a.ToString(); lblMsg.Text += Environment.NewLine; // 支持局部函数了 int GetNumber() { return 1; } } } }
OK
[源码下载]