当前位置: 首页 > 科技观察

C#7功能预览

时间:2023-03-13 14:34:14 科技观察

在过去的一年里,我们向读者展示了许多被考虑包含在C#7中的功能。在最近发布的VisualStudio15预览版中,Microsoft决定向用户提供这些功能作为C#7最终版本的一部分。元组值类型。NET提供了元组(Tuple)类型,但是在C#中使用会出现各种问题。由于元组类型是引用类型,在一些对性能敏感的代码中,你很可能会避免使用它带来的GC开销。同时,元组类型是不可变的,虽然这使得跨线程共享更安全,但这也意味着每次进行更改时都必须分配一个新对象。为了解决这个问题,C#7将提供一个值类型元组。这是一个可变类型,对于性能关键的代码,这种方法会更有效。此外,作为值类型,每次分配时都会复制一份,因此出现多线程问题的风险很小。您可以使用以下语法创建元组:varresult=(5,20);也可以选择给元组中的值命名,这不是必须的,只是为了让代码更易读。varresult=(计数:5,总和:20);您可能会想,“不错的功能,但我可以自己编写”。但下一个功能才是真正的大问题。多个返回值从一个函数返回两个值在类C语言中总是一件麻烦事。您唯一的选择是将结果封装在某种结构中,或者使用输出参数。与许多函数式编程语言一样,C#选择了第一种方式为您提供此功能:(int,int)Tally(IEnumerablelist)如您所见,这里使用了一个通用元组基本问题:我们将没有知道每个字段做什么的方法。因此,C#选择通过一个编译器trick来命名结果:(intCount,intSum)Tally(IEnumerablelist)这里需要强调一点:C#不会生成新的匿名类型,你得到的仍然是一个元组,但编译器会假定其属性是Count和Sum,而不是Item1和Item2。因此,以下代码行是等效的:varresult=Tally(list);Console.WriteLine(result.Item1);Console.WriteLine(result.Count);请注意,我们还没有多赋值语法,如果最终实现了这个语法,它的用法可能是这样的:(count,sum)=Tally(list);除了提供简单的功能函数外,多个返回值的效用也体现在异步代码的编写上,因为异步函数中不允许有out参数。模式匹配:改进的Switch语法块VB和函数式程序员对C#最大的抱怨之一是C#中switch语句的功能有限。VB开发人员希望能够进行范围匹配,而习惯于F#或Haskell的开发人员希望能够使用分解模式匹配。C#旨在提供这两种功能。当模式匹配一??个类型时,你可以创建一个变量来保存转换的结果。例如,在System.Object上使用switch语句时,可以编写如下代码:caseintx:如果对象是数字类型,则变量x将被赋值。否则,程序将按从上到下的顺序检查下一个case语句块。如果想更具体地匹配,还可以使用范围检查:caseintxwhenx>0:caseinty:本例中,如果对象是正整数,则执行x代码块。如果对象为0或负整数,而y将执行代码块。如果需要检查空值,只需使用以下语法:casenull;它是分解,可以完全分解一个对象。考虑以下语法:if(personisProfessor{Subjectisvars,FirstNameis"Scott"})这段代码完成了两件事:它创建了一个局部变量s并将其赋值给Theassignmentis((Professor)person).Subject。它执行相等性检查((教授)人).FirstName==“Scott”。用C#6代码重写它看起来像这样:块的改进。大型数据结构的引用传递比值传递快得多,因为后者需要复制整个结构。同样,返回对大型数据结构的引用也可以提高速度。在像C这样的语言中,可以通过指针返回对结构的引用。这种方式会带来一个通病,就是指针指向的内存可能因为某种原因被回收了。C#通过使用引用回避了这个问题,引用本身就是一个附加了规则的指针。最重要的规则是您不能返回对局部变量的引用。如果您尝试这样做,则当函数返回时,变量引用的堆栈将已经不可访问。在微软的演示代码中,它返回的引用指向数组中的一个结构。因为它本质上是指向数组中元素的指针,所以数组本身随后可以被修改。例如:varx=refFirstElement(myArray)x=5;//MyArray[0]nowequals5这种语法的用例是对性能高度敏感的代码,在大多数应用程序中不需要使用这个特性。二进制文字此版本还引入了一个小功能,即二进制文字。这个语法只是一个简单的前缀,例如5可以表示为“0b0101”。此功能的主要用例是设置基于标志的枚举和创建位掩码以实现与C风格语言的互操作性。局部函数局部函数是在另一个函数中定义的函数。***乍一看,局部函数似乎只是比匿名函数稍微好一点的语法。但它实际上有几个优点:首先,你不需要分配一个委托来持有这个功能。这不仅减少了内存压力,还允许编译器内联函数。其次,在创建闭包时不需要将对象分配给闭包,因为它可以直接访问局部变量。这也提高了性能,因为它也减少了GC的压力。从第二条规则推断,您将无法创建本地函数的委托。这实际上是代码组织的一个优势,因为您不需要创建单独的函数并将现有函数的状态作为显式参数传递。部分类的改进***特色功能是一种处理部分类的新方法。过去,部分类的应用是基于代码先生成的概念而出现的。生成的代码将包含一系列部分方法,开发人员可以选择实现这些方法来调整类的行为。有了新的“替换”语法,开发人员有了一个新的选择,可以用最直接的方式编写代码,然后引入代码生成器并重写这些方法。下面是一个简单的例子来展示开发者的代码编写方法:publicstringFirstName{get;set;}简单明了,但是不符合XAML风格应用程序的编写方法。因此,代码生成器将生成如下代码:privatestringm_FirstName;staticreadonlyPropertyChangedEventArgss_FirstName_EventArgs=newPropertyChangedEventArgs("FirstName")replacepublicstringFirstName{get{returnm_FirstName;}set{if(m_FirstName==value)return;m_FirstName=value;PropertyChanged?.Invoke(this,m_FirstName_EventArg);}用“replace”关键字,生成的代码将直接替换手写代码,添加缺少的功能。在此示例中,我们甚至能够处理开发人员经常忽略的一些比较棘手的部分,例如缓存EventArgs对象。虽然这个官方示例仅用于属性更改通知,但该技术还可以用于各种面向方面编程(AOP)的场景,例如将登录注入代码、安全检查、参数验证以及.想要了解这些功能的读者可以在第9频道观看视频“C#的未来”。