C#7.0特性
1.Tuples 元组
从一个方法中返回多个值是在实际开发中经常会碰到的场景,一般这种情况我们会使用自定义数据类型、输出参数或者返回一个集合的方式。但在 C# 7.0 中通过元组类型以及元组可以很方便的处理这种场景,请看如下代码:
( string, string, string, string) getEmpInfo() { //read EmpInfo from database or any other source and just return them string strFirstName = "abc"; string strAddress = "Address"; string strCity= "City"; string strState= "State"; return (strFirstName, strAddress, strCity, strState); // tuple literal } //调用上述方法返回多个值 var empInfo= getEmpInfo(); WriteLine("Emp info as {empInfo .Item1} {empInfo .Item2} {empInfo .Item3} {empInfo .Item4}.");
在上述例子中我们可以轻松从元组中返回多个值,但是 Item1, Item2 的名称不好看,我们可以在返回前给它指定一些有意义的名称,如下面代码:
(string strFName, string strAdd, string strC, string strSt) getEmpInfo() { //code goes here } //使用指定名称来获取相应值 var empInfo= getEmpInfo(); WriteLine("Emp info as {empInfo.strFName} {empInfo.strAdd} {empInfo.strC} {empInfo.strSt}."); 此外你可以像下面这样直接返回元组中的名称: return (strFName: strFirstName, strAdd: strAddress, strCity: strC, strState: strSt);
Tuples 元组是非常有用的,可以用来替代哈希表或者字典结构,你设置可以为一个单一的键返回多个值。此外你可以使用它来替代 List 。
.NET 已经有了 Tuple 元组类型 ,但其引用类型会导致一些性能方面的问题。而在 C# 7.0 中提供了值类型的 Tuple 元组,这比老版本速度要快很多,同时还提供了可变类型。
析构
绝大多数时候我们不会去访问整个 Tuple 元组,或者说我们只需要内部的一些值,这个时候我们就可以用 C# 7.0 的 Deconstruction 析构特性,通过它轻松释放一个元组或者从中获取所需的值,请看如下代码:
( string strFName, string strAdd, string strC, string strSt) = getEmpInfo(); Console.WriteLine($"Address: { strAdd }, Country: { strC }");
2.记录类型 Record Type
C# 支持 Record Type 记录类型,其实说白了就是属性和值的容器。绝大多数类是包含属性和值的,我们需要大量的代码来声明这种类型。有了 Record Type 之后就可以大量减少代码,如下代码片段所示:
class studentInfo { string _strFName; string _strMName; string _strLName; studentInfo(string strFN, string strMN, string strLN){ this._strFName = strFN; this._strMName = strMN; this._strLName = strLN; } public string StudentFName {get{ return this._strFName;}} public string StudentMName {get{ return this._strMName;}} public string StudentLName {get{ return this._strLName;}}
上述代码中我们定义了一个包含属性、构造函数和变量的类,为了访问和声明变量我需要编写更多的代码。
C# 7.0 的 Record Type 可以避免这种情况,请看代码:
class studentInfo(string StudentFName, string StudentMName, string StudentLName);
3.最小化 OUT 输出变量
当我们需要一个方法返回多个值的时候,经常会用到输出参数。但是一般输出参数是引用类型,而且它其实就是一个参数,这样使用只不过是受限于语言本身的限制,不过有一个限制就是输出参数在使用前必须被初始化,如下代码所示:
class SetOut { void AssignVal(out string strName) { strName = "I am from OUT"; } static void Main() { string strArgu; AssignVal(out strArgu); // here contents of strArgu is "I am from OUT" } }
C# 7.0 减少了编写额外代码的痛苦,你不需要在传递参数前进行初始化,如下所示:
static void Main() { AssignVal(out string szArgu); // here contents of szArgu is "I am from OUT" }
可以使用 var 作为参数类型,这样就不需要使用前进行声明。
注意在这里使用的这些变量只在一个受限的范围内有效,因此我们不能在方法外使用这些变量。
一旦我们将变量直接作为参数使用,C# 7.0 可以通过 var 关键字来进行声明。因此你不用担心数据类型问题,请看下面代码:
static void Main() { AssignVal(out var szArgu); // here contents of szArgu is "I am from OUT" }
4.不允许为空的引用类型
'?' 用于允许为空的值类型,而 '!' 是不允许为空的引用类型。
int objNullVal; //non-nullable value type int? objNotNullVal; //nullable value type string! objNotNullRef; //non-nullable reference type string objNullRef; //nullable reference type 现在再来看看在运行这个代码之后的编译器效果 MyClass objNullRef; // Nullable reference type MyClass! objNotNullRef; // Non-nullable reference type objNullRef = null; // this is nullable, so no problem in assigning objNotNullRef = null; // Error, as objNotNullRef is non-nullable objNotNullRef = objNullRef; // Error, as nullable object can not be refered WriteLine(objNotNullRef.ToString()); // Not null so can convert to tostring WriteLine(objNullRef.ToString()); // could be null if (objNullRef != null) { WriteLine(objNullRef.ToString); } // No error as we have already checked it WriteLine(objNullRef!.Length); // No error
5.本地方法和函数
在当前的 C# 版本中已经有本地方法和函数(请看 Func 和 Action), 但对于本地方法仍有一些限制,例如不能使用如下特性:
- 泛型
- 输出参数
- Ref
- params
而现在 C# 7.0 就解决了这些问题,请看下面代码:
private static void Main(string[] args) { int local_var = 100; int LocalFunction(int arg1) { return local_var * arg1; } Console.WriteLine(LocalFunction(100)); }
6.代码可读性的提升
我们经常在代码中使用字面量,如果这些字面量太长就会影响可读性。因此 C# 7.0 在这方面做了改进。C# 7.0 允许使用 '_' 下划线以便于更好的理解,如下代码所示:
var lit1 = 478_1254_3698_44; var lit2 = ab0Xab_bc47at_XY; //C# also come with binary literal for bunary values var binLit = 1100_1011_0100_1010_1001;
7.模式匹配
C# 7.0 允许用户在 IS 和 SWITCH 语句中使用模式匹配,因此我们可以匹配任意的数据类型,模式可以是常亮模式,类型模式以及 Var 模式。下面的代码将有助于你理解这个概念,让我们从 IS 模式开始:
public void Method1( object obj) { //following null is constant pattern if (obj is null) return; //datatype pattern, string is datatype that we check directly if (obj is string st) { //code goes here } else return; }
Switch 模式 可以通过额外的 case 语句在使用任意类型的数据匹配实现更多的帮助和更灵活的方式。
class Calculate(); class Add(int a, int b, int c) : Calculate; class Substract(int a, int b) : Calculate; class Multiply(int a, int b, int c) : Calculate; Calculate objCal = new Multiply(2, 3, 4); switch (objCal) { case Add(int a, int b, int c): //code goes here break; case Substract(int a, int b): //code goes here break; case Multiply(int a, int b, int c): //code goes here break; default: //default case break; }
8.通过 Ref 返回 'return'
你是否尝试过在方法中返回变量的引用?C# 7.0 就允许你这样做。你可以传递一个使用 Ref 声明的变量并作为 Ref 返回,也可以作为 Ref 存储,是不是很神奇?
来看代码:
ref string getFromList(string strVal, string[] Values) { foreach (string val1 in Values) { if (strVal == val1) return ref val1; //return location as ref not actual value } } string[] values = { "a", "b", "c", "d" }; ref string strSubstitute = ref getFromList("b", values); strSubstitute = "K"; // replaces 7 with 9 in the array System.Write(values[1]); // it prints "K"
9.表达式可以抛出异常
public string getEmpInfo( string EmpName) { string[] empArr = EmpName.Split(","); return (empArr.Length > 0) ? empArr[0] : throw new Exception("Emp Info Not exist"); }

浙公网安备 33010602011771号