元组值范例
.NET供应了一个元组(Tuple)范例,但细致在C#中运用时却存在着林林总总的题目。由于元组范例是一个援用范例,因而在一些关于机能相称敏感的代码中,你很可以会防止因运用它而形成GC的开支。同时,元组范例是不可变的,虽然这使跨线程同享变得更平安,但也意味着每次举行变动都必需分派一个新的对象。
为了应对这一题目,C# 7将供应一个值范例的元组。这是一个可变范例,对那些注重机能的代码来讲,这类体式格局将更加高效。同时,作为值范例,它在每次举行分派时都邑生成一个拷贝,因而几乎没有发生多线程题目的风险。
你可以经由过程以下语法建立一个元组:
var result = (5, 20);
你也可以挑选对元组中的值举行定名,这一点并非必需的,只是让代码具有更好的可读性。
var result = (count: 5, sum: 20);
你可以会想,“很棒的特征,但我自身也能写得出来”。但下一个特征才是重头戏。
多返回值
在类C作风的言语中,要在一个函数中返回两个值始终是一件贫苦事。你只能挑选将效果封装成某种构造,或是运用输出参数。与很多函数式编程言语一样,C#挑选了第一种体式格局为你供应这一特征:
(int, int) Tally (IEnumerable<int> list)
可以看到,在这里运用泛用的元组有一个基本题目:我们将无从得知每一个字段的作用。因而,C#挑选经由过程一个编译器花样对效果举行定名:
(int Count, int Sum) Tally (IEnumerable<int> list)
我们在此须要强调一点:C#并没有生成一个新的匿名范例,你所取得的仍旧是一个元组,但编译器将假定它的属性为Count和Sum,而不是Item1和Item2。所以,以下代码行的作用都是等价的:
var result = Tally(list); Console.WriteLine(result.Item1); Console.WriteLine(result.Count);
请注意一点,我们如今还不具有多赋值语法,假如这类语法终究完成,那末它的用法多是如许的:
(count, sum) = Tally(list);
除了供应简朴的功用性函数以外,多返回值的实用性还体如今异步代码的编写上,由于在async函数中是不许可运用out参数的。
形式婚配:革新的Switch语法块
VB与函数式递次员关于C#埋怨得最多的一点就是C#中的switch语句功用非常有限。VB开发者愿望可以举行局限婚配,而习惯了F#或Haskell的开发者则愿望可以运用剖析式的形式婚配。C#盘算同时供应这两种特征。
在对范例举行形式婚配时,你可以建立一个变量以保留转型的效果。举例来讲,在对一个System.Object运用switch语句时,你可以编写以下代码:
case int x:
假如该对象是数值范例,则变量x将得以赋值。不然的话,递次将按从上至下的递次搜检下一个case语句块。假如你想更细致地举行婚配,还可以运用局限搜检:
case int x when x > 0: case int y:
在这个示例中,假如该对象是正整数,则x代码块将被实行。假如对象是0或负整数,而y代码块将被实行。
假如须要搜检null值,则只需运用以下语法:
case null;
形式婚配:剖析
目前为止,我们仅仅展现了某种对VB中已有的特征所做的增量式革新,而形式婚配真正的壮大的地方在于剖析,它可以将某个对象完整拆开,考虑一下以下语法:
if (person is Professor {Subject is var s, FirstName is "Scott"})
这段代码完成了两件事:
它建立了一个当地变量s,将其赋值为((Professor)person).Subject。
它实行了一次相称性搜检 ((Professor)person).FirstName == "Scott"。
假如将其用C# 6代码改写则是如许:
var temp = person as Professor; if (temp != null && temp.FirstName == "Scott") { var s = temp.Subject
在终究宣布中,我们估计可以同时看到对switch语句块的这两种革新。
援用返回
关于大数据构造举行援用通报比起值通报要快很多,由于后者须要对全部构造举行拷贝。与之相似,返回一个大数据构造的援用一样可以提拔速率。
在相似于C如许的言语中,可以经由过程指针返回某个构造的援用。这类体式格局会带来一个罕见的题目,即指针所指向的内存可以会由于某种原因罢了被回收了。
C#经由过程运用援用的体式格局逃避这一题目,援用自身是一个附加了划定规矩的指针。最主要的一条划定规矩是,你不可以返回某个当地变量的援用。假如你尝试如许做,那末该变量所援用的栈信息在函数返回时就已变得不可接见了。
在微软的展现代码中,它所返回的援用指向一个数组中的某个构造。由于它实质上是指向数组中某个元素的指针,因而随后可以对数组自身举行修正。举例来讲:
var x = ref FirstElement(myArray) x = 5; //MyArray[0] now equals 5
这一语法的用例是对机能高度敏感的代码,在大多数运用中都无需运用这一特征。
二进制字面值(Binary Literals)
此次宣布还引入了一个小特征,即二进制字面值。这一语法只是一个简朴的前缀罢了,比方5可以示意为“0b0101”。这一特征的主要用例是设置基于flag的罗列,以及建立位掩码(bitmask),以用于与C作风言语的互操纵。
当地函数
当地函数是指在另一个函数中所定义的函数。第一眼看来,当地函数好像只是比匿名函数稍好的一种语法。但它现实上还存在几个长处:
起首,你无需为其分派一个托付以保留该函数。这不仅减少了内存压力,同时还许可编译器对该函数举行内联操纵。
其次,在建立闭包时,也无需为其分派一个对象,由于它可以直接接见当地变量。这一点一样可以改良机能,由于它也减少了GC的压力。
根据第二条划定规矩推算,你将没法建立一个指向当地函数的托付。这一点关于代码的构造现实上是一个长处,由于你无需建立自力的函数,而且将现有函数的状况作为显式的参数举行通报。
部份类的革新
末了演示的特征是一种处置惩罚部份类的新体式格局。在过去,部份类的运用是基于代码生成优先的观点而涌现的。所生成的代码将包括一系列部份要领,开发者可以挑选完成这些要领,以调解类的行动。
经由过程新的“replace”语法,开发者就多了一种新挑选,可以以最直接的体式格局编写代码,随后再引入代码生成器,并重写这些要领。以下将经由过程一个简朴的示例表现开发者的代码编写体式格局:
public string FirstName {get; set;}
简朴又清楚,但完整不符合XAML作风运用的写法。因而,代码生成器将生成以下代码:
private string m_FirstName; static readonly PropertyChangedEventArgs s_FirstName_EventArgs =new PropertyChangedEventArgs("FirstName") replace public string FirstName { get { return m_FirstName; } set { if (m_FirstName == value) return; m_FirstName = value; PropertyChanged?.Invoke(this, m_FirstName_EventArg); }
经由过程“replace”关键字,所生成的代码将直接替代手写的代码,增加所缺失的功用。在这个示例中,我们以至还可以处置惩罚一些开发者经常会疏忽的贫苦的部份,比方对EventArgs对象举行缓存。
虽然这个官方示例仅用于属性变动关照,但这一手艺还可用于种种“面向切面编程(AOP)”的场景,比方在代码中注入日记纪录、平安搜检、参数校验以及其他种种烦琐的样板式代码。
假如读者想现实相识一下这些特征,可以欣赏Channel 9中的视频“The Future of C#”。
以上就是带你明白C#7 特征代码示例的细致内容,更多请关注ki4网别的相干文章!