文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏
参与翻译: CY2 (8), coyee (7)

介绍

C# 7.0 计划分成几个步骤进行发布,微软将会在 Visual Studio 15 Preview 4 版本时一起发布(2016年8月),这将会包含 C# 7.0 的绝大多数新特性。详情请看 Release Post

这个版本中,代码的简化和性能的提升是关键点。Tuples 元组、模式匹配是一些相当棒的新特性。希望你会喜欢这些改进。

接下来让我们看看 C# 7.0 到底有什么新特性。

代码使用

Tuples 元组

从一个方法中返回多个值是在实际开发中经常会碰到的场景,一般这种情况我们会使用自定义数据类型、输出参数或者返回一个集合的方式。但在 C# 7.0 中通过元组类型以及元组可以很方便的处理这种场景,请看如下代码:

第 1 段(可获 1.71 积分)
( 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 的名称不好看,我们可以在返回前给它指定一些有意义的名称,如下面代码:

第 2 段(可获 0.38 积分)
(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 。

第 3 段(可获 0.65 积分)

.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 }");
第 4 段(可获 1.09 积分)

记录类型 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;}}
}
第 5 段(可获 0.65 积分)

上述代码中我们定义了一个包含属性、构造函数和变量的类,为了访问和声明变量我需要编写更多的代码。

C# 7.0 的 Record Type 可以避免这种情况,请看代码:

class studentInfo(string StudentFName, string StudentMName, string StudentLName);

一行代码搞定!

上面代码和前面我们定义的类效果一样。

最小化 OUT 输出变量

当我们需要一个方法返回多个值的时候,经常会用到输出参数。但是一般输出参数是引用类型,而且它其实就是一个参数,这样使用只不过是受限于语言本身的限制,不过有一个限制就是输出参数在使用前必须被初始化,如下代码所示:

第 6 段(可获 1.25 积分)
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 作为参数类型,这样就不需要使用前进行声明。

第 7 段(可获 0.44 积分)

注意在这里使用的这些变量只在一个受限的范围内有效,因此我们不能在方法外使用这些变量。

一旦我们将变量直接作为参数使用,C# 7.0 可以通过 var 关键字来进行声明。因此你不用担心数据类型问题,请看下面代码:

static void Main()
{
   AssignVal(out var szArgu);
   // here contents of szArgu is "I am from OUT"
}

不允许为空的引用类型

空的引用对所有程序员来说都是一个头疼的问题,这个问题值 100 万美元。如果你没有对这些问题进行检查,就会经常在程序运行期间碰到各种空引用的问题。而 C# 7.0 给我们带来了“非空引用类型”。

第 8 段(可获 1.36 积分)

我认为这个语法目前还没有固定下来,接下来他们还会发布如下语言:

'?' 用于允许为空的值类型,而 '!' 是不允许为空的引用类型。

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
第 9 段(可获 0.45 积分)

本地方法和函数

在当前的 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));
}
第 10 段(可获 0.81 积分)

上述代码中我们定义了一个 '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;
第 11 段(可获 1.01 积分)

字面量其实什么都不是,无非就是一个预定义的常量值(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; 
}
第 12 段(可获 0.81 积分)

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;
}
第 13 段(可获 0.35 积分)

上面例子中 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"
第 14 段(可获 0.75 积分)

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 的新特性。

祝编码愉快!

 

第 15 段(可获 1.24 积分)

文章评论