作者:empty 页数:134 出版社:empty |
模式匹配扩展可C#实现与功能语言的代数数据类型和模式匹配的许多忧势,但这种方式与基础语言的外观紧密集成。基本功能包括:记录类型,这些类型的语义含义由数据形状描述,和模式匹配,这是一个新的表达式窗体,用于后用这些数据类型的极简的多级分解。此方法的元秦通过编程语言F#和Scala中的相关功能来实现。为expression扩展1s运算符以针对视式测试表达式。
这种形式的relationaL expression除了C#规范中的現有窗体外。如果is标记左倒的relational expression来指定值或没有类型,则会发生编译时错误。该模式的每个标识符都引入了一个新的局部变量, 该局部变量在is运算符true后(即, 如果为true, 为明确值)。注意:在技术上, 1s-expression和constant pattern中的类型之间存在二义性, 其中可能是限定标识符的有效分析,我们尝试将其绑定为类型以与以前版本的语言兼容,只有当这种情况失败时,我们才会将其解析为在其他上下文中执行的操作(必须是常量或类型)。这种歧义仅出现在is表达式的右侧。模式模式在1s运算符和switch_statement中用于表示要比较传入数据的数据的形状。模式可以是递归的, 以便可以将部分数据与子模式进行匹配。
注意:在技术上, is-expression和cons ant pattern中的类型之间存在二义性, 其中可能是限定标识符的有效分析,我们尝试将其绑定为类型以导以前版本的语言兼容;只有当这种情况失妝时,我们才会将其解析为在其他上下文中执行的操作(必须是常量或类型)。这种歧义仅出现在1s表达式的右侧。声明模式如果测试成功, 则declaration_pattern两个测试表达式是否为给定的类型并将其转换为该类型。如果smp le_designation是一个标识符, 则会引入给定标识符的给定类型的局部变量。当模式匹配操作的结果为true时,将明磅分配该局部变量。declaration_pattern此表达式的运行时语义是根据模式中的类型测试左relational expression操作数的运行时类型。如果它属于此运行时类型(或某些子类型) , 则true is operator的结果。它声明一个由标识符命名的新局部变量.该标识符在结果true时赋给左操作数的值。左侧和给定类型的静态类型的某些组合被视为不兼容井导致编译时错误。如果存在标识转换、隐式引用转换,装箱转换、显式引用转换或从E到T的取消装箱转换,则将静态类型:的值称为模式r兼容。如果类型E的表达式不与它所匹配的类型模式中的类型兼容,则会发生编译时错误。注意:在C#7.1中,我们会扩展此项,以便在输入类型或类型T是开放类型时允许模式匹配操作。此段落替换为以下内容左侧和给定类型的静态类型的某些组合被视为不兼容井导致编译时错误。如果存在标识转换、隐式引用转换、装箱转换,显式引用转换或从E到一的取消装箱转换,或者E或T是开放类型,则将静态类型E的值视为与类型T模式兼容.如果类型E的表达式不与它所匹配的类型模式中的类型兼容,则会发生编译时错误。声明模式对于执行引用类型的运行时类型测试非常有用.井且替换了方法
否则, 如果object.Equals(e, c) 返回true模式, 则视为匹配, 在这种情况下, 如果c的静态类型与常量的类型不兼容则会发生编译时错误。Var模式var_pattern表达式e与var_pattern总是匹配。换营之, 与var模式匹配始终会成功。如果siple_designation是标识符, 则在运行时,e的值将绑定到新引人的局部变量。局部变量的类型为e的静态类型。如果名称var绑定到类型, 则是错误的。扩展了switch语句, 以选择执行第一个具有导switch表达式相匹配的模式的块。未定义模式匹配的顺序。允许编译器按顺序匹配模式,并重复使用已匹配的模式的结果来计算其他模式的匹配结如果存在case保护, 则其表达式的类型为b col, 它作为附加条件进行评估.此条件必须满足, 才能认为需要满足如果switch_la be/在运行时不起作用, 则是错误的, 因为在以前的情况下, 其模式归入。[TO DO:我们应该更精确地了解编译器要求使用哪种方法才能达到这一判断。]当且仅当该事例块精确包含一个switch_/a be时, 在switch_label中声明的模式变量将在其case块中明确眠值。。如果模式为case标签, 则该变量的作用域为事例块。否则, 特在is pattern表达式中声明变量, 并且其作用域基于直接包合is_pattern表达式的表达式的构造.如下所示:·如果表达式位于expression-bodied lambda表达式中, 则其作用域为lambda的主体。·如果表达式在expression-bodied方法或属性中, 则它的作用域是方法或属性的主体。·如果表达式位于catch子句的x hen子句中, 则该表达式的作用域是catch的子句。·如果表达式位于i terai on_statement中, 则它的作用域只是该语句。·否则,如果表达式是在其他语句形式中.则它的作用域是包含语句的作用域。为了确定作用域, embedded_statement被视为位于其自身的作用域中。例如, if statement的语法为因此, 如果i statement的受控语句声明一个模式变量, 则其作用域限制为该embedded_statement:其他情况是出于其他原因(例如,在参数的默认值或属性中)错误,这两者都是惜误,因为这些上下文需要常量表达·如果表达式在构造函散韧始值设定项中,则其作用域为构造函数始值设定项和构造函数的主体。·如果表达式所在的查询子句所指定的值将转换为lambda体, 则该表达式的作用域只是该表达式。可以解释为对具有两个自变量的的调用G A和U>(7)。或者.它可以解释为对下的调用,该参数是如果可以将标记序列(在上下文中)作为简单名称(第7.6.3)、成员访向(第7.65)或指针-成员访阿(第18.52)以类然后,特类型参数列表保留为简单名称、成员访问或指针成员访向的一部分,并且会丢弃标记序列的任何其他可能分析。否则,类型参数列表不会被视为简单名称、成员访向或>指针成员防向的一部分,即使没有其他可能的标记序列分析也是如此。请注意,当在命名空间威类型名称中分析类型参散列表时,不应用这些规则(第3.8根据此规则,书解释为对F的调用,该参数是一个参数,它是对具有两个类型参数和一个正则参数的泛型方法
Contents
最新功能规范
C#7.0规范建议
模式匹配
本地函数
Out变量声明
引发表达式
二进制文本
数字分隔符
C#7.1规范建议
异步主方法
默认表达式
推导元组名
使用泛型的模式匹配
C#7.2规范建议
只读引用
ref-like类型的编译时安全性
非尾随命名参数
专用受保护
条件引用
前导数字分隔符
C#7.3规范建议
非托管的泛型类型约束
无论上下文是可移动还是不可移动, 索引fixed字段都不应要求固定
基于模式的fixed语句
Ref局部重新分配
Stack alloc数组初始值设定项
面向自动实现的属性字段的特性
初始化表达式中的表达式变量
元组相等(==)和元组不等(!=)
改进了重载候选项
C#8.0规范建议
可为null的引用类型-建议
可为null的引用类型-规范
递归模式匹配
默认接方法
异步流
范围
基于模式的using和using声明
静态本地函数
Null合并分配
只读实例成员
嵌套stack alloc
7的C#模式匹配
2020/6/29-·Edit Qn line
:relational_expression'is pattern
:declaration pattern
|constant_pattern
|var_pattern
:type simple_designation
:shift expression
:'var'simple_designation
:types in ple_designation
:shift_expression
模式匹配扩展可C#实现与功能语言的代数数据类型和模式匹配的许多忧势,但这种方式与基础语言的外观紧密集
成。基本功能包括:记录类型,这些类型的语义含义由数据形状描述,和模式匹配,这是一个新的表达式窗体,用于后
用这些数据类型的极简的多级分解。此方法的元秦通过编程语言F#和Scala中的相关功能来实现。
为expression
扩展1s运算符以针对视式测试表达式。
relational_expression
这种形式的relationaL expression除了C#规范中的現有窗体外。如果is标记左倒的relational expression来指定值
或没有类型,则会发生编译时错误。
该模式的每个标识符都引入了一个新的局部变量, 该局部变量在is运算符true后(即, 如果为true, 为明确
值)。
注意:在技术上, 1s-expression和constant pattern中的类型之间存在二义性, 其中可能是限定标识符的有效分
析,我们尝试将其绑定为类型以与以前版本的语言兼容,只有当这种情况失败时,我们才会将其解析为在其他上
下文中执行的操作(必须是常量或类型)。这种歧义仅出现在is表达式的右侧。
模式
模式在1s运算符和switch_statement中用于表示要比较传入数据的数据的形状。模式可以是递归的, 以便可以将
部分数据与子模式进行匹配。
pattern
declaration_pattern
constant_pattern
var_pattern
注意:在技术上, is-expression和cons ant pattern中的类型之间存在二义性, 其中可能是限定标识符的有效分
析,我们尝试将其绑定为类型以导以前版本的语言兼容;只有当这种情况失妝时,我们才会将其解析为在其他上
下文中执行的操作(必须是常量或类型)。这种歧义仅出现在1s表达式的右侧。
声明模式
如果测试成功, 则declaration_pattern两个测试表达式是否为给定的类型并将其转换为该类型。如
果smp le_designation是一个标识符, 则会引入给定标识符的给定类型的局部变量。当模式匹配操作的结果为true
时,将明磅分配该局部变量。
declaration_pattern
此表达式的运行时语义是根据模式中的类型测试左relational expression操作数的运行时类型。如果它属于此运
行时类型(或某些子类型) , 则true is operator的结果。它声明一个由标识符命名的新局部变量.该标识符在结
果true时赋给左操作数的值。
左侧和给定类型的静态类型的某些组合被视为不兼容井导致编译时错误。如果存在标识转换、隐式引用转换,装箱
转换、显式引用转换或从E到T的取消装箱转换,则将静态类型:的值称为模式r兼容。如果类型E的表达
式不与它所匹配的类型模式中的类型兼容,则会发生编译时错误。
注意:在C#7.1中,我们会扩展此项,以便在输入类型或类型T是开放类型时允许模式匹配操作。此段落替换
为以下内容
左侧和给定类型的静态类型的某些组合被视为不兼容井导致编译时错误。如果存在标识转换、隐式引用转换、
装箱转换,显式引用转换或从E到一的取消装箱转换,或者E或T是开放类型,则将静态类型E的值视
为与类型T模式兼容.如果类型E的表达式不与它所匹配的类型模式中的类型兼容,则会发生编译时错误。
声明模式对于执行引用类型的运行时类型测试非常有用.井且替换了方法
var v=expr as Type;
1f(vl-null) {I/code using v}
稍微简单一些
if(expr is Typo V) {//code using v)
如果芙型是可以为null的值类型, 则是请误的,
声明模式可用于测试可为null的类型的值:类型为Null abl acT>(或装箱T) 的值与类型模式匹配T21d如果该值
不为null并且T 2的类型为T或!的某些基类型或接, 例如, 在代码片段中
int?x=3;
1f(x1s1ntv) {I/code using v}
在运行时true if语句的条件, v在块内保存类型int的值3.
常量模式
constant_pattern
常数模式根据常数值测试表达式的值, 常数可以是任意常量表达式, 如文本、声明的const变量的名称、枚举常量
或type of表达式。
如果e和c均为整型类型, 则当true表达式e--c的结果时, 模式将被视为匹配。
否则, 如果object.Equals(e, c) 返回true模式, 则视为匹配, 在这种情况下, 如果c的静态类型与常量的类型不兼
容则会发生编译时错误。
Var模式
var_pattern
表达式e与var_pattern总是匹配。换营之, 与var模式匹配始终会成功。如果siple_designation是标识符, 则在运行
时,e的值将绑定到新引人的局部变量。局部变量的类型为e的静态类型。
如果名称var绑定到类型, 则是错误的。
扩展了switch语句, 以选择执行第一个具有导switch表达式相匹配的模式的块。
未定义模式匹配的顺序。允许编译器按顺序匹配模式,并重复使用已匹配的模式的结果来计算其他模式的匹配结
如果存在case保护, 则其表达式的类型为b col, 它作为附加条件进行评估.此条件必须满足, 才能认为需要满足
如果switch_la be/在运行时不起作用, 则是错误的, 因为在以前的情况下, 其模式归入。[TO DO:我们应该更精确地了
解编译器要求使用哪种方法才能达到这一判断。]
当且仅当该事例块精确包含一个switch_/a be时, 在switch_label中声明的模式变量将在其case块中明确眠值。
。如果模式为case标签, 则该变量的作用域为事例块。
否则, 特在is pattern表达式中声明变量, 并且其作用域基于直接包合is_pattern表达式的表达式的构造.如下所示:
·如果表达式位于expression-bodied lambda表达式中, 则其作用域为lambda的主体。
·如果表达式在expression-bodied方法或属性中, 则它的作用域是方法或属性的主体。
·如果表达式位于catch子句的x hen子句中, 则该表达式的作用域是catch的子句。
·如果表达式位于i terai on_statement中, 则它的作用域只是该语句。
·否则,如果表达式是在其他语句形式中.则它的作用域是包含语句的作用域。
为了确定作用域, embedded_statement被视为位于其自身的作用域中。例如, if statement的语法为
因此, 如果i statement的受控语句声明一个模式变量, 则其作用域限制为该embedded_statement:
其他情况是出于其他原因(例如,在参数的默认值或属性中)错误,这两者都是惜误,因为这些上下文需要常量表达
·如果表达式在构造函散韧始值设定项中,则其作用域为构造函数始值设定项和构造函数的主体。
·如果表达式所在的查询子句所指定的值将转换为lambda体, 则该表达式的作用域只是该表达式。
可以解释为对具有两个自变量的的调用G A和U>(7)。或者.它可以解释为对下的调用,该参数是
如果可以将标记序列(在上下文中)作为简单名称(第7.6.3)、成员访向(第7.65)或指针-成员访阿(第18.52)以类
然后,特类型参数列表保留为简单名称、成员访问或指针成员访向的一部分,并且会丢弃标记序列的任何其他可
能分析。否则,类型参数列表不会被视为简单名称、成员访向或>指针成员防向的一部分,即使没有其他可能的
标记序列分析也是如此。请注意,当在命名空间威类型名称中分析类型参散列表时,不应用这些规则(第3.8
根据此规则,书解释为对F的调用,该参数是一个参数,它是对具有两个类型参数和一个正则参数的泛型方法
; 'var'sin ple_designation
Switch语句
switch_label
case guard
果。
此条件。
[TO DO:应指定何时可以访问switch块。]
模式变量的范围
在模式中声明的变量的作用城如下:
:'case'co plex pattern case guard?:
l'case'can stant_expression case_guard':
l'default'tr'
:'M hen'expression
if_statement
if(x) H(y is var z) ;
在这种情况下, :的作用域为嵌入的语句M(y is var 2) ; .
式,
在C#73中,我们添加了以下上下文,可在其中声明模式变量
:'if'('boolean_expression') es bedded_state nent
F(GcA, B(7) ) ;
F(GcA, B>(7) ) ;
F(G A,B>7);
Is frr('boole at_expression'yer bedded_state nent else'en bedded_state nent
·如果表达式在字段初始值设定项中.其作用域就是它出现的equals value clause。
对句法歧义的更改
在某些情况下,出现语法C#不明确的情况,语营规范说明了如何解决这些歧文:
7.6.5.2语法多文性
简单名称(第7.6.3)和成员访同(第7.6.5)的生产可以在表达式的语法中产生歧义。例如,语句:
一个参数,它是对具有两个类型参数和一个正则参数的泛型方法的调用G.
型参数列表(第44.1)结尾,则将检查紧跟在结束、标记后面的标记。如果是
()]}:;,-1-1n
节),语句
的调用6.语句
F(G A,B7);
每个都将解释为对具有两个自变量的的调用。语句
x=FcA>+y;
将被解释为小于运算符、大于运算符和一元正运算符,就如同语句已写入x-(F《A)>(+y),而不是作为带有
后跟二元加法运算符的类型参数列表的简单名称。在语句中
x-y is CcT>+7;
标记CCT>被解释为带有类型参数列表的命名空间或类型名称。
7中C#引入了许多更改,这使得这些歧文消除规则不再足以处理语言的复杂性,
Out变量声明
现在可以在out参数中声明变量:
MC out Typename) ;
但类型可以是泛型:
MC out AcB>nane) ;
由干参数的语营语法使用expression, 因此此上下文服从消除规则。在这种情况下, 关闭, 后跟一个标识符, 该标
识符不是允许它被视为类型参散列表的标记之一。因此,我建议将标识符添加到用于触发类型参数列表的消除
歧义的令牌集。
元组和析构声明
元组文本运行完全相同的问题。考虑元组表达式
(A B, C>D, EcF, G>H)
在用于分析C#参数列表的旧6个规则下, 这会分析为具有四个元素的元组, 从AcB开始。但是, 如果在析构的左
测出现这种情况,我们需要由标识持标记触发的歧义消除,如上所述:
{AcB, CD, EcF, GH) -0;
这是声明两个变量的析构声明, 其中第一个变量的类型为A KBC>和命名D。换之, 元组文本包含两个表达式,
其中每个表达式都是一个声明表达式。
为了简化规范和编译器,我建议将此元组文本分析为双元素元组(无论它是否显示在值的左侧)中。这是上一节中
所述歧文消除的自然结果。
模式匹配
模式匹配会引入一个新的上下文,在此上下文中会出现表达式类型的多义性。之前,1s运算符的右边是一个类
型,现在,它可以是类型或表达式,如果它是类型,则可以后跟标识符。从技术上讲,可以更改现有代码的含文:
var x-e1sTcA>B;
可在c#6规则中将其分析为
var x=((eisT) A) >B;
但在c#7规则下(上面建议的歧义消除)将被解析为
var x=e is TcAs 8;
T cAo类型的变量:声明。幸运的是, 本机编译器和Roslyn编译器都有bug, 因此它们给出了c#6代码的语法错
误。因此,不需要考虑这种特殊的重大更改。
模式匹配引入了其他标记,这些标记应促进选择类型的多义性解析。下面的现有有效c#6代码的示例将中断,无
需外消除规则:
var x=eisA cB>85f;//&s
var x-e1sAcBsIIf;//l
var x=eisA cB>&f://&
var x=eisA cB[] ://[
消除歧义规则的建议更改
我建议修订规范,以更改歧义命牌的列表
()])
to
()]}?=-l=ln8&II&[
在某些上下文中, 我们将标识符视为歧义标记。这些上下文包括:要消除的标记的序列紧靠某个关键宇1s、case
或out, 或者分析元组文本的第一个元素(在这种情况下.命牌前面是(或:, 标识符后跟, ) 或元组文本的后
续元素。
修改后消除规则
修改后的消除歧义规则如下所示
如果可以将标记序列(在上下文中)作为简单名称(第7.6.3)、成员访问(第7.6.5)或指针-成员访问(第1852)以类
型参数列表(第44.1)结尾,则将检查紧跟在结束>标记后面的标记,以查看它是否为
() ] } :; , .?.lml“8a|x【之一或
·其中一个关系运算符c>ci5as;或
·上下文查询关键字显示在查询表达式中;或
·在某些上下文中,我们将标识符视为歧义标记。这些上下文包括:要消除的标记的序列紧靠在分析元组文本
的第一个元素时is、case或out.成在分析元组文本的第一个元素时(在这种情况下.命牌前面是(或
,标识符后跟,)或元组文本的后续元素。
如果以下标记在此列表中,或在此类上下文中为标识符,则会将类型参数列表保留为菌中名称、成员访向或指针
成员边向的一部分,并且会丢弃标记序列的任何其他可能分析,否则,类型参散列表不被视为简名称、成员访
向或指针访阿权的一部分,即使没有其他可能的标记序列分析也是如此。请注意,当在命名空间或类型名
称中分析类型参数列表时,不应用这些规则(第3.8节)。
由于此建议造成的重大更改
由于此建议的消除歧义规则,不能识别重大更改,
有趣的示例
下面是这些歧文消除规则的一些有趣的结果:
表达式(Ac8,C>D)是具有两个元秦的元组,每个元秦都是比较。
表达式(AcB, C>D, E) 是具有两个元素的元组, 其中第一个元素是声明表达式。
调用M(ACB, C>O, E) 具有三个参数。
调用M(out AcB, CO, E) 有两个参数, 第一个参数是out声明。
e1sAcBsc使用声明表达式的表达式。
Case标签case AdB>C:使用声明表达式。
模式匹配的一些示例
为-As
我们可以替换用法
var vu expr as Type;
if(vI-null) (
稍微简单、直授
假设我们定义一组递归类型来表示表达式(每个单独的提议):
现在, 我们可以定义函数来计算表达式的(unreduced) 导数:
//code using v
if(expr is Type v) {
//code using v
测试可为null
我们可以替换用法
Type?v-xl-y?.z;
1f(v, Has value} {
稍徽简单、直接
var value=v.GetValue Dr Default() ;
//code using value
if(x?.yr.z is Type value) {
//code using value
算术简化
abstract class Expr;
class X() :Expr;
class Const(doublevalue) :Expr;
class Add(Expr Left, Expr Right) :Expr;
class Halt(Expr Left, Expr Right) :Expr;
class Neg(Expr value) :Expr;
Expr Deriv(Expre)
表达式simplifier演示位置模式:
suit ch(e) (
ExprS in pl if y(Expre)
ca seXO:return Const(1);
case Const(*) :return Const(8) ;
case Add(var Left, var Right) :
return Add(Deriv(Left) , Der1v{Right) ) ;
case NuIt(var Left, var Right) ;
return Add(Hult(Deriv(Left) , Right》, Nul t(Left, Deriv(Right) ) ) ;
case Neg(var Value) :
return Neg(Deriv(Value) ) ;
suit ch(e) (
case Nul t(Const(e) , *) :return Const(e) ;
case Nul t( , Const(a) ) :return Const(e) ;
case Mult(Const(1) , var x) :retum5inplify(x) ;
case Nul t(var x, Const(1) ) :returnS in pl if y(x) ;
case Nul t(Const(var 1) , Canst(var r) ) :ret umn Const(1*r) ;
case Add(Const(e) , var x) :return Simplify(x) ;
case Add(var x, Const{e) ] :return Simplify(x) ;
case Add(Const(var 1) , Const(var r) ) :return Const(l+r) ;
case Neg(Const(var k) ) :return Const(-k) ;
default:return e;
本地函数
2020/6/29·:Edit Qn line
:local-variable-declaration t; '
l local-constant-declaration;
|I ocal-function-declaration
我们扩展C#了以支持块范围内的函数声明。本地函数可以使用封闭范围内的(捕获)变量。
编译器使用流分析来检测本地函数使用的变量,然后再为其试值。函数的每个调用都需要明确赋值此类变量。同
样,编译器会确定返回时明确赋值的变量。调用本地函数后,此类变量被视为明确赋值。
在定义之前,可以从词法点调用本地函数。当本地函数声明语句不可访问时,它们不会导致警告。
TO DO:编范
语法语法
此语法表示为与当前规范语法的不同之处。
declaration-statement
+local-function-declaration
本地函数可能使用封闭范围中定义的变量。当前实现要求在本地函数内读取的每个变量都是明确赋值的,如同在其
在试验这一点之后(例如,不可能定义两个相互归的本地函数),我们已经修改了我们希望明确赋值的工作方式,
修订版本(尚未实现)是在本地函数中读取的所有局部变量都必须在本地图数的每个调用中明确赋值。这实际上比
声音更为微妙,而且还有一组工作要使其正常工作。完成后,您将能够将您的本地丽数移动到它的封闭块末尾。
新的明确眠慎规则与推断本地困数的返回类型不兼容,因此,我们可能会删除对推断返回类型的支持。
除非将本地函数转换为委托,否则将在值类型为的帧中进行捕获。这意味着,不会因将本地函数与捕获一起使用而
:local-function-header local-function-body
;
+local-functi an header
:local-function-nodi fiers?re tum-type identifier type-par are ter-list?
+local-functi an-nod1fiers
(for nal-para neter-list?) type-par are ter-constraints-clauses
:(async l unsafe)
+local-function-body
:block
larr uw-expression-body
定义点执行本地函数一样。此外,还必须在任何使用点“执行“本地函数定义。
获得任何垃圾回收压力。
可访问性
我们添加到规范
|语句expresion-bodied lambda表达式或本地函数的主体被视为可访问,
Out变量声明
2020/6/29·Edt Q nine
:out'type identifier
l.
2020/6/29·:Edit Qn line
Out变量声明功能允许在将变量作为out参数传递的位道声明该变量,
argument_value
用这种方式声明的变量称为out变量。您可以对变量的类型使用上下文关键字var。作用域将与通过模式匹配引
人的模式变量的作用域相同。
根据语言规范(7.6.7元素访问部分) , 元素访问的参数列表(案引表达式) 不包含ref或out参数。但编译器允许它们
用于各种方案, 例如, 在接受out的元数据中声明的索引器。
在argument_value引入的本地变量的范围内.在其声明之前的文本位置引用该局部变量是编译时错误。
在立即包含其声明的同一个参数列表中引用隐式类型化的(第8.5.1) out变量也是错误的。
重载决策的修改方式如下:
我们添加了一个新的转换;
存在从隐式类型化的out变量声明到每个类型的表达式的转换。
又
式类型化出变量的类型是声明的类型。
and
式类型化出变量没有类型,
从隐式类型化出变量声明中的表达式的转换不会被视为比从表达式进行的任何其他转换都好。
隐式类型化out变量的类型是重款决策选择的方法签名中的相应参数的类型。
添加了新的语法节点Declaration Expression Syntax以表示out var参数中的声明。
Throw表达式
我们扩展了要包含的表达式窗体集
throw_expression
null_coalescing_expression
类型规则如下所示:
·Throw_expression没有类型。
·Throw expression可以通过隐式转换转换为每种类型。
Throw达式引发的伯是通过计算nulL coale sing_expression得出的值, 该nulL coalescing_expression必须表示从
Systen.Exception派生的类类型syste r.Exception的美类型的伯, 成者是具有其有效基类的System.Exception(或
子类) 的类型参数类型的值。如果表达式的计算生成nu1l, 则改为引发Systen.NullReferenceException。
计算引发表达式时的行为与为throw语句指定的行为相同。
流分析规则如下所示:
·对于每个变量v, 都将在throw_expression iff的nul_coalescing, expression之前明确赋值v, throw_expression之
·对于每个变量v, V在throw_expression后都是明确赋值。
:'throw null_coalescing_expression
:throw_expression
前,该变量已明确赋值。
仅在以下语法上下文中允许引发表达式
·作为三元条件运算符的第二个或第三个操作数?:
·作为null合并运算符的第二个操作数??
·作为expression-bodied lambda或方法的主体。
一
进制文本
2020/6/29··Edit Qn ling
:.
|binary-integer-literal
向C#和VB添加二进制文本的请求相对较为常见。对于位撞码(例如标志枚举),这似乎真正有用,但它也只是为了
便于教学。
二进制文本如下所示:
int nineteen-Ebi a 811;
在语法和语义上,它们与十六进制文本相同,不同之处在于,使用b/B.而不是x/x.只需使用数字。和1.
并在base 2中进行解释, 而不是16.
实现这些和对语言用户的概念性开销没有太大的代价。
语法
语法如下所示:
integer-literal:
binary-integer-literal:
binary-digits:
binary-digit:
能够在大数值中对数字进行分组会给您带来很大的可读性影响,并且没有明显的缺点,
添加二进制文本(#215)会增加数值文本的可能性,因此这两个功能互相增强。
我们将遵循Java和其他方法, 并使用下划线作为数字分隔符。它可以在数字文本中的任何位置发生(除了第一
个字符和最后一个字符),因为不同的分组在不同方案中可能有意义,特别是对于不同的数字基准
任何数字序列都可以用下划线分隔,两个连续数字之间可能有多个下划线,它们在小数和指数中是允许的,但在前
面的规则后,它们可能不会出现在指数字符(1.1e_1)旁边或类型说明符(10_f)旁的小数点(10_.0)的旁边。在二
进制和十六进制文本中使用时,它们可能不会立即出现在ex或eb之后。
:oo binary-digits integer-type-suffix-opt
|7eB binary-digits integer-type-suffix-opt
:binary-digit
|binary-dig tts binary-digit
:0
11
数字分隔符
2020/6/29·Edt Q nine
int bin-eb 1881_1818_o aei_e iee;
in the x=ex1b_ao_44_fe;
Int dec-33_554_432;
int we frd=1_2_ 3455_
doublereal=1088.111le-1_880;
语法非常简单,分隔符没有语义影响,它们只是被忽略。
这有很大的价值,井且很容易实现。
9;
Async Main
2020/6/29··Edi Q nine
·[x]建议
·门原型
·门实现
·门规范
总结
允许在应用程序的Main/entrypoint方法中使用aws it, 方法是尤许入点返回Task/Task cint并将其标记为
async.
动机
在学习C#时, 在编写基干控制台的实用程序时, 以及在编写要从Main调用和au a it async方法的小型测试应用
程序时, 此方法非常常见。如今, 我们通过强制在单独的异步方法中完成此类await的操作, 在此处添加了一个级
别的复杂程度,使开发人员只需编与如下所示的样板即可开始使用
public static void Na in()
private static async Task Hain Async{)
我们可以消除对这种样板的需求.使其更易于开始, 只需允许主要async以便在其中使用ma it·
为避免出现兼容性风险,如果不存在以前集的任何重载,则这些新签名仅被视为有效的5。语言/编译器不需要将
entrypoint标记为async, 不过, 大多数使用情况都将标记为。
当其中一项被标识为入点时, 编译器将合成调用以下编码方法之一的实际enty point方法;
允许async void。对于直接调用该语义的代码, 我们需要将其保持不变, 这样就会使得生成的入点调用它(未返
使用“Main Async*而不是“Main'作为名称。尽管建议对返回任务的方法使用async后缀但主要是关于库功能(主
MairA sync O) , Get waiter() .Get Result() ;
.//Hain body here
详细设计
当前允许s以下签名:
static void Hain()
static void Hain fstring[] )
static in tHain()
static in tHain(string[] )
我们将扩展允许的s的列表,使其包括:
static Task Hain()
static Task cint sHain()
static Task Hain(string[lY
static Task cint>Hain(string[] )
·static Task Main() 将导致编译器发出等效的
private static voidS Generated Hain() -Hain() .Get As a iter() -Get Re suit() ;
static Task Main(string[] ) 将导致编译器发出等效的
private static voidS Gone rated Hain(string[] args) ->Hain(args) .Get A waiter() .Get Result O;
·static Task cint>Mo inC) 将导致编译器发出等效的
private static int$Generated Hain() ->Hain() .Get A walter() .Get Result() ;
·static Task cint>Main(string[] ) 将导致编译器发出等效的
private static intS Generated Hain fstring D] args) ->Main(args) .Get A walter() .Get Result O;
用法示例:
using Systen;
using Syste r.Net.Http i
class Test
回任务)变得困难。我们可以通过生成另外两种方法来解决这种情况,例如:
private static vol dS Entrypoint Hain() =>Hain() .Get Au a it erO) .Get Result() ;
static async Task Hain(string[] args) ->
缺点
主要缺点只是支持其他入点签名的额外复杂性。
备选项
其他变体
public static async void Main O
变成
public static async void Main() →>am a itS Hain Task O;
private static async TaskS Hain Task()
还有关于鼓励使用async void的问题。
要不是) , 并且支持其他入点名称超出“Main'。
Console.M rite Line(au a it new HttpClient() .GetString Async(args[8] ) ) ;
.//avait code
.l/au a it code
未解决的问题
不适用
设计会议
不适用
·[x]建议
·[x]原型
·[x]实现
·门规范
目标类型“默认 文本
2020/6/29·:Edit Qn line
总结
目标类型化default功能是default(T) 运算符的较短形式, 这允许省略类型。改为通过目标类型推断其类型。除
此之外, 它的行为类似于default(T)
动机
主要动机是避免键入冗余信息。
例如, 在调用void H ethod(Irr u table Array cS one Type>array) 时, 默认文本尤许H(default) 代替
H(default(I mau table Array c Sore Types) ) 。
这适用干许多方案,例如:
·