这个版本中,代码的简化和性能的提升是关键点。Tuples 元组、模式匹配是一些相当棒的新特性。希望你会喜欢这些改进。
接下来让我们看看 C# 7.0 到底有什么新特性。
代码使用
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 。
析构
绝大多数时候我们不会去访问整个 Tuple 元组,或者说我们只需要内部的一些值,这个时候我们就可以用 C# 7.0 的 Deconstruction 析构特性,通过它轻松释放一个元组或者从中获取所需的值,请看如下代码:
( string strFName, string strAdd, string strC, string strSt) = getEmpInfo();
Console.WriteLine($"Address: { strAdd }, Country: { strC }");
记录类型 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;}}
}
class studentInfo(string StudentFName, string StudentMName, string StudentLName);
一行代码搞定!
上面代码和前面我们定义的类效果一样。
最小化 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"
}
不允许为空的引用类型

空的引用对所有程序员来说都是一个头疼的问题,这个问题值 100 万美元。如果你没有对这些问题进行检查,就会经常在程序运行期间碰到各种空引用的问题。而 C# 7.0 给我们带来了“非空引用类型”。
我认为这个语法目前还没有固定下来,接下来他们还会发布如下语言:
‘?‘ 用于允许为空的值类型,而 ‘!‘ 是不允许为空的引用类型。
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
本地方法和函数

在当前的 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));
}
上述代码中我们定义了一个 ‘LocalFunction’ 作为本地函数,该函数位于 Main 函数中,我们可以在函数中使用 out 或者 ref 。
代码可读性的提升

我们经常在代码中使用字面量,如果这些字面量太长就会影响可读性。因此 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;
字面量其实什么都不是,无非就是一个预定义的常量值(Litearls in C#)
模式匹配

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;
}
上面例子中 switch case 对模式的检查方法为 Multiply 。
通过 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"
In above sample we have find and replace a string, by return a Ref from method.
Throw Exception from Expression

没错,C# 7.0 可以直接在表达式中抛出异常,请看:
public string getEmpInfo( string EmpName)
{
string[] empArr = EmpName.Split(",");
return (empArr.Length > 0) ? empArr[0] : throw new Exception("Emp Info Not exist");
}
上述代码中我们可以直接在 return 语句中抛出异常,这个真的很棒!
注意点
上述所有特性都是微软已经通过 Visual Studio 2015 Release 4 中附带的 C# 7.0 中提供。
希望你会喜欢 C# 7.0 的新特性。
祝编码愉快!
转载请标明出处:梦在这里
本文地址:linmi.cc/?p=653
