FeatureTitle
DescriptionPlus
AllHeadersAndTitle
C#
语言规范
3.0
注意
©1999-2008MicrosoftCorporation。保留所有权利。
Microsoft、Windows、VisualBasic、VisualC#和Visual
本文提及的其他产品和公司名称可能是其各自所有者的商标。
目录
1.简介
1.1Helloworld1
1.2程序结构2
1.3类型和变量3
1.4表达式6
1.5语句8
1.6类和对象12
1.6.1成员12
1.6.2可访问性13
1.6.3类型形参13
1.6.4基类14
1.6.5字段14
1.6.6方法15
1.6.6.1参数15
1.6.6.2方法体和局部变量16
1.6.6.3静态方法和实例方法17
1.6.6.4虚方法、重写方法和抽象方法
1.6.6.5方法重载20
1.6.7其他函数成员21
1.6.7.1构造函数22
1.6.7.2属性23
1.6.7.3索引器23
1.6.7.4事件23
1.6.7.5运算符24
1.6.7.6析构函数25
1.7结构25
1.8数组26
1.9接口27
1.10枚举28
1.11委托30
1.12属性31
2.词法结构33
2.1程序33
2.2文法33
2.2.1文法表示法33
2.2.2词法文法34
2.2.3句法文法34
2.3词法分析34
2.3.1行结束符35
2.3.2注释35
2.3.3空白37
2.4标记37
2.4.1Unicode字符转义序列3
2.4.2标识符38
2.4.3关键字40
2.4.4文本40
2.4.4.1布尔值40
2.4.4.2整数41
2.4.4.3实数42
2.4.4.4字符42
2.4.4.5字符串43
2.4.4.6null文本45
2.4.5运算符和标点符号45
2.5预处理指令45
2.5.1条件编译符号47
2.5.2预处理表达式47
2.5.3声明指令48
2.5.4条件编译指令49
2.5.5诊断指令51
2.5.6区域指令51
2.5.7行指令52
2.5.8Pragma指令52
2.5.8.1Pragmawarning
3.基本概念55
3.1应用程序启动55
3.2应用程序终止56
3.3声明56
3.4成员58
3.4.1命名空间成员58
3.4.2结构成员58
3.4.3枚举成员59
3.4.4类成员59
3.4.5接口成员59
3.4.6数组成员59
3.4.7委托成员59
3.5成员访问60
3.5.1已声明可访问性60
3.5.2可访问域61
3.5.3实例成员的受保护访问63
3.5.4可访问性约束64
3.6签名和重载65
3.7范围66
3.7.1名称隐藏68
3.7.1.1通过嵌套隐藏68
3.7.1.2通过继承隐藏69
3.8命名空间和类型名称70
3.8.1完全限定名72
3.9自动内存管理73
3.10执行顺序75
4.类型77
4.1值类型77
4.1.1System.ValueType类型
4.1.2默认构造函数78
4.1.3结构类型79
4.1.4简单类型79
4.1.5整型80
4.1.6浮点型81
4.1.7decimal类型82
4.1.8bool类型82
4.1.9枚举类型83
4.1.10可以为null的类型83
4.2引用类型83
4.2.1类类型84
4.2.2对象类型85
4.2.3string类型85
4.2.4接口类型85
4.2.5数组类型85
4.2.6委托类型85
4.3装箱和拆箱85
4.3.1装箱转换85
4.3.2拆箱转换87
4.4构造类型87
4.4.1类型实参88
4.4.2开放和封闭类型88
4.4.3绑定和未绑定类型89
4.4.4满足约束89
4.5类型形参90
4.6表达式目录树类型91
5.变量93
5.1变量类别93
5.1.1静态变量93
5.1.2实例变量93
5.1.2.1类中的实例变量93
5.1.2.2结构中的实例变量94
5.1.3数组元素94
5.1.4值参数94
5.1.5引用形参94
5.1.6输出形参94
5.1.7局部变量95
5.2默认值95
5.3明确赋值96
5.3.1初始已赋值变量96
5.3.2初始未赋值变量97
5.3.3确定明确赋值的细则97
5.3.3.1一般语句规则97
5.3.3.2块语句、checked和unchecked语句
5.3.3.3表达式语句98
5.3.3.4声明语句98
5.3.3.5if语句98
5.3.3.6switch语句99
5.3.3.7while语句99
5.3.3.8do语句99
5.3.3.9for语句99
5.3.3.10break、continue和goto语句
5.3.3.11throw语句100
5.3.3.12return语句100
5.3.3.13try-catch语句
5.3.3.14try-finally语句
5.3.3.15try-catch-finally语句
5.3.3.16foreach语句10
5.3.3.17using语句102
5.3.3.18lock语句102
5.3.3.19yield语句103
5.3.3.20简单表达式的一般规则10
5.3.3.21带有嵌入表达式的表达式的一般规则
5.3.3.22调用表达式和对象创建表达式
5.3.3.23简单赋值表达式104
5.3.3.24&&表达式104
5.3.3.25||表达式105
5.3.3.26!表达式105
5.3.3.27??表达式106
5.3.3.28?:表达式106
5.3.3.29匿名函数107
5.4变量引用107
5.5变量引用的原子性107
6.转换109
6.1隐式转换109
6.1.1标识转换109
6.1.2隐式数值转换110
6.1.3隐式枚举转换110
6.1.4可以为null的隐式转换1
6.1.5null文本转换110
6.1.6隐式引用转换111
6.1.7装箱转换111
6.1.8隐式常量表达式转换112
6.1.9涉及类型形参的隐式转换112
6.1.10用户定义的隐式转换112
6.1.11匿名函数转换和方法组转换11
6.2显式转换112
6.2.1显式数值转换113
6.2.2显式枚举转换114
6.2.3可以为null的显式转换1
6.2.4显式引用转换115
6.2.5拆箱转换116
6.2.6涉及类型形参的显式转换116
6.2.7用户定义的显式转换117
6.3标准转换117
6.3.1标准隐式转换117
6.3.2标准显式转换117
6.4用户定义的转换118
6.4.1允许的用户定义转换118
6.4.2提升转换运算符118
6.4.3用户定义转换的计算118
6.4.4用户定义的隐式转换119
6.4.5用户定义的显式转换120
6.5匿名函数转换121
6.5.1匿名函数转换为委托类型的计算1
6.5.2匿名函数转换为表达式目录树类型的计算
6.5.3实现示例122
6.6方法组转换125
7.表达式127
7.1表达式的分类127
7.1.1表达式的值128
7.2运算符128
7.2.1运算符的优先级和顺序关联性12
7.2.2运算符重载129
7.2.3一元运算符重载决策131
7.2.4二元运算符重载决策131
7.2.5候选用户定义运算符131
7.2.6数值提升131
7.2.6.1一元数值提升132
7.2.6.2二元数值提升132
7.2.7提升运算符133
7.3成员查找134
7.3.1基类型135
7.4函数成员135
7.4.1实参列表137
7.4.2类型推断140
7.4.2.1第一阶段140
7.4.2.2第二阶段141
7.4.2.3输入类型141
7.4.2.4输出类型141
7.4.2.5依赖141
7.4.2.6输出类型推断141
7.4.2.7参数类型显式推断141
7.4.2.8精确推断142
7.4.2.9下限推断142
7.4.2.10固定142
7.4.2.11推断返回类型142
7.4.2.12方法组转换的类型推断14
7.4.2.13查找一组表达式的最通用类型
7.4.3重载决策144
7.4.3.1适用函数成员145
7.4.3.2更好的函数成员145
7.4.3.3表达式的更佳转换146
7.4.3.4类型的更佳转换146
7.4.3.5泛型类中的重载147
7.4.4函数成员调用147
7.4.4.1已装箱实例上的调用148
7.5基本表达式149
7.5.1文本149
7.5.2简单名称149
7.5.2.1块中的固定含义151
7.5.3带括号的表达式152
7.5.4成员访问152
7.5.4.1相同的简单名称和类型名称1
7.5.4.2语法多义性154
7.5.5调用表达式155
7.5.5.1方法调用155
7.5.5.2扩展方法调用157
7.5.5.3委托调用159
7.5.6元素访问159
7.5.6.1数组访问159
7.5.6.2索引器访问160
7.5.7this访问160
7.5.8base访问161
7.5.9后缀增量和后缀减量运算符162
7.5.10new运算符162
7.5.10.1对象创建表达式163
7.5.10.2对象初始值设定项164
7.5.10.3集合初始值设定项166
7.5.10.4数组创建表达式167
7.5.10.5委托创建表达式169
7.5.10.6匿名对象创建表达式170
7.5.11typeof运算符172
7.5.12checked和unchecked运算符
7.5.13默认值表达式175
7.5.14匿名方法表达式176
7.6一元运算符176
7.6.1一元加运算符176
7.6.2一元减运算符176
7.6.3逻辑否定运算符177
7.6.4按位求补运算符177
7.6.5前缀增量和减量运算符178
7.6.6强制转换表达式178
7.7算术运算符179
7.7.1乘法运算符179
7.7.2除法运算符180
7.7.3余数运算符181
7.7.4加法运算符182
7.7.5减法运算符184
7.8移位运算符186
7.9关系和类型测试运算符187
7.9.1整数比较运算符187
7.9.2浮点比较运算符188
7.9.3小数比较运算符189
7.9.4布尔相等运算符189
7.9.5枚举比较运算符189
7.9.6引用类型相等运算符189
7.9.7字符串相等运算符191
7.9.8委托相等运算符191
7.9.9相等运算符和null192
7.9.10is运算符192
7.9.11as运算符193
7.10逻辑运算符193
7.10.1整数逻辑运算符194
7.10.2枚举逻辑运算符194
7.10.3布尔逻辑运算符194
7.10.4可以为null的布尔逻辑运算符
7.11条件逻辑运算符195
7.11.1布尔条件逻辑运算符196
7.11.2用户定义的条件逻辑运算符19
7.12空合并运算符196
7.13条件运算符197
7.14匿名函数表达式198
7.14.1匿名函数签名199
7.14.2匿名函数体200
7.14.3重载决策200
7.14.4外层变量201
7.14.4.1捕获的外层变量201
7.14.4.2局部变量实例化202
7.14.5匿名函数表达式的计算204
7.15查询表达式204
7.15.1查询表达式中的多义性205
7.15.2查询表达式转换206
7.15.2.1带有延续部分的select和GroupBy子句
7.15.2.2显式范围变量类型206
7.15.2.3简并查询表达式207
7.15.2.4from、let、where、join和orderby子句
7.15.2.5select子句211
7.15.2.6GroupBy子句21
7.15.2.7透明标识符212
7.15.3查询表达式模式213
7.16赋值运算符214
7.16.1简单赋值215
7.16.2复合赋值217
7.16.3事件赋值217
7.17表达式218
7.18常量表达式218
7.19布尔表达式219
8.语句221
8.1结束点和可到达性221
8.2块223
8.2.1语句列表223
8.3空语句224
8.4标记语句224
8.5声明语句225
8.5.1局部变量声明225
8.5.2局部常量声明226
8.6表达式语句227
8.7选择语句227
8.7.1if语句227
8.7.2switch语句228
8.8迭代语句231
8.8.1while语句232
8.8.2do语句232
8.8.3for语句233
8.8.4foreach语句234
8.9跳转语句236
8.9.1break语句237
8.9.2continue语句238
8.9.3goto语句238
8.9.4return语句239
8.9.5throw语句240
8.10try语句241
8.11checked语句和unchecked语句
8.12lock语句243
8.13using语句244
8.14yield语句246
9.命名空间249
9.1编译单元249
9.2命名空间声明249
9.3Extern别名250
9.4using指令251
9.4.1using别名指令252
9.4.2Using命名空间指令254
9.5命名空间成员256
9.6类型声明256
9.7命名空间别名限定符257
9.7.1别名的唯一性258
10.类259
10.1类声明259
10.1.1类修饰符259
10.1.1.1抽象类260
10.1.1.2密封类260
10.1.1.3静态类260
10.1.2分部修饰符261
10.1.3类型形参261
10.1.4类基本规范262
10.1.4.1基类262
10.1.4.2接口实现264
10.1.5类型形参约束264
10.1.6类体267
10.2分部类型268
10.2.1属性268
10.2.2修饰符268
10.2.3类型形参和约束269
10.2.4基类269
10.2.5基接口269
10.2.6成员270
10.2.7分部方法270
10.2.8名称绑定273
10.3类成员273
10.3.1实例类型274
10.3.2构造类型的成员274
10.3.3继承275
10.3.4new修饰符276
10.3.5访问修饰符276
10.3.6构成类型277
10.3.7静态成员和实例成员277
10.3.8嵌套类型278
10.3.8.1完全限定名278
10.3.8.2已声明可访问性278
10.3.8.3隐藏279
10.3.8.4this访问279
10.3.8.5对包含类型的私有和受保护成员的访问
10.3.8.6泛型类中的嵌套类型281
10.3.9保留成员名称281
10.3.9.1为属性保留的成员名称28
10.3.9.2为事件保留的成员名称28
10.3.9.3为索引器保留的成员名称2
10.3.9.4为析构函数保留的成员名称
10.4常量283
10.5字段284
10.5.1静态字段和实例字段286
10.5.2只读字段286
10.5.2.1对常量使用静态只读字段2
10.5.2.2常量和静态只读字段的版本控制
10.5.3可变字段288
10.5.4字段初始化289
10.5.5变量初始值设定项289
10.5.5.1静态字段初始化290
10.5.5.2实例字段初始化291
10.6方法292
10.6.1方法形参293
10.6.1.1值形参294
10.6.1.2引用形参295
10.6.1.3输出形参296
10.6.1.4形参数组296
10.6.2静态方法和实例方法299
10.6.3虚方法299
10.6.4重写方法301
10.6.5密封方法303
10.6.6抽象方法304
10.6.7外部方法305
10.6.8分部方法305
10.6.9扩展方法305
10.6.10方法体306
10.6.11方法重载307
10.7属性307
10.7.1静态属性和实例属性308
10.7.2访问器308
10.7.3自动实现的属性313
10.7.4可访问性314
10.7.5虚、密封、重写和抽象访问器3
10.8事件316
10.8.1类似字段的事件318
10.8.2事件访问器320
10.8.3静态事件和实例事件321
10.8.4虚、密封、重写和抽象访问器3
10.9索引器322
10.9.1索引器重载325
10.10运算符325
10.10.1一元运算符327
10.10.2二元运算符327
10.10.3转换运算符328
10.11实例构造函数330
10.11.1构造函数初始值设定项331
10.11.2实例变量初始值设定项332
10.11.3构造函数执行332
10.11.4默认构造函数334
10.11.5私有构造函数334
10.11.6可选的实例构造函数形参33
10.12静态构造函数335
10.13析构函数337
10.14迭代器339
10.14.1枚举器接口339
10.14.2可枚举接口339
10.14.3产生类型339
10.14.4枚举器对象339
10.14.4.1MoveNext方法
10.14.4.2Current属性3
10.14.4.3Dispose方法3
10.14.5可枚举对象341
10.14.5.1GetEnumerator方法
10.14.6实现示例342
11.结构349
11.1结构声明349
11.1.1结构修饰符349
11.1.2分部修饰符349
11.1.3结构接口350
11.1.4结构体350
11.2结构成员350
11.3类和结构的区别350
11.3.1值语义352
11.3.2继承352
11.3.3赋值353
11.3.4默认值353
11.3.5装箱和取消装箱353
11.3.6this的含义355
11.3.7字段初始值设定项355
11.3.8构造函数356
11.3.9析构函数356
11.3.10静态构造函数356
11.4结构示例357
11.4.1数据库整数类型357
11.4.2数据库布尔类型358
12.数组361
12.1数组类型361
12.1.1System.Array类型
12.1.2数组和泛型IList接口
12.2数组创建362
12.3数组元素访问363
12.4数组成员363
12.5数组协变363
12.6数组初始值设定项363
13.接口367
13.1接口声明367
13.1.1接口修饰符367
13.1.2分部修饰符367
13.1.3基接口368
13.1.4接口体368
13.2接口成员368
13.2.1接口方法370
13.2.2接口属性370
13.2.3接口事件370
13.2.4接口索引器370
13.2.5接口成员访问370
13.3完全限定接口成员名372
13.4接口实现373
13.4.1显式接口成员实现374
13.4.2所实现接口的唯一性376
13.4.3泛型方法的实现376
13.4.4接口映射377
13.4.5接口实现继承380
13.4.6接口重新实现381
13.4.7抽象类和接口382
14.枚举385
14.1枚举声明385
14.2枚举修饰符385
14.3枚举成员386
14.4System.Enum类型38
14.5枚举值和运算388
15.委托389
15.1委托声明389
15.2委托兼容性391
15.3委托实例化391
15.4委托调用392
16.异常395
16.1导致异常的原因395
16.2System.Exception类
16.3异常的处理方式395
16.4公共异常类396
17.属性397
17.1属性类397
17.1.1属性用法397
17.1.2定位和命名参数398
17.1.3属性参数类型399
17.2属性说明399
17.3属性实例404
17.3.1属性的编译404
17.3.2属性实例的运行时检索405
17.4保留属性405
17.4.1AttributeUsage属性
17.4.2Conditional属性
17.4.2.1条件方法406
17.4.2.2条件属性类408
17.4.3Obsolete属性409
17.5交互操作的属性410
17.5.1与COM和Win32组件的交互操作
17.5.2与其他.NET语言的交互操作
17.5.2.1IndexerName属性
18.不安全代码411
18.1不安全上下文411
18.2指针类型413
18.3固定和可移动变量416
18.4指针转换416
18.4.1指针数组417
18.5表达式中的指针418
18.5.1指针间接寻址419
18.5.2指针成员访问419
18.5.3指针元素访问420
18.5.4address-of运算符
18.5.5指针递增和递减422
18.5.6指针算术运算422
18.5.7指针比较423
18.5.8sizeof运算符423
18.6fixed语句424
18.7固定大小缓冲区427
18.7.1固定大小缓冲区的声明427
18.7.2表达式中的固定大小缓冲区42
18.7.3明确赋值检查429
18.8堆栈分配430
18.9动态内存分配431
A.文档注释433
A.1简介433
A.2建议的标记434
A.2.1435
A.2.2436
A.2.3436
A.2.4436
A.2.5437
A.2.6438
A.2.11440
A.2.12441
A.2.13441
A.2.14441
A.2.15442
A.2.16442
A.2.17442
A.2.18
A.3处理文档文件443
A.3.1ID字符串格式443
A.3.2ID字符串示例445
A.4示例448
A.4.1C#源代码448
A.4.2产生的XML451
B.语法455
B.1词法文法455
B.1.1行结束符455
B.1.2注释455
B.1.3空白456
B.1.4标记456
B.1.5Unicode字符转义序列4
B.1.6标识符456
B.1.7关键字457
B.1.8文本458
B.1.9运算符和标点符号460
B.1.10预处理指令460
B.2句法文法462
B.2.1基本概念462
B.2.2类型462
B.2.3变量464
B.2.4表达式464
B.2.5语句470
B.2.6命名空间474
B.2.7类475
B.2.8结构481
B.2.9数组482
B.2.10接口482
B.2.11枚举483
B.2.12委托484
B.2.13属性484
B.3不安全代码的语法扩展485
C.参考资料489
简介
Helloworld
usingSystem;
classHello{staticvoidMain(){Console.Wri
cschello.cs
Hello,World
程序结构
usingSystem;
namespaceAcme.Collections{publicclassStack
publicvoidPush(objectdata){top=newE
publicobjectPop(){if(top==null)thro
classEntry{publicEntrynext;pub
publicEntry(Entrynext,objectdata){t
csc/t:libraryacme.cs
usingSystem;usingAcme.Collections;
classTest{staticvoidMain(){Stacks=ne
csc/r:acme.dlltest.cs
100101
类型和变量
类别
说明
值类型
简单类型
有符号整型:sbyte、short、int和long
无符号整型:byte、ushort、uint和ulong
Unicode字符型:char
IEEE浮点型:float和double
高精度小数型:decimal
布尔型:bool
枚举类型
enumE{...}形式的用户定义的类型
结构类型
structS{...}形式的用户定义的类型
可以为null的类型
其他所有具有null值的值类型的扩展
引用类型
类类型
其他所有类型的最终基类:object
Unicode字符串型:string
classC{...}形式的用户定义的类型
接口类型
interfaceI{...}形式的用户定义的类型
数组类型
一维和多维数组,例如int[]和int[,]
委托类型
例如,delegateintD(...)形式的用户定义的类型
类别
位数
类型
范围/精度
有符号整型
8
sbyte
–128至127
16
short
–32,768至32,767
32
int
–2,147,483,648至2,147,483,647
64
long
–9,223,372,036,854,775,808至9,223,372,036,854,775
无符号整型
8
byte
0至255
16
ushort
0至65,535
32
uint
0至4,294,967,295
64
ulong
0至18,446,744,073,709,551,615
浮点型
32
float
1.5 × 10−45至3.4 × 1038,7位精度
64
double
5.0 × 10−324至1.7 × 10308,15位精度
小数
128
decimal
1.0 × 10−28至7.9 × 1028,28位精度
usingSystem;
classTest{staticvoidMain(){inti=123;
变量类型
可能的内容
不可以为null的值类型
类型完全相同的值
可以为null的值类型
null值或类型完全相同的值
对象
空引用、对任何引用类型的对象的引用,或者对任何值类型的装箱值的引用
类类型
空引用、对该类类型的实例的引用,或者对从该类类型派生的类的实例的引用
接口类型
空引用、对实现该接口类型的类类型的实例的引用,或者对实现该接口类型的值类型的装箱值的引用
数组类型
空引用、对该数组类型的实例的引用,或者对兼容数组类型的实例的引用
委托类型
空引用或对该委托类型的实例的引用
表达式
类别
表达式
说明
基本
x.m
成员访问
x(...)
方法和委托调用
x[...]
数组和索引器访问
x++
后增量
x--
后减量
newT(...)
对象和委托创建
newT(...){...}
使用初始值设定项创建对象
new{...}
匿名对象初始值设定项
newT[...]
数组创建
typeof(T)
获得T的System.Type对象
checked(x)
在checked上下文中计算表达式
unchecked(x)
在unchecked上下文中计算表达式
default(T)
获取类型T的默认值
delegate{...}
匿名函数(匿名方法)
一元
+x
恒等
-x
求相反数
!x
逻辑求反
~x
按位求反
++x
前增量
--x
前减量
(T)x
将x显式转换为类型T
乘除
x*y
乘法
x/y
除法
x%y
求余
加减
x+y
加法、字符串串联、委托组合
x–y
减法、委托移除
移位
x<
左移
x>>y
右移
关系和类型检测
x
小于
x>y
大于
x<=y
小于或等于
x>=y
大于或等于
xisT
如果x属于T类型,则返回true,否则返回false
xasT
返回转换为类型T的x,如果x不是T则返回null
相等
x==y
等于
x!=y
不等于
逻辑AND
x&y
整型按位AND,布尔逻辑AND
逻辑XOR
x^y
整型按位XOR,布尔逻辑XOR
逻辑OR
x|y
整型按位OR,布尔逻辑OR
条件AND
x&&y
仅当x为true才对y求值
条件OR
x||y
仅当x为false才对y求值
空合并
X??y
如果x为null,则对y求值,否则对x求值
条件
x?y:z
如果x为true,则对y求值,如果x为false,则对z求值
赋值或匿名函数
x=y
赋值
xop=y
复合赋值;支持的运算符有:
*=/=%=+=-=<<=>>=&=^=|=
(Tx)=>y
匿名函数(lambda表达式)
语句
语句
示例
局部变量声明
staticvoidMain(){inta;intb=2,c=3;
局部常量声明
staticvoidMain(){constfloatpi=3.1415927f;
表达式语句
staticvoidMain(){inti;i=123;//Exp
if语句
staticvoidMain(string[]args){if(args.Length
switch语句
staticvoidMain(string[]args){intn=args.Le
while语句
staticvoidMain(string[]args){inti=0;whi
do语句
staticvoidMain(){strings;do{s=C
for语句
staticvoidMain(string[]args){for(inti=0;
foreach语句
staticvoidMain(string[]args){foreach(string
break语句
staticvoidMain(){while(true){string
continue语句
staticvoidMain(string[]args){for(inti=0;
goto语句
staticvoidMain(string[]args){inti=0;got
return语句
staticintAdd(inta,intb){returna+b;}
staticvoidMain(){Console.WriteLine(Add(1,2))
yield语句
staticIEnumerableRange(intfrom,intto){
staticvoidMain(){foreach(intxinRange(-10,
throw和try语句
staticdoubleDivide(doublex,doubley){if(y
staticvoidMain(string[]args){try{if(arg
checked和unchecked语句
staticvoidMain(){inti=int.MaxValue;check
lock语句
classAccount{decimalbalance;
publicvoidWithdraw(decimalamount){lock(th
using语句
staticvoidMain(){using(TextWriterw=File.C
类和对象
publicclassPoint{publicintx,y;
publicPoint(intx,inty){this.x=x;
}
Pointp1=newPoint(0,0);Pointp2=newPoint(1
成员
成员
说明
常量
与类关联的常量值
字段
类的变量
方法
类可执行的计算和操作
属性
与读写类的命名属性相关联的操作
索引器
与以数组方式索引类的实例相关联的操作
事件
可由类生成的通知
运算符
类所支持的转换和表达式运算符
构造函数
初始化类的实例或类本身所需的操作
析构函数
在永久丢弃类的实例之前执行的操作
类型
类所声明的嵌套类型
可访问性
可访问性
含义
public
访问不受限制
protected
访问仅限于此类或从此类派生的类
internal
访问仅限于此程序
protectedinternal
访问仅限于此程序或从此类派生的类
private
访问仅限于此类
类型形参
publicclassPair{publicTFirst
publicTSecondSecond;}
Pairpair=newPair{Fir
基类
publicclassPoint{publicintx,y;
publicPoint(intx,inty){this.x=x;
publicclassPoint3D:Point{publicintz;
publicPoint3D(intx,inty,intz):base(x,y){
Pointa=newPoint(10,20);Pointb=newPoint3D
字段
publicclassColor{publicstaticreadonlyColo
privatebyter,g,b;
publicColor(byter,byteg,byteb){thi
方法
参数
usingSystem;
classTest{staticvoidSwap(refintx,refint
staticvoidMain(){inti=1,j=2;
usingSystem;
classTest{staticvoidDivide(intx,inty,out
staticvoidMain(){intres,rem;
publicclassConsole{publicstaticvoidWrite(s
publicstaticvoidWriteLine(stringfmt,paramso
...}
Console.WriteLine("x={0}y={1}z={2}",x,y,z);
strings="x={0}y={1}z={2}";object[]args=ne
方法体和局部变量
usingSystem;
classSquares{staticvoidMain(){inti=0
while(i<10){j=i*i;Console.Wri
静态方法和实例方法
classEntity{staticintnextSerialNo;
intserialNo;
publicEntity(){serialNo=nextSerialNo++;
publicintGetSerialNo(){returnserialNo;
publicstaticintGetNextSerialNo(){return
publicstaticvoidSetNextSerialNo(intvalue){
usingSystem;
classTest{staticvoidMain(){Entity.SetN
Entitye1=newEntity();Entitye2=newEn
Console.WriteLine(e1.GetSerialNo());//Outp
虚方法、重写方法和抽象方法
usingSystem;usingSystem.Collections;
publicabstractclassExpression{publicabstrac
publicclassConstant:Expression{doublevalue
publicConstant(doublevalue){this.value=
publicoverridedoubleEvaluate(Hashtablevars)
publicclassVariableReference:Expression{str
publicVariableReference(stringname){this.
publicoverridedoubleEvaluate(Hashtablevars)
publicclassOperation:Expression{Expression
publicOperation(Expressionleft,charop,Expre
publicoverridedoubleEvaluate(Hashtablevars)
Expressione=newOperation(newVariableRefere
usingSystem;usingSystem.Collections;
classTest{staticvoidMain(){
Expressione=newOperation(newVariableR
Hashtablevars=newHashtable();
vars["x"]=3;vars["y"]=5;Console.Wri
vars["x"]=1.5;vars["y"]=9;Console.W
方法重载
classTest{staticvoidF(){Console.WriteL
staticvoidF(objectx){Console.WriteLine("
staticvoidF(intx){Console.WriteLine("F(i
staticvoidF(doublex){Console.WriteLine("
staticvoidF(Tx){Console.WriteLine("F<
staticvoidF(doublex,doubley){Console.W
staticvoidMain(){F();//InvokesF()
其他函数成员
publicclassList{
constintdefaultCapacity=4;
常量
T[]items;intcount;
字段
publicList():this(defaultCapacity){}
publicList(intcapacity){items=newT[capac
构造函数
publicintCount{get{returncount;}}
publicintCapacity{get{returnitems.Len
属性
publicTthis[intindex]{get{returnitem
索引器
publicvoidAdd(Titem){if(count==Capacity
protectedvirtualvoidOnChanged(){if(Change
publicoverrideboolEquals(objectother){ret
staticboolEquals(Lista,Listb){if(
方法
publiceventEventHandlerChanged;
事件
publicstaticbooloperator==(Lista,List
publicstaticbooloperator!=(Lista,List
运算符
}
构造函数
Listlist1=newList();List
属性
Listnames=newList();names.Cap
索引器
Listnames=newList();names.Add
事件
usingSystem;
classTest{staticintchangeCount;
staticvoidListChanged(objectsender,EventArgs
staticvoidMain(){Listnames=new
运算符
usingSystem;
classTest{staticvoidMain(){Lista
析构函数
结构
classPoint{publicintx,y;
publicPoint(intx,inty){this.x=x;t
classTest{staticvoidMain(){Point[]poi
structPoint{publicintx,y;
publicPoint(intx,inty){this.x=x;t
Pointa=newPoint(10,10);Pointb=a;a.x=20
数组
usingSystem;
classTest{staticvoidMain(){int[]a=n
int[]a1=newint[10];int[,]a2=newint[10,5]
int[][]a=newint[3][];a[0]=newint[10];a[1]
int[]a=newint[]{1,2,3};
int[]a={1,2,3};
int[]t=newint[3];t[0]=1;t[1]=2;t[2]=3
接口
interfaceIControl{voidPaint();}
interfaceITextBox:IControl{voidSetText(stri
interfaceIListBox:IControl{voidSetItems(str
interfaceIComboBox:ITextBox,IListBox{}
interfaceIDataBound{voidBind(Binderb);}
publicclassEditBox:IControl,IDataBound{pub
publicvoidBind(Binderb){...}}
EditBoxeditBox=newEditBox();IControlcontrol
objectobj=newEditBox();IControlcontrol=(IC
publicclassEditBox:IControl,IDataBound{voi
voidIDataBound.Bind(Binderb){...}}
EditBoxeditBox=newEditBox();editBox.Paint();
枚举
usingSystem;
enumColor{Red,Green,Blue}
classTest{staticvoidPrintColor(Colorcolor)
staticvoidMain(){Colorc=Color.Red;
enumAlignment:sbyte{Left=-1,Center=0,
inti=(int)Color.Blue;//inti=2;Colorc=
Colorc=0;
委托
usingSystem;
delegatedoubleFunction(doublex);
classMultiplier{doublefactor;
publicMultiplier(doublefactor){this.facto
publicdoubleMultiply(doublex){returnx*
classTest{staticdoubleSquare(doublex){
staticdouble[]Apply(double[]a,Functionf){
staticvoidMain(){double[]a={0.0,0.5,
double[]squares=Apply(a,Square);
double[]sines=Apply(a,Math.Sin);
Multiplierm=newMultiplier(2.0);double[]
double[]doubles=Apply(a,(doublex)=>x*
属性
usingSystem;
publicclassHelpAttribute:Attribute{stringu
publicHelpAttribute(stringurl){this.url=
publicstringUrl{get{returnurl;}}
publicstringTopic{get{returntopic;}
[Help("http://msdn.microsoft.com/.../MyClass.htm")
usingSystem;usingSystem.Reflection;
classTest{staticvoidShowHelp(MemberInfomem
staticvoidMain(){ShowHelp(typeof(Widget))
词法结构
程序
转换,这一步将用特定字符指令系统和编码方案编写的文件转换为Unicode字符序列。
词法分析,这一步将Unicode输入字符流转换为标记流。
句法分析,这一步将标记流转换为可执行代码。
文法
文法表示法
while-statement:while(boolean-expression)
statement-list:statementstatement-liststateme
block:{statement-listopt}
block:{}{statement-list}
real-type-suffix:FfDdMm之一
real-type-suffix:FfDdMm
词法文法
句法文法
词法分析
input:input-sectionopt
input-section:input-section-partinput-section
input-section-part:input-elementsoptnew-linep
input-elements:input-elementinput-elementsinp
input-element:whitespacecommenttoken
行结束符
new-line:回车符(U+000D)换行符(U+000A)回车符(U+000D)后
如果源文件的最后一个字符为Control-Z字符(U+001A),则删除此字符。
如果源文件非空并且源文件的最后一个字符不是回车符(U+000D)、换行符(U+000A)、行分隔
注释
comment:single-line-commentdelimited-comment
single-line-comment://input-charactersopt
input-characters:input-characterinput-characters
input-character:除new-line-character之外的任何Unicod
new-line-character:回车符(U+000D)换行符(U+000A)下一行符
delimited-comment:/*delimited-comment-textopt
delimited-comment-text:delimited-comment-section
delimited-comment-section:/asterisksoptnot-sl
asterisks:*asterisks*
not-slash-or-asterisk:除/或*之外的任何Unicode字符
/*Hello,worldprogramThisprogramwrites“he
//Hello,worldprogram//Thisprogramwrites“he
空白
whitespace:任何含Unicode类Zs的字符水平制表符(U+0009)垂直
标记
token:identifierkeywordinteger-literalreal-lit
Unicode字符转义序列
unicode-escape-sequence:\uhex-digithex-digi
classClass1{staticvoidTest(bool\u0066){
classClass1{staticvoidTest(boolf){cha
标识符
identifier:available-identifier@identifier-or
available-identifier:不是keyword的identifier-or-k
identifier-or-keyword:identifier-start-character
identifier-start-character:letter-character_(下划线
identifier-part-characters:identifier-part-charac
identifier-part-character:letter-characterdecima
letter-character:类Lu、Ll、Lt、Lm、Lo或Nl的Unicode
combining-character:类Mn或Mc的Unicode字符表示类Mn
decimal-digit-character:类Nd的Unicode字符表示类Nd
connecting-character:类Pc的Unicode字符表示类Pc的字符
formatting-character:类Cf的Unicode字符表示类Cf的字符
class@class{publicstaticvoid@static(bool@
classClass1{staticvoidM(){cl\u0061ss.s
如果使用了前缀“@”,移除它。
将每个unicode-escape-sequence转换为它的对应Unicode字符。
移除所有formatting-characters。
关键字
keyword:以下关键字之一abstractasbaseboolbr
文本
literal:boolean-literalinteger-literalreal-lite
布尔值
boolean-literal:truefalse
整数
integer-literal:decimal-integer-literalhexadecim
decimal-integer-literal:decimal-digitsinteger-
decimal-digits:decimal-digitdecimal-digitsdec
decimal-digit:0123456789之一
integer-type-suffix:UuLlULUluLul
hexadecimal-integer-literal:0xhex-digitsint
hex-digits:hex-digithex-digitshex-digit
hex-digit:0123456789ABC
如果该整数没有后缀,则它属于以下所列的类型中第一个能够表示其值的那个类型:int、uint、long
如果该整数带有后缀U或u,则它属于以下所列的类型中第一个能够表示其值的那个类型:uint和
如果该整数带有后缀L或l,则它属于以下所列的类型中第一个能够表示其值的那个类型:long和
如果该整数带有后缀UL、Ul、uL、ul、LU、Lu、lU或lu,则它属于ulong类型。
当具有值2147483648(231)且没有integer-type-suffix的一个
当具有值9223372036854775808(263)的一个decimal-intege
实数
real-literal:decimal-digits.decimal-digits
exponent-part:esignoptdecimal-digitsEsi
sign:+-之一
real-type-suffix:FfDdMm之一
以F或f为后缀的实数的类型为float。例如,实数1f、1.5f、1e10f和123
以D或d为后缀的实数的类型为double。例如,实数1d、1.5d、1e10d和12
以M或m为后缀的实数的类型为decimal。例如,实数1m、1.5m、1e10m和1
字符
character-literal:'character'
character:single-charactersimple-escape-sequence
single-character:除'(U+0027)、\(U+005C)和new-li
simple-escape-sequence:\'\"\\\0\a\b
hexadecimal-escape-sequence:\xhex-digithex-
转义序列
字符名称
Unicode编码
\'
单引号
0x0027
\"
双引号
0x0022
\\
反斜杠
0x005C
\0
Null
0x0000
\a
警报
0x0007
\b
BackspaceBackspace
0x0008
\f
换页符
0x000C
\n
换行符
0x000A
\r
回车
0x000D
\t
水平制表符
0x0009
\v
垂直制表符
0x000B
字符串
string-literal:regular-string-literalverbatim-st
regular-string-literal:"regular-string-literal
regular-string-literal-characters:regular-string-
regular-string-literal-character:single-regular-s
single-regular-string-literal-character:除"(U+00
verbatim-string-literal:@"verbatim-string-lit
verbatim-string-literal-characters:verbatim-strin
verbatim-string-literal-character:single-verbatim
single-verbatim-string-literal-character:除"之外的任
quote-escape-sequence:""
stringa="hello,world";//hello,worldst
stringc="hello\tworld";//helloworld
stringe="Joesaid\"Hello\"tome";//Joesai
stringg="\\\\server\\share\\file.txt";//\\ser
stringi="one\r\ntwo\r\nthree";stringj=@"one
classTest{staticvoidMain(){objecta=
null文本
null-literal:null
运算符和标点符号
operator-or-punctuator:{}[]().,
right-shift:>|>
right-shift-assignment:>|>=
预处理指令
pp-directive:pp-declarationpp-conditionalpp-lin
#define和#undef,分别用于定义和取消定义条件编译符号(第
#if、#elif、#else和#endif,用于按条件跳过源代码中的节(第
#line,用于控制行号(在发布错误和警告信息时使用)(第
#error和#warning,分别用于发出错误和警告(第
#region和#endregion,用于显式标记源代码中的节(第
#pragma,用于为编译器指定可选的上下文信息(第
#defineA#undefB
classC{#ifAvoidF(){}#elsevoidG(){}
#ifBvoidH(){}#elsevoidI(){}#endif}
classC{voidF(){}voidI(){}}
条件编译符号
conditional-symbol:除true或false外的任何identifier
预处理表达式
pp-expression:whitespaceoptpp-or-expression
pp-or-expression:pp-and-expressionpp-or-expressi
pp-and-expression:pp-equality-expressionpp-and-e
pp-equality-expression:pp-unary-expressionpp-equ
pp-unary-expression:pp-primary-expression!whi
pp-primary-expression:truefalseconditional-symb
声明指令
pp-declaration:whitespaceopt#whitespaceopt
pp-new-line:whitespaceoptsingle-line-commentop
#defineEnterprise
#ifProfessional||Enterprise#defineAdvanced
namespaceMegacorp.Data{#ifAdvancedclassP
#defineAnamespaceN{#defineB#ifBclas
#defineA#defineA
#defineA#undefA#undefA
条件编译指令
pp-conditional:pp-if-sectionpp-elif-sectionso
pp-if-section:whitespaceopt#whitespaceopt
pp-elif-sections:pp-elif-sectionpp-elif-sections
pp-elif-section:whitespaceopt#whitespaceopt
pp-else-section:whitespaceopt#whitespaceopt
pp-endif:whitespaceopt#whitespaceoptendi
conditional-section:input-sectionskipped-section
skipped-section:skipped-section-partskipped-sect
skipped-section-part:skipped-charactersoptnew-
skipped-characters:whitespaceoptnot-number-sig
not-number-sign:除#外的任何input-character
按顺序计算#if和#elif指令的pp-expressions,直到得出true值。如
如果所有pp-expressions的结果都为false并且存在#else指令,则选择
否则不选择任何conditional-section。
#defineDebug//Debuggingon#undefTrace//Tr
classPurchaseTransaction{voidCommit(){#
#defineDebug//Debuggingon
classPurchaseTransaction{voidCommit(){#
classHello{staticvoidMain(){System.Con
hello,#ifDebugworld#elseNebraska#endif
#ifX/*#else/**/classQ{}#endif
诊断指令
pp-diagnostic:whitespaceopt#whitespaceopt
pp-message:new-linewhitespaceinput-characters
#warningCodereviewneededbeforecheck-in
#ifDebug&&Retail#errorAbuildcan'tbeboth
classTest{...}
区域指令
pp-region:pp-start-regionconditional-sectionop
pp-start-region:whitespaceopt#whitespaceopt
pp-end-region:whitespaceopt#whitespaceopt
#region...#endregion
#iftrue...#endif
行指令
pp-line:whitespaceopt#whitespaceoptline
line-indicator:decimal-digitswhitespacefile
file-name:"file-name-characters"
file-name-characters:file-name-characterfile-nam
file-name-character:除"之外的任何input-character
Pragma指令
pp-pragma:whitespaceopt#whitespaceoptpr
pragma-body:pragma-warning-body
Pragmawarning
pragma-warning-body:warningwhitespacewarnin
warning-action:disablerestore
warning-list:decimal-digitswarning-listwhites
usingSystem;
classProgram{[Obsolete]staticvoidFoo(){
staticvoidMain(){#pragmawarningdisable612
基本概念
应用程序启动
staticvoidMain(){...}
staticvoidMain(string[]args){...}
staticintMain(){...}
staticintMain(string[]args){...}
应用程序终止
声明
在程序的所有源文件中,namespace-member-declarations若没有被置于任何一
在程序的所有源文件中,一个namespace-member-declarations若在nam
每个类、结构或接口声明创建一个新的声明空间。新的声明空间名称是通过class-member-dec
每个委托声明创建一个新的声明空间。名称通过形参(fixed-parameters和paramet
每个枚举声明创建一个新的声明空间。名称通过enum-member-declarations引入此
每个方法声明、索引器声明、运算符声明、实例构造函数声明和匿名函数均创建一个名为localvari
每个block或switch-block以及for、foreach和using语句都
每个block或switch-block都为标签创建一个单独的声明空间。名称通过label
字段声明和局部变量声明的声明顺序确定其初始值设定项(如果有)的执行顺序。
在使用局部变量前必须先定义它们(第
当省略constant-expression值时,枚举成员声明(第
namespaceMegacorp.Data{classCustomer{
namespaceMegacorp.Data{classOrder{...
classA{voidF(){inti=0;if(true)
voidG(){if(true){inti=0;}
voidH(){if(true){inti=0;}
voidI(){for(inti=0;i<10;i++)H
成员
命名空间成员
结构成员
sbyte的成员是System.SByte结构的成员。
byte的成员是System.Byte结构的成员。
short的成员是System.Int16结构的成员。
ushort的成员是System.UInt16结构的成员。
int的成员是System.Int32结构的成员。
uint的成员是System.UInt32结构的成员。
long的成员是System.Int64结构的成员。
ulong的成员是System.UInt64结构的成员。
char的成员是System.Char结构的成员。
float的成员是System.Single结构的成员。
double的成员是System.Double结构的成员。
decimal的成员是System.Decimal结构的成员。
bool的成员是System.Boolean结构的成员。
枚举成员
类成员
object的成员是System.Object类的成员。
string的成员是System.String类的成员。
接口成员
数组成员
委托成员
成员访问
已声明可访问性
public,选择它的方法是在成员声明中包括public修饰符。public的直观含义是“访问
protected,选择它的方法是在成员声明中包括protected修饰符。protected
internal,选择它的方法是在成员声明中包括internal修饰符。internal的直观
protectedinternal(意为受保护或内部的),选择它的方法是在成员声明中包括prot
private,选择它的方法是在成员声明中包括private修饰符。private的直观含义是
命名空间隐式地具有public已声明可访问性。在命名空间声明中不允许使用访问修饰符。
编译单元或命名空间中声明的类型可以具有public或internal已声明可访问性,默认的已
类成员可具有五种已声明可访问性中的任何一种,默认为private已声明可访问性。(请注意,声明为
结构成员可以具有public、internal或private已声明可访问性并默认为pri
接口成员隐式地具有public已声明可访问性。在接口成员声明中不允许使用访问修饰符。
枚举成员隐式地具有public已声明可访问性。在枚举成员声明中不允许使用访问修饰符。
可访问域
如果T的已声明可访问性为public,则T的可访问域是P的以及引用P的任何程序的程
如果T的已声明可访问性为internal,则T的可访问域是P的程序文本。
如果M的已声明可访问性为public,则M的可访问域是T的可访问域。
如果M的已声明可访问性是protectedinternal,则设D表示P的程序文本和
如果M的已声明可访问性是protected,则设D表示T的程序文本和从T派生的任何
如果M的已声明可访问性为internal,则M的可访问域是T的可访问域与P的程序文
如果M的已声明可访问性为private,则M的可访问域是T的程序文本。
首先,如果M是在某个类型(相对于编译单元或命名空间)内声明的,则当该类型不可访问时将会发生编译时
然后,如果M为public,则允许进行访问。
否则,如果M为protectedinternal,则当访问发生在声明了M的程序中,或发生
否则,如果M为protected,则当访问发生在声明了M的类中,或发生在从声明M的类派
否则,如果M为internal,则当访问发生在声明了M的程序中时允许进行访问。
否则,如果M为private,则当访问发生在声明了M的类型中时允许进行访问。
否则,类型或成员不可访问,并发生编译时错误。
publicclassA{publicstaticintX;internal
internalclassB{publicstaticintX;intern
publicclassC{publicstaticintX;in
privateclassD{publicstaticintX;i
A和A.X的可访问域无限制。
A.Y、B、B.X、B.Y、B.C、B.C.X和B.C.Y的可访问域是包含程序的程序文本。
A.Z的可访问域是A的程序文本。
B.Z和B.D的可访问域是B的程序文本,包括B.C和B.D的程序文本。
B.C.Z的可访问域是B.C的程序文本。
B.D.X和B.D.Y的可访问域是B的程序文本,包括B.C和B.D的程序文本。
B.D.Z的可访问域是B.D的程序文本。
classA{intx;
staticvoidF(Bb){b.x=1;//Ok}}
classB:A{staticvoidF(Bb){b.x=1;/
实例成员的受保护访问
M形式的非限定type-name或primary-expression。
E.M形式的primary-expression,假定E的类型是T或从T派生的类,其
base.M形式的primary-expression。
publicclassA{protectedintx;
staticvoidF(Aa,Bb){a.x=1;//Ok
publicclassB:A{staticvoidF(Aa,Bb){
classC{protectedTx;}
classD:C{staticvoidF(){Ddt
可访问性约束
类类型的直接基类必须至少与类类型本身具有同样的可访问性。
接口类型的显式基接口必须至少与接口类型本身具有同样的可访问性。
委托类型的返回类型和参数类型必须至少与委托类型本身具有同样的可访问性。
常量的类型必须至少与常量本身具有同样的可访问性。
字段的类型必须至少与字段本身具有同样的可访问性。
方法的返回类型和参数类型必须至少与方法本身具有同样的可访问性。
属性的类型必须至少与属性本身具有同样的可访问性。
事件的类型必须至少与事件本身具有同样的可访问性。
索引器的类型和参数类型必须至少与索引器本身具有同样的可访问性。
运算符的返回类型和参数类型必须至少与运算符本身具有同样的可访问性。
实例构造函数的参数类型必须至少与实例构造函数本身具有同样的可访问性。
classA{...}
publicclassB:A{...}
classA{...}
publicclassB{AF(){...}
internalAG(){...}
publicAH(){...}}
签名和重载
方法签名由方法的名称、类型形参的个数和它的每一个形参(按从左到右的顺序)的类型和种类(值、引用或输出
实例构造函数签名由它的每一个形参(按从左到右的顺序)的类型和种类(值、引用或输出)组成。具体而言,实
索引器签名由它的每一个形参(按从左到右的顺序)的类型组成。需注意的是,索引器签名既不包含元素类型,也
运算符签名由运算符的名称和它的每一个形参(按从左到右的顺序)的类型组成。具体而言,运算符的签名不包含
方法重载允许类、结构或接口用同一个名称声明多个方法,条件是它们的签名在该类、结构或接口中是唯一的。
实例构造函数重载允许类或结构声明多个实例构造函数,条件是它们的签名在该类或结构中是唯一的。
索引器重载允许类、结构或接口声明多个索引器,条件是它们的签名在该类、结构或接口中是唯一的。
运算符重载允许类或结构用同一名称声明多个运算符,条件是它们的签名在该类或结构中是唯一的。
interfaceITest{voidF();//F()
voidF(intx);//F(int)
voidF(refintx);//F(refint)
voidF(outintx);//F(outint)error
voidF(intx,inty);//F(int,int)
intF(strings);//F(string)
intF(intx);//F(int)error
voidF(string[]a);//F(string[])
voidF(paramsstring[]a);//F(string[])erro
范围
由namespace-member-declaration(第
namespace-declaration中namespace-member-declarati
由extern-alias-directive定义的名称的范围扩展到直接包含它的编译单元或命名空
由using-directive(第
由class-declaration(第
由struct-declaration(第
由interface-declaration(第
由delegate-declaration(第
由class-member-declaration(第
由struct-member-declaration(第
由enum-member-declaration(第
在method-declaration(第
在indexer-declaration(第
在operator-declaration(第
在constructor-declaration(第
在lambda-expression中声明的参数范围是该lambda-expression的
在anonymous-method-expression中声明的参数范围为该anonymous
在labeled-statement(第
在local-variable-declaration(第
在switch语句(第
在for语句(第
在local-constant-declaration(第
作为foreach-statement、using-statement、lock-statemen
classA{voidF(){i=1;}
inti=0;}
classA{inti=0;
voidF(){i=1;//Error,useprecedes
voidG(){intj=(j=1);//Valid}
voidH(){inta=1,b=++a;//Valid}}
usingSystem;
classA{}
classTest{staticvoidMain(){stringA=
Typet=typeof(A);//typecontext
Console.WriteLine(s);//writes"hello,wor
名称隐藏
通过嵌套隐藏
classA{inti=0;
voidF(){inti=1;}
voidG(){i=1;}}
classOuter{staticvoidF(inti){}
staticvoidF(strings){}
classInner{voidG(){F(1);//In
staticvoidF(longl){}}}
通过继承隐藏
类或结构中引入的常量、字段、属性、事件或类型会把所有同名的基类成员隐藏起来。
类或结构中引入的方法隐藏所有同名的非方法基类成员,以及所有具有相同签名(方法名称和参数个数、修饰符和
类或结构中引入的索引器隐藏所有具有相同签名(参数个数和类型)的基类索引器。
classBase{publicvoidF(){}}
classDerived:Base{publicvoidF(){}//War
classBase{publicvoidF(){}}
classDerived:Base{newpublicvoidF(){}}
classBase{publicstaticvoidF(){}}
classDerived:Base{newprivatestaticvoidF(
classMoreDerived:Derived{staticvoidG(){F
命名空间和类型名称
namespace-name:namespace-or-type-name
type-name:namespace-or-type-name
namespace-or-type-name:identifiertype-argument
I
N.I
如果namespace-or-type-name的形式为I或I: 如果K为零,namespace-or-type-name出现在泛型方法声明中(第
否则,如果namespace-or-type-name出现在类型声明中,则对于每个实例类型T(
如果K为零,并且T的声明包含名为I的类型参数,则namespace-or-type-n
否则,如果namespace-or-type-name出现在该类型声明的体中,且T或其任一基
如果当时前面的步骤不成功,则对于每个命名空间N,从出现namespace-or-type-nam
如果K为零,并且I为 N中的命名空间的名称,则:
如果出现namespace-or-type-name的位置包含在N的命名空间声明中,并且该命
否则,namespace-or-type-name引用N中名为I的命名空间。
否则,如果N包含一个具有名称 I且有K 个类型形参的可访问类型,则:
如果K为零,并且出现namespace-or-type-name的位置包含在N的命名空间
否则,namespace-or-type-name引用利用给定类型实参构造的该类型。
否则,如果出现namespace-or-type-name的位置包含在N的命名空间声明中:
如果K为零,并且该命名空间声明包含一个将名称I与一个导入的命名空间或类型关联的extern
否则,如果该命名空间声明的using-namespace-directives导入的命名空间恰好
否则,如果该命名空间声明的using-namespace-directives导入的命名空间包含
否则,namespace-or-type-name未定义,并将导致发生编译时错误。
否则,namespace-or-type-name的形式为N.I或N.I 如果K为零,N引用一个命名空间,并且N包含名为I的嵌套命名空间,则namespace
否则,如果N引用一个命名空间,并且N包含一个具有名称 I且有K 个类型形参的可访问类型,
否则,如果N引用一个(可能是构造的)类或结构类型,并且N或其任一基类包含一个具有名称I且
否则,N.I是无效的namespace-or-type-name并将发生编译时错误。
namespace-or-type-name是T.I形式的namespace-or-type
namespace-or-type-name是typeof(T)形式的typeof-expr
完全限定名
如果N是全局命名空间的成员,则它的完全限定名为N。
否则,它的完全限定名为S.N,其中S是声明了N的命名空间或类型的完全限定名。
classA{}//A
namespaceX//X{classB//X.B{c
namespaceY//X.Y{classD{}//X.Y.D
namespaceX.Y//X.Y{classE{}//X.Y.E}
自动内存管理
当创建对象时,为其分配内存,运行构造函数,将该对象视为活对象。
在后续执行过程中,如果不会再访问该对象或它的任何部分(除了运行它的析构函数),则将该对象视为不再使用
一旦对象符合销毁条件,在稍后某个时间将运行该对象的析构函数(第
一旦运行对象的析构函数,如果该对象或它的任何部分无法由任何可能的执行继续(包括运行析构函数)访问,则
最后,在对象变得符合回收条件后,垃圾回收器将释放与该对象关联的内存。
usingSystem;
classA{~A(){Console.WriteLine("Destruct
classB{objectRef;
publicB(objecto){Ref=o;}
~B(){Console.WriteLine("Destructinstanceo
classTest{staticvoidMain(){Bb=newB
DestructinstanceofADestructinstanceofB
DestructinstanceofBDestructinstanceofA
usingSystem;
classA{~A(){Console.WriteLine("Destruct
publicvoidF(){Console.WriteLine("A.F");
classB{publicARef;
~B(){Console.WriteLine("Destructinstanceo
classTest{publicstaticARefA;publicstat
staticvoidMain(){RefB=newB();RefA
//AandBnoweligiblefordestructionGC.C
//Bnoweligibleforcollection,butAisnot
DestructinstanceofADestructinstanceofBA.F
执行顺序
在执行线程中需保持数据依赖性。就是说,在计算每个变量的值时,就好像线程中的所有语句都是按原始程序顺序
保留初始化的排序规则(第
对于不稳定读写(第
类型
type:value-typereference-typetype-parameter
值类型
value-type:struct-typeenum-type
struct-type:type-namesimple-typenullable-type
simple-type:numeric-typebool
numeric-type:integral-typefloating-point-typede
integral-type:sbytebyteshortushortintuintlo
floating-point-type:floatdouble
nullable-type:non-nullable-value-type?
non-nullable-value-type:type
enum-type:type-name
System.ValueType类型
默认构造函数
对于所有simple-types,默认值是将其所有位都置零的位模式所产生的值:
对于sbyte、byte、short、ushort、int、uint、long和ulong,默
对于char,默认值为'\x0000'。
对于float,默认值为0.0f。
对于double,默认值为0.0d。
对于decimal,默认值为0.0m。
对于bool,默认值为false。
对于enum-typeE,默认值为0,该值被转换为类型E。
对于struct-type,默认值是通过将所有值类型字段设置为它们的默认值并将所有引用类型字段设置
对于nullable-type,默认值是一个其HasValue属性为false且Valu
classA{voidF(){inti=0;intj=ne
结构类型
简单类型
保留字
化名的类型
sbyte
System.SByte
byte
System.Byte
short
System.Int16
ushort
System.UInt16
int
System.Int32
uint
System.UInt32
long
System.Int64
ulong
System.UInt64
char
System.Char
float
System.Single
double
System.Double
bool
System.Boolean
decimal
System.Decimal
inti=int.MaxValue;//System.Int32.MaxValuec
大多数简单类型允许通过编写literals(第
当表达式的操作数都是简单类型常量时,编译器可以在编译时计算表达式。这样的表达式称为constant
通过const声明可以声明简单类型(第
涉及简单类型的转换可以参与由其他结构类型定义的转换运算符的计算,但用户定义的转换运算符永远不能参与其
整型
sbyte类型表示有符号8位整数,其值介于-128和127之间。
byte类型表示无符号8位整数,其值介于0和255之间。
short类型表示有符号16位整数,其值介于-32768和32767之间。
ushort类型表示无符号16位整数,其值介于0和65535之间。
int类型表示有符号32位整数,其值介于-2147483648和2147483647之
uint类型表示无符号32位整数,其值介于0和4294967295之间。
long类型表示有符号64位整数,其值介于–9223372036854775808和92
ulong类型表示无符号64位整数,其值介于0和18446744073709551615
char类型表示无符号16位整数,其值介于0和65535之间。char类型的可能值集
对于一元运算符+和~,操作数转换为T类型,其中T是int、uint、long和u
对于一元运算符–,操作数转换为类型T,其中T是int和long中第一个可以完全表示操
对于+、–、*、/、%、&、^、|、==、!=、>、<、>=和<=二元运算符,操作数转换为类
对于二元运算符<<和>>,左操作数转换为T类型,其中T是int、uint、long
不存在从其他类型到char类型的隐式转换。具体而言,即使sbyte、byte和ushort
char类型的常量必须写成character-literals或带有强制转换为类型char
浮点型
正零和负零。大多数情况下,正零和负零的行为与简单的值零相同,但某些运算会区别对待此两种零(第
正无穷大和负无穷大。无穷大是由非零数字被零除这样的运算产生的。例如,1.0/0.0产生正无穷大
非数字(Not-a-Number)值,常缩写为NaN。NaN是由无效的浮点运算(如零被零除)
以s × m × 2e形式表示的非零值的有限集,其中s为1或−1,m和e由特殊的
如果一个操作数为整型,则该操作数转换为与另一个操作数的类型相同的浮点型。
然后,如果任一操作数的类型为double,则另一个操作数转换为double。至少用double
否则,至少用float范围和精度执行运算,结果的类型为float(对于关系运算符则为bool
如果浮点运算的结果对于目标格式太小,则运算结果变成正零或负零。
如果浮点运算的结果对于目标格式太大,则运算结果变成正无穷大或负无穷大。
如果浮点运算无效,则运算的结果变成NaN。
如果浮点运算的一个或两个操作数为NaN,则运算的结果变成NaN。
decimal类型
bool类型
枚举类型
可以为null的类型
类型为bool的HasValue属性
类型为T的Value属性
newT?(x)
引用类型
reference-type:class-typeinterface-typearray-ty
class-type:type-nameobjectstring
interface-type:type-name
array-type:non-array-typerank-specifiers
non-array-type:type
rank-specifiers:rank-specifierrank-specifiers
rank-specifier:[dim-separatorsopt]
dim-separators:,dim-separators,
delegate-type:type-name
类类型
类类型
说明
System.Object
所有其他类型的最终基类。请参见第
System.String
C#语言的字符串类型。请参见第
System.ValueType
所有值类型的基类。请参见第
System.Enum
所有枚举类型的基类。请参见第
System.Array
所有数组类型的基类。请参见第
System.Delegate
所有委托类型的基类。请参见第
System.Exception
所有异常类型的基类。请参见第
对象类型
string类型
接口类型
数组类型
委托类型
装箱和拆箱
装箱转换
从任何value-type到object类型。
从任何value-type到System.ValueType类型。
从任何non-nullable-value-type到value-type实现的任何int
从任何nullable-type到由nullable-type的基础类型实现的任何inte
从任何enum-type到System.Enum类型。
从任何具有基础enum-type的nullable-type到System.Enum类型
sealedclassBox:System.ValueType{Tvalue;
publicBox(Tt){value=t;}}
inti=123;objectbox=i;
inti=123;objectbox=newBox(i);
inti=123;objectbox=i;if(boxisint){C
structPoint{publicintx,y;
publicPoint(intx,inty){this.x=x;t
Pointp=newPoint(10,10);objectbox=p;p.x=
拆箱转换
从object类型到任何value-type。
从System.ValueType类型到任何value-type。
从任何interface-type到实现了该interface-type的任何non-nu
从任何interface-type到其基础类型实现了该interface-type的任何n
从System.Enum类型到任何enum-type。
从System.Enum类型到任何具有基础enum-type的nullable-type。
objectbox=123;inti=(int)box;
objectbox=newBox(123);inti=((Box
构造类型
namespaceWidgets{classQueue{...}classQu
namespaceMyApplication{usingWidgets;
classX{Queueq1;//Non-genericWidget
classOuter{publicclassInner{...}
publicInneri;//TypeofiisOuter.Inne
类型实参
type-argument-list:
type-arguments:type-argumenttype-arguments,
type-argument:type
开放和封闭类型
类型形参定义开放类型。
当且仅当数组元素类型是开放类型时,该数组类型才是开放类型。
当且仅当构造类型的一个或多个类型实参为开放类型时,该构造类型才是开放类型。当且仅当构造的嵌套类型的一
绑定和未绑定类型
满足约束
如果约束为类类型、接口类型或类型形参,则假设C表示该约束,并用所提供的类型实参替换出现在该约束中
标识转换(第6.1.1节)
隐式引用转换(第
装箱转换(第
从类型形参A到C的隐式引用、装箱或类型形参转换。
如果约束为引用类型约束(class),则类型A必须满足下列条件之一:
A为接口类型、类类型、委托类型或数组类型。注意,System.ValueType和System
A是已知为引用类型的类型形参(第
如果约束为值类型约束(struct),则类型A必须满足下列条件之一:
A为结构类型或枚举类型,但不是可以为null的类型。注意,System.ValueType和
A为具有值类型约束的类型形参(第
如果约束为构造函数约束new(),则类型A一定不能为abstract,并且必须具有公共无参数
A为值类型,因为所有值类型都具有公共默认构造函数(第4.1.2节)。
A为具有构造函数约束的类型形参(第
A为具有值类型约束的类型形参(第
A是不为abstract并且包含显式声明的无参数public构造函数的类。
A不为abstract,并且具有默认构造函数(第
classBwhereT:IEnumerable{...}
classD:BwhereT:IEnumerable{...}
classE:B>{...}
类型形参
type-parameter:identifier
不能直接使用类型形参声明基类(第
类型形参上的成员查找规则取决于应用到该类型形参的约束(如果有)。这将在第
类型形参的可用转换取决于应用到该类型形参的约束(如果有)。这将在第
如果事先不知道由类型形参给出的类型是引用类型(第
仅当类型形参受constructor-constraint或值类型约束(第
不能在属性中的任何位置上使用类型形参。
不能在成员访问(第
在不安全代码中,类型形参不能用作unmanaged-type(第18.2节)。
表达式目录树类型
Funcdel=x=>x+1;//Code
Expression>exp=x=>x+1;//Da
Funcdel2=exp.Compile();
inti1=del(1);
inti2=del2(1);
变量
变量类别
classA{publicstaticintx;inty;
voidF(int[]v,inta,refintb,outintc){
静态变量
实例变量
类中的实例变量
结构中的实例变量
数组元素
值参数
引用形参
变量在可以作为引用形参在函数成员或委托调用中传递之前,必须已明确赋值(第
在函数成员或匿名函数内部,引用形参被视为初始已赋值。
输出形参
变量在可以作为输出形参在函数成员或委托调用中传递之前无需明确赋值。
在正常完成函数成员或委托调用之后,每个作为输出形参传递的变量都被认为在该执行路径中已赋值。
在函数成员或匿名函数内部,输出形参被视为初始未赋值。
函数成员或匿名函数的每个输出形参在该函数成员或匿名函数正常返回前都必须已明确赋值(第
局部变量
默认值
静态变量。
类实例的实例变量。
数组元素。
对于value-type的变量,默认值与该value-type的默认构造函数(第
对于reference-type的变量,默认值为null。
明确赋值
初始已赋值的变量(第
如果所有可能通向给定位置的执行路径都至少包含以下内容之一,则初始未赋值的变量(第
将变量作为左操作数的简单赋值(第
将变量作为输出形参传递的调用表达式(第
对于局部变量,包含变量初始值设定项的局部变量声明(第
如果一个实例变量的包含它的那个struct-type变量被视为已明确赋值,则该实例变量被视为已明
如果一个struct-type变量的每个实例变量都被视为已明确赋值,则该结构类型变量被视为已明确
变量必须在获取其值的每个位置都已明确赋值。这确保了从来不会出现未定义的值。变量在表达式中出现被视为要
该变量为简单赋值的左操作数,
该变量作为输出形参传递,或者
该变量为struct-type变量并作为成员访问的左操作数出现。
变量必须在它作为引用形参传递的每个位置都已明确赋值。这确保了被调用的函数成员可以将引用形参视为初始已
函数成员的所有输出形参必须在函数成员返回的每个位置都已明确赋值,返回位置包括通过return语句
struct-type实例构造函数的this变量必须在该实例构造函数返回的每个位置明确赋值。
初始已赋值变量
静态变量。
类实例的实例变量。
初始已赋值结构变量的实例变量。
数组元素。
值形参。
引用形参。
在catch子句或foreach语句中声明的变量。
初始未赋值变量
初始未赋值结构变量的实例变量。
输出形参,包括结构实例构造函数的this变量。
局部变量,在catch子句或foreach语句中声明的那些除外。
确定明确赋值的细则
在每个语句的开头处
在每个语句的结束点(第
在每个将控制转移到另一个语句或语句结束点的arc上
在每个表达式的开头处
在每个表达式的结尾处
明确赋值。这表明在能达到该点的所有可能的控制流上,v都已赋值。
未明确赋值。当在bool类型表达式结尾处确定变量的状态时,未明确赋值的变量的状态可能(但不一定)
在true表达式后明确赋值。此状态表明如果该布尔表达式计算为true,则v是明确赋值的,但
在false表达式后明确赋值。此状态表明如果该布尔表达式计算为false,则v是明确赋值的
一般语句规则
v在函数成员体的开头处不是明确赋值的。
v在任何无法访问的语句的开头处都是明确赋值的。
在任何其他语句开头处,为了确定v的明确赋值状态,请检查以该语句开头处为目标的所有控制流转移上的
在block、checked、unchecked、if、while、do、for、foreach、
块语句、checked和unchecked语句
表达式语句
v在expr的开头处与在stmt的开头处具有相同的明确赋值状态。
如果v在expr的结尾处明确赋值,则它在stmt的结束点也明确赋值;否则,它在stmt
声明语句
如果stmt是不带有初始值设定项的声明语句,则v在stmt的结束点与在stmt的开头
如果stmt是带有初始值设定项的声明语句,则确定v的明确赋值状态时可把stmt当作一个语
if语句
if(expr)then-stmtelseelse-stmt
v在expr的开头处与在stmt的开头处具有相同的明确赋值状态。
如果v在expr的结尾处明确赋值,则它在指向then-stmt和else-stmt或
如果v在expr的结尾处具有“在true表达式后明确赋值”状态,则它在指向then-s
如果v在expr的结尾处具有“在false表达式后明确赋值”状态,则它在指向else-
否则,认为v在指向then-stmt或else-stmt,或指向stmt的结束点(如果
switch语句
位于expr开头处的v的明确赋值状态与位于stmt开头处的v的状态相同。
在指向可访问的switch块语句列表的控制流转移上,v的明确赋值状态就是它在expr结尾处
while语句
while(expr)while-body
v在expr的开头处与在stmt的开头处具有相同的明确赋值状态。
如果v在expr的结尾处明确赋值,则它在指向while-body和指向stmt结束点
如果v在expr的结尾处具有“在true表达式后明确赋值”状态,则它在指向while-
如果v在expr的结尾处具有“在false表达式后明确赋值”状态,则它在指向stmt
do语句
dodo-bodywhile(expr);
v在从stmt的开头处到do-body的控制流转移上的明确赋值状态与在stmt的开头处
v在expr的开头处与在do-body的结束点具有相同的明确赋值状态。
如果v在expr的结尾处是明确赋值的,则它在指向stmt的结束点的控制流转移上是明确赋值
如果v在expr的结尾处的状态为“在false表达式后明确赋值”,则它在指向stmt
for语句
for(for-initializer;for-condition;for-iterat
{for-initializer;while(for-condition){
break、continue和goto语句
throw语句
throwexpr;
return语句
returnexpr;
位于expr开头处的v的明确赋值状态与位于stmt开头处的v的明确赋值状态相同。
如果v是输出形参,则它必须在下列两个位置之一被明确赋值:
在expr之后
在包含return语句的try-finally或try-catch-finally的f
return;
如果v是输出形参,则它必须在下列两个位置之一被明确赋值:
在stmt之前
在包含return语句的try-finally或try-catch-finally的f
try-catch语句
trytry-blockcatch(...)catch-block-1...catch(.
位于try-block开头处的v的明确赋值状态与位于stmt开头处的v的明确赋值状态
位于catch-block-i(对于所有的i)开头处的v的明确赋值状态与位于stmt开头
当且仅当v在try-block和每个catch-block-i(每个i从1到n)
try-finally语句
trytry-blockfinallyfinally-block
位于try-block开头处的v的明确赋值状态与位于stmt开头处的v的明确赋值状态
位于finally-block开头处的v的明确赋值状态与位于stmt开头处的v的明确
当且仅当下列条件中至少有一个为真时,位于stmt结束点处的v的明确赋值状态才是明确赋值的:
v在try-block的结束点明确赋值
v在finally-block的结束点明确赋值
try-catch-finally语句
trytry-blockcatch(...)catch-block-1...catch(
try{trytry-blockcatch(...)catch-block-1
classA{staticvoidF(){inti,j;try
catch{//neitherinorjdefinitelyassig
finally{//neitherinorjdefinitelyass
foreach语句
foreach(typeidentifierinexpr)embedded-state
位于expr开头处的v的明确赋值状态与位于stmt开头处的v的状态相同。
在指向embedded-statement或指向stmt结束点处的控制流转移上,v的明确赋
using语句
using(resource-acquisition)embedded-statement
位于resource-acquisition开头处的v的明确赋值状态与位于stmt开头处
在指向embedded-statement的控制流转移上,v的明确赋值状态与位于resour
lock语句
lock(expr)embedded-statement
位于expr开头处的v的明确赋值状态与位于stmt开头处的v的状态相同。
在指向embedded-statement的控制流转移上,v的明确赋值状态与位于expr结
yield语句
yieldreturnexpr;
位于expr开头处的v的明确赋值状态与位于stmt开头处的v的状态相同。
位于stmt结尾处的v的明确赋值状态与位于expr结尾处的v的状态相同。
简单表达式的一般规则
位于此类表达式结尾处的v的明确赋值状态与位于表达式开头处的v的明确赋值状态相同。
带有嵌入表达式的表达式的一般规则
位于expr1开头处的v的明确赋值状态与位于expr开头处的v的明确赋值状态相同。
位于expri(i大于1)开头处的v的明确赋值状态与位于expri-1结尾处的v的
位于expr结尾处的v的明确赋值状态与位于exprn结尾处的v的明确赋值状态相同。
调用表达式和对象创建表达式
primary-expression(arg1,arg2,…,argn)
newtype(arg1,arg2,…,argn)
对于调用表达式,位于primary-expression之前的v的明确赋值状态与位于exp
对于调用表达式,位于arg1之前的v的明确赋值状态与位于primary-expressio
对于对象创建表达式,位于arg1之前的v的明确赋值状态与位于expr之前的v的状态相
对于每一个参数argi,位于argi之后的v的明确赋值状态由标准表达式规则决定,其中忽略所
对于每一个i大于1的参数argi,位于argi之前的v的明确赋值状态与位于arg
如果变量v是被作为out参数传递(即,形式为“outv”的参数),则无论将它用作哪一个a
对于数组初始值设定项(第
简单赋值表达式
位于expr-rhs之前的v的明确赋值状态与位于expr之前的v的明确赋值状态相同。
如果w与v是同一变量,则位于expr之后的v的明确赋值状态是明确赋值的。否则,位于
&&表达式
位于expr-first之前的v的明确赋值状态与位于expr之前的v的明确赋值状态相
如果位于expr-first之后的v的状态是明确赋值的或为“在true表达式后明确赋值”
位于expr之后的v的明确赋值状态取决于:
如果在expr-first之后,v的状态是明确赋值的,则在expr之后的v的状态也是明
否则,如果位于expr-second之后的v的状态是明确赋值的,而且位于expr-firs
否则,如果位于expr-second之后的v的状态是明确赋值的或为“在true表达式后明
否则,如果位于expr-first之后的v的状态是“在false表达式后明确赋值”,而且
否则,在expr之后,v的状态就不是明确赋值的。
classA{staticvoidF(intx,inty){inti
||表达式
位于expr-first之前的v的明确赋值状态与位于expr之前的v的明确赋值状态相
如果位于expr-first之后的v的状态是明确赋值的或“在false表达式后明确赋值”
位于expr之后的v的明确赋值状态取决于:
如果在expr-first之后,v的状态是明确赋值的,则在expr之后的v的状态也是明
否则,如果位于expr-second之后的v的状态是明确赋值的,而且位于expr-firs
否则,如果位于expr-second之后的v的状态是明确赋值的或是“在false表达式后
否则,如果位于expr-first之后的v的状态是“在true表达式后明确赋值”,而且位
否则,在expr之后,v的状态就不是明确赋值的。
classA{staticvoidG(intx,inty){inti
!表达式
位于expr-operand之前的v的明确赋值状态与位于expr之前的v的明确赋值状
位于expr之后的v的明确赋值状态取决于:
如果在expr-operand之后,v的状态是明确赋值的,则在expr之后,v的状态也是
如果在expr-operand之后,v的状态不是明确赋值的,则在expr之后,v的状态也
如果位于expr-operand之后的v的状态是“在false表达式后明确赋值”,则位于
如果位于expr-operand之后的v的状态是“在true表达式后明确赋值”,则位于
??表达式
位于expr-first之前的v的明确赋值状态与位于expr之前的v的明确赋值状态相
位于expr-second之前的v的明确赋值状态与位于expr-first之后的v的
位于expr之后的v的明确赋值状态取决于:
如果expr-first是值为null的常量表达式(第
否则,位于expr之后的v的状态与位于expr-first之后的v的明确赋值状态相同
?:表达式
位于expr-cond之前的v的明确赋值状态与位于expr之前的v的状态相同。
当且仅当位于expr-cond之后的v的状态是明确赋值的或“在true表达式后明确赋值”
当且仅当位于expr-cond之后的v的状态是明确赋值的或“在false表达式后明确赋值
位于expr之后的v的明确赋值状态取决于:
如果expr-cond是值为true的常量表达式(第
否则,如果expr-cond是值为false的常量表达式(第
否则,如果位于expr-true之后的v的状态是明确赋值的,而且位于expr-false
否则,在expr之后,v的状态就不是明确赋值的。
匿名函数
位于body之前的外层变量v的明确赋值状态与位于expr之前的v的状态相同。即,外层
位于expr之后的外层变量v的明确赋值状态与位于expr之前的v的状态相同。
delegateboolFilter(inti);
voidF(){intmax;
//Error,maxisnotdefinitelyassignedFilte
max=5;DoWork(f);}
delegatevoidD();
voidF(){intn;Dd=()=>{n=1;};
d();
//Error,nisnotdefinitelyassignedConsole
变量引用
variable-reference:expression
变量引用的原子性
转换
inta=123;longb=a;//implicitconversion
隐式转换
标识转换
隐式数值转换
隐式枚举转换
可以为null的隐式转换
null文本转换
隐式引用转换
装箱转换
隐式常量表达式转换
用户定义的隐式转换
匿名函数转换
方法组转换
标识转换
隐式数值转换
从sbyte到short、int、long、float、double或decimal。
从byte到short、ushort、int、uint、long、ulong、float、do
从short到int、long、float、double或decimal。
从ushort到int、uint、long、ulong、float、double或deci
从int到long、float、double或decimal。
从uint到long、ulong、float、double或decimal。
从long到float、double或decimal。
从ulong到float、double或decimal。
从char到ushort、int、uint、long、ulong、float、double或
从float到double。
隐式枚举转换
可以为null的隐式转换
从S?到T?的隐式转换。
从S到T?的隐式转换。
如果可以为null的转换是从S?到T?:
如果源值为null(HasValue属性为false),则结果为T?类型的null值。
否则,转换计算过程为从S?解包为S,然后进行从S到T的基础转换,最后从T包装(第
如果可以为null的转换是从S到T?,则转换计算过程为从S到T的基础转换,然后从
null文本转换
隐式引用转换
从任何reference-type到object。
从任何class-typeS到任何class-typeT(前提是S是从T派生的)。
从任何class-typeS到任何interface-typeT(前提是S实现了T)
从任何interface-typeS到任何interface-typeT(前提是S是从
从元素类型为SE的array-typeS到元素类型为TE的array-typeT(
S和T只是元素类型不同。换言之,S和T具有相同的维数。
SE和TE都是reference-types。
存在从SE到TE的隐式引用转换。
从任何array-type到System.Array以及它实现的接口。
从一维数组类型S[]到System.Collections.Generic.IList
从任何delegate-type到System.Delegate以及它实现的接口。
从null文本到任何reference-type。
涉及已知为引用类型的类型参数的隐式转换。有关涉及类型参数的隐式转换的更多详细信息,请参见第
装箱转换
如果源值为null(HasValue属性为false),则结果为目标类型的空引用。
否则,结果为对经过源值解包和装箱后所产生的装箱T的引用。
隐式常量表达式转换
int类型的constant-expression(第
long类型的constant-expression可以转换为ulong类型(前提是co
涉及类型形参的隐式转换
从T到其有效基类C、从T到C的任何基类,以及从T到C实现的任何接口。在运行时,
从T到T的有效接口集中的接口类型I和从T到I的任何基接口。在运行时,如果T为
从T到类型形参U,前提是T依赖U(第
从null文本到T(假定T已知为引用类型)。
用户定义的隐式转换
匿名函数转换和方法组转换
显式转换
所有隐式转换。
显式数值转换。
显式枚举转换。
可以为null的显式转换。
显式引用转换。
显式接口转换。
拆箱转换。
用户定义的显式转换。
显式数值转换
从sbyte到byte、ushort、uint、ulong或char。
从byte到sbyte和char。
从short到sbyte、byte、ushort、uint、ulong或char。
从ushort到sbyte、byte、short或char。
从int到sbyte、byte、short、ushort、uint、ulong或char。
从uint到sbyte、byte、short、ushort、int或char。
从long到sbyte、byte、short、ushort、int、uint、ulong或
从ulong到sbyte、byte、short、ushort、int、uint、long或
从char到sbyte、byte或short。
从float到sbyte、byte、short、ushort、int、uint、long、ul
从double到sbyte、byte、short、ushort、int、uint、long、u
从decimal到sbyte、byte、short、ushort、int、uint、long、
对于从一个整型到另一个整型的转换,处理取决于该转换发生时的溢出检查上下文(第
在checked上下文中,如果源操作数的值在目标类型的范围内,转换就会成功,但如果源操作数的值在
在unchecked上下文中,转换总是会成功并按下面这样继续。
如果源类型大于目标类型,则截断源值(截去源值中容不下的最高有效位)。然后将结果视为目标类型的值。
如果源类型小于目标类型,则源值或按符号扩展或按零扩展,以使它的大小与目标类型相同。如果源类型是有符号
如果源类型的大小与目标类型相同,则源值被视为目标类型的值。
对于从decimal到整型的转换,源值向零舍入到最接近的整数值,该整数值成为转换的结果。如果转换
对于从float或double到整型的转换,处理取决于发生该转换时的溢出检查上下文(第
在checked上下文中,如下所示进行转换:
如果操作数的值是NaN或无穷大,则引发System.OverflowException。
否则,源操作数会向零舍入到最接近的整数值。如果该整数值处于目标类型的范围内,则该值就是转换的结果。
否则,引发System.OverflowException。
在unchecked上下文中,转换总是会成功并按下面这样继续。
如果操作数的值是NaN或infinite,则转换的结果是目标类型的一个未经指定的值。
否则,源操作数会向零舍入到最接近的整数值。如果该整数值处于目标类型的范围内,则该值就是转换的结果。
否则,转换的结果是目标类型的一个未经指定的值。
对于从double到float的转换,double值舍入到最接近的float值。如果
对于从float或double到decimal的转换,源值将转换为decimal表示
对于从decimal到float或double的转换,decimal值舍入到最接近的
显式枚举转换
从sbyte、byte、short、ushort、int、uint、long、ulong、char
从任何enum-type到sbyte、byte、short、ushort、int、uint、l
从任何enum-type到任何其他enum-type。
Ref174437950
可以为null的显式转换
从S?到T?的显式转换。
从S到T?的显式转换。
从S?到T的显式转换。
如果可以为null的转换是从S?到T?:
如果源值为null(HasValue属性为false),则结果为T?类型的null值。
否则,转换计算过程为从S?解包为S,然后进行从S到T的基础转换,最后从T包装为T
如果可以为null的转换是从S到T?,则转换计算过程为从S到T的基础转换,然后从
如果可以为null的转换是从S?到T,则转换计算过程为从S?解包为S,然后进行从S
显式引用转换
从object到任何其他reference-type。
从任何class-typeS到任何class-typeT(前提是S为T的基类)。
从任何class-typeS到任何interface-typeT(前提是S未密封并且
从任何interface-typeS到任何class-typeT(前提是T未密封或T
从任何interface-typeS到任何interface-typeT(前提是S不是
从元素类型为SE的array-typeS到元素类型为TE的array-typeT(
S和T只是元素类型不同。换言之,S和T具有相同的维数。
SE和TE都是reference-types。
存在从SE到TE的显式引用转换。
从System.Array及其实现的接口到任何array-type。
从一维数组类型S[]到System.Collections.Generic.IList
从System.Collections.Generic.IList及其基接口到一维数组类型
从System.Delegate及其实现的接口到任何delegate-type。
涉及已知为引用类型的类型形参的显式转换。有关涉及类型形参的显式转换的更多详细信息,请参见第
拆箱转换
涉及类型形参的显式转换
从T的有效基类C到T和从C的任何基类到T。在运行时,如果T为值类型,则转换将作
从任何接口类型到T。在运行时,如果T为值类型,则转换将作为取消装箱转换执行。否则,转换将作为显
从T到任何interface-typeI,前提是尚未存在从T到I的隐式转换。在运行时
从类型形参U到T,前提是T依赖U(第
classX{publicstaticlongF(Tt){retu
classX{publicstaticlongF(Tt){retu
用户定义的显式转换
标准转换
标准隐式转换
标识转换(第
隐式数值转换(第
可以为null的隐式转换(第
隐式引用转换(第
装箱转换(第
隐式常量表达式转换(第
涉及类型形参的隐式转换(第
标准显式转换
用户定义的转换
允许的用户定义转换
S0和T0是不同的类型。
S0和T0中总有一个是声明了该运算符的类类型或结构类型。
S0和T0都不是interface-type。
除用户定义的转换之外,不存在从S到T或从T到S的转换。
提升转换运算符
用户定义转换的计算
查找考虑从中使用用户定义的转换运算符的类和结构集。此集由源类型及其基类和目标类型及其基类组成(隐式假
通过该类型集确定适用的用户定义转换运算符和提升转换运算符。一个转换运算符如满足下述条件就是适用的:必
由适用的用户定义运算符集,明确地确定哪一个运算符是最精确的。一般而言,最精确的运算符是操作数类型“最
首先,如果需要,执行一个标准转换,将源类型转换为用户定义转换运算符或提升转换运算符的操作数所要求的类
然后,调用用户定义转换运算符或提升转换运算符来执行转换。
最后,如果需要,再执行一个标准转换,将用户定义转换运算符或提升转换运算符的结果类型转换为目标类型。
如果存在从A类型到B类型的标准隐式转换(第
在一个类型集中,包含程度最大的类型(mostencompassingtype)是指这样的一个
在一个类型集中,被包含程度最大的类型(mostencompassedtype)是指这样一个类
用户定义的隐式转换
确定类型S0和T0。如果S或T是可以为null的类型,则S0和T0为它们的
查找类型集D,将从该类型集考虑用户定义的转换运算符。此集由S0(如果S0是类或结构)、S0
查找适用的用户定义转换运算符和提升转换运算符集U。集U由用户定义的隐式转换运算符和提升隐式转换
在U中查找运算符的最精确的源类型SX:
如果U中的任何运算符都从S转换,则SX为S。
否则,SX在U中运算符的合并源类型集中是被包含程度最大的类型。如果无法恰好找到一个被包含程度最
在U中查找运算符的最精确的目标类型TX:
如果U中的任何运算符都转换为T,则TX为T。
否则,TX是U中运算符的合并目标类型集中包含程度最大的类型。如果无法恰好找到一个包含程度最大的
查找最具体的转换运算符:
如果U中只含有一个从SX转换到TX的用户定义转换运算符,则这就是最精确的转换运算符。
否则,如果U恰好包含一个从SX转换到TX的提升转换运算符,则这就是最具体的转换运算符。
否则,转换是不明确的,并发生编译时错误。
最后,应用转换:
如果S不是SX,则执行从S到SX的标准隐式转换。
调用最具体的转换运算符,以从SX转换到TX。
如果TX不是T,则执行从TX到T的标准隐式转换。
用户定义的显式转换
确定类型S0和T0。如果S或T是可以为null的类型,则S0和T0为它们的
查找类型集D,将从该类型集考虑用户定义的转换运算符。该类型集由S0(如果S0为类或结构)、S
查找适用的用户定义转换运算符和提升转换运算符集U。集U由用户定义的隐式或显式转换运算符以及提升
在U中查找运算符的最精确的源类型SX:
如果U中的任何运算符都从S转换,则SX为S。
否则,如果U中的任何运算符都从包含S的类型转换,则SX是这些运算符的合并源类型集中被包含
否则,SX在U中运算符的合并源类型集中是包含程度最大的类型。如果无法恰好找到一个包含程度最大的
在U中查找运算符的最精确的目标类型TX:
如果U中的任何运算符都转换为T,则TX为T。
否则,如果U中的任何运算符都转换为被T包含的类型,则TX是这些运算符的合并目标类型集中包
否则,TX是U中运算符的合并目标类型集中被包含程度最大的类型。如果找不到被包含程度最大的类型,
查找最具体的转换运算符:
如果U中只含有一个从SX转换到TX的用户定义转换运算符,则这就是最精确的转换运算符。
否则,如果U恰好包含一个从SX转换到TX的提升转换运算符,则这就是最具体的转换运算符。
否则,转换是不明确的,并发生编译时错误。
最后,应用转换:
如果S不是SX,则执行从S到SX的标准显式转换。
调用最精确的用户定义转换运算符来执行从SX到TX的转换。
如果TX不是T,则执行从TX到T的标准显式转换。
匿名函数转换
anonymous-method-expression或lambda-expression被归
如果F包含anonymous-function-signature,则D与F的参数个数
如果F不包含anonymous-function-signature,则D可以有零个或多个
如果F具有显式类型化参数列表,则D中的每个参数与F中的对应参数具有相同的类型和修饰符。
如果F具有隐式类型化参数列表,则D没有ref或out参数。
如果D具有void返回类型并且F的函数体是一个表达式,则将F的每个参数均指定为D
如果D具有void返回类型并且F的函数体是一个语句块,则将F的每个参数均指定为D
如果D具有非空返回类型并且F的函数体是一个表达式,则将F的每个参数均指定为D中对应参
如果D具有非空返回类型并且F的函数体是一个语句块,则将F的每个参数均指定为D中对应参
Funcf1=x=>x+1;//Ok
Funcf2=x=>x+1;//Ok
Funcf3=x=>x+1;//Error
匿名函数转换为委托类型的计算
delegatedoubleFunction(doublex);
classTest{staticdouble[]Apply(double[]a,F
staticvoidF(double[]a,double[]b){a=A
匿名函数转换为表达式目录树类型的计算
实现示例
publicdelegatevoidD();
classTest{staticvoidF(){Dd=()=>{
classTest{staticvoidF(){Dd=newD(__
staticvoid__Method1(){Console.WriteLine("
classTest{intx;
voidF(){Dd=()=>{Console.WriteLine(x)
classTest{intx;
voidF(){Dd=newD(__Method1);}
void__Method1(){Console.WriteLine(x);}
classTest{voidF(){inty=123;Dd=
classTest{voidF(){__Locals1__locals1=
class__Locals1{publicinty;
publicvoid__Method1(){Console.WriteLine
classTest{intx;
voidF(){inty=123;for(inti=0;i
classTest{voidF(){__Locals1__locals1=
class__Locals1{publicTest__this;pu
class__Locals2{public__Locals1__locals
publicvoid__Method1(){Console.WriteLine
方法组转换
对于E(A)形式的方法调用(第
实参列表A是一个表达式列表,每个都可归类为变量并且具有D的formal-parameter
所考虑的候选方法仅为那些可以其正常形式(第
如果第7.5
选定的方法M必须与委托类型D兼容(第
如果选定的方法M是实例方法,则与E关联的实例表达式确定委托的目标对象。
如果选定的方法M是通过实例表达式上的成员访问表示的扩展方法,则该实例表达式将确定委托的目标对象。
转换的结果是类型D的值,即一个引用选定方法和目标对象的新创建的委托。
delegatestringD1(objecto);
delegateobjectD2(strings);
delegateobjectD3();
delegatestringD4(objecto,paramsobject[]a);
delegatestringD5(inti);
classTest{staticstringF(objecto){...}
staticvoidG(){D1d1=F;//OkD2d2
}}
objectobj=newEventHandler(myDialog.OkClick);
objectobj=(EventHandler)myDialog.OkClick;
如果在编译时选定的方法是一个实例方法,或者是一个以实例方法访问的扩展方法,则委托的目标对象由与E
计算实例表达式。如果此计算导致异常,则不执行进一步的操作。
如果实例表达式为reference-type,则由实例表达式计算的值将成为目标对象。如果目标对象为
如果实例表达式为value-type,则执行装箱操作(第
否则,选定的方法为静态方法调用的一部分,而委托的目标对象为null。
为委托类型D的一个新实例分配存储位置。如果没有足够的可用内存来为新实例分配存储位置,则引发Sy
用对在编译时确定的方法的引用和对上面计算的目标对象的引用初始化新委托实例。
表达式
表达式的分类
值。每个值都有关联的类型。
变量。每个变量都有关联的类型,称为该变量的已声明类型。
命名空间。归为此类的表达式只能出现在member-access(第
类型。归为此类的表达式只能出现在member-access(第
方法组。它是一组重载方法,是成员查找(第
null文本。归类为null文本的表达式可以隐式转换为引用类型或可以为null的类型。
匿名函数。归类为匿名函数的表达式可以隐式转换为兼容的委托类型或表达式目录树类型。
属性访问。每个属性访问都有关联的类型,即该属性的类型。此外,属性访问可以有关联的实例表达式。当调用实
事件访问。每个事件访问都有关联的类型,即该事件的类型。此外,事件访问还可以有关联的实例表达式。事件访
索引器访问。每个索引器访问都有关联的类型,即该索引器的元素类型。此外,索引器访问还可以有关联的实例表
Nothing。这出现在当表达式是调用一个具有void返回类型的方法时。归类为Nothing
表达式的值
变量的值只是当前存储在该变量所标识的存储位置的值。必须先将变量视为已明确赋值(第
通过调用属性的get-accessor来获取属性访问表达式的值。如果属性没有get-acces
通过调用索引器的get-accessor来获取索引器访问表达式的值。如果索引器没有get-ac
运算符
一元运算符。一元运算符带一个操作数并使用前缀表示法(如–x)或后缀表示法(如x++)。
二元运算符。二元运算符带两个操作数并且全都使用中缀表示法(如x + y)。
三元运算符。只存在一个三元运算符?:,它带三个操作数并使用中缀表示法(c? x: y)。
运算符的优先级和顺序关联性
章节
类别
运算符
7.5
基本
x.yf(x)a[x]x++x--new
typeofdefaultcheckeduncheckeddelegate
7.6
一元
+-!~++x--x(T)x
7.7
乘除
*/%
7.7
加减
+-
7.8
移位
<<>>
7.9
关系和类型检测
<><=>=isas
7.9
相等
==!=
7.10
逻辑AND
&
7.10
逻辑XOR
^
7.10
逻辑OR
|
7.11
条件AND
&&
7.11
条件OR
||
7.12
空合并
??
7.13
条件
?:
7.16,
赋值和lambda表达式
=*=/=%=+=-=<<=>>=&=^=|=
=>
除了赋值运算符外,所有的二元运算符都左结合(left-associative),意思是从左向右执行
赋值运算符和条件运算符(?:)向右顺序关联(right-associative),意思是从右向
运算符重载
+-!~++--truefalse
+-*/%&|^<<>>==!=
运算符表示法
函数表示法
opx
operatorop(x)
xop
operatorop(x)
xopy
operatorop(x,y)
一元运算符重载决策
对于由X为运算operatorop(x)提供的候选的用户定义运算符集,应根据第
如果候选的用户定义运算符集不为空,则它就会成为运算的候选运算符集。否则,预定义一元operator
第7.4.3
二元运算符重载决策
确定X和Y为运算operatorop(x,y)提供的候选用户定义运算符集。该集包括由
如果候选的用户定义运算符集不为空,则它就会成为运算的候选运算符集。否则,预定义二元operator
第7.4.3
候选用户定义运算符
确定类型T0。如果T是可以为null的类型,则T0是其基础类型;否则T0等于T。
对于T0中的所有operatorop声明和此类运算符的提升形式,如果关于参数列表A至少
否则,如果T0为object,则候选运算符集为空。
否则,T0提供的候选运算符集为T0的直接基类提供的候选运算符集,或者为T0的有效基类(如果
数值提升
intoperator*(intx,inty);uintoperator*(uint
一元数值提升
二元数值提升
如果有一个操作数的类型为decimal,则另一个操作数转换为decimal类型;否则,如果另一
否则,如果有一个操作数的类型为double,则另一个操作数转换为double类型。
否则,如果有一个操作数的类型为float,则另一个操作数转换为float类型。
否则,如果有一个操作数的类型为ulong,则另一个操作数转换为ulong类型;否则,如果另一个
否则,如果有一个操作数的类型为long,则另一个操作数转换为long类型。
否则,如果有一个操作数的类型为uint而另一个操作数的类型为sbyte、short或int
否则,如果有一个操作数的类型为uint,则另一个操作数转换为uint类型。
否则,两个操作数都转换为int类型。
decimalAddPercent(decimalx,doublepercent){
decimalAddPercent(decimalx,doublepercent){
提升运算符
对于一元运算符
+++---!~
对于二元运算符
+-*/%&|^<<>>
对于相等运算符
==!=
对于关系运算符
<><=>=
成员查找
首先确定名为 N的可访问的成员的集:
如果T是类型形参,则该集是被指定为T的主要约束或次要约束(第
否则,该集由 T中所有名为 N的可访问(第3.5节)成员(包括继承的成员)和object中
下一步,如果K为零,则移除声明中包含类型形参的所有嵌套类型。如果K不为零,则移除所有具有不同
接着,如果调用该成员,则从该集中移除所有不可调用的成员。
然后,从该集中移除被其他成员隐藏的成员。对于该集中的每个成员S.M(其中S是声明了成员M的
如果M是一个常量、字段、属性、事件或枚举成员,则从该集中移除在S的基类型中声明的所有成员。
如果M是一个类型声明,则从该集中移除在S的基类型中声明的所有非类型,并从该集中移除与在S
如果M是方法,则从该集移除在S的基类型中声明的所有非方法成员。
然后,从该集中移除被类成员隐藏的接口成员。仅当T为类型形参,并且T同时具有除object
如果M是一个常量、字段、属性、事件、枚举成员或类型声明,则从该集中移除在接口声明中声明的所有成员
如果M是一个方法,则从该集中移除在接口声明中声明的所有非方法成员,并从该集中移除与在接口声明中声
最后,移除了隐藏成员后,按下述规则确定查找结果:
如果该集由单个非方法成员组成,则此成员即为查找的结果。
否则,如果该集只包含方法,则这组方法即为查找结果。
否则,该查找是不明确的,将会发生编译时错误。
基类型
如果T为object,则T没有基类型。
如果T为enum-type,则T的基类型为类类型System.Enum、System.V
如果T为struct-type,则T的基类型为类类型System.ValueType和
如果T为class-type,则T的基类型为T的基类,其中包括类类型object。
如果T为interface-type,则T的基类型为T的基接口和类类型object。
如果T为array-type,则T的基类型为类类型System.Array和obje
如果T为delegate-type,则T的基类型为类类型System.Delegate
函数成员
方法
属性
事件
索引器
用户定义运算符
实例构造函数
静态构造函数
析构函数
构造
示例
说明
方法调用
F(x,y)
应用重载决策以在包含类或结构中选择最佳的方法F。以参数列表(x,y)调用该方法。如果该方法不
T.F(x,y)
应用重载决策以在类或结构T中选择最佳的方法F。如果该方法不为static,则发生编译时错误。
e.F(x,y)
应用重载决策以在e的类型给定的类、结构或接口中选择最佳的方法F。如果该方法为static,则
属性访问
P
调用包含类或结构中属性P的get访问器。如果P是只写的,则发生编译时错误。如果P不是
P=value
用参数列表(value)调用包含类或结构中的属性P的set访问器。如果P是只读的,则
T.P
调用类或结构T中属性P的get访问器。如果P不为static,或者P是只写的,
T.P=value
用参数列表(value)调用类或结构T中的属性P的set访问器。如果P不为st
e.P
用实例表达式e调用由e的类型给定的类、结构或接口中属性P的get访问器。如果P为
e.P=value
用实例表达式e和参数列表(value)调用e的类型给定的类、结构或接口中属性P的s
事件访问
E+=value
调用包含类或结构中的事件E的add访问器。如果E不是静态的,则用this来表达对应的
E-=value
调用包含类或结构中的事件E的remove访问器。如果E不是静态的,则用this来表达
T.E+=value
调用类或结构T中事件E的add访问器。如果E不是静态的,则发生编译时错误。
T.E-=value
调用类或结构T中事件E的remove访问器。如果E不是静态的,则发生编译时错误。
e.E+=value
用实例表达式e调用由e的类型给定的类、结构或接口中事件E的add访问器。如果E是
e.E-=value
用实例表达式e调用由e的类型给定的类、结构或接口中事件E的remove访问器。如果
索引器访问
e[x,y]
应用重载决策以在e的类型给定的类、结构或接口中选择最佳的索引器。用实例表达式e和参数列表(
e[x,y]=value
应用重载决策以在e的类型给定的类、结构或接口中选择最佳的索引器。用实例表达式e和参数列表(
运算符调用
-x
应用重载决策以在x的类型给定的类或结构中选择最佳的一元运算符。用参数列表(x)调用选定的运算
x+y
应用重载决策以在x和y的类型给定的类或结构中选择最佳的二元运算符。用参数列表(x,y)
实例构造函数调用
newT(x,y)
应用重载决策以在类或结构T中选择最佳的实例构造函数。用参数列表(x,y)调用该实例构造函数
实参列表
对于实例构造函数、方法和委托,将实参指定为argument-list,如下所述。
对于属性,当调用get访问器时,实参列表是空的;而当调用set访问器时,实参列表由指定为赋值
对于事件,实参列表由指定为+=或-=运算符的右操作数的表达式组成。
对于索引器,实参列表由在索引器访问中的方括号之间指定的表达式组成。当调用set访问器时,实参列表
对于用户定义的运算符,实参列表由一元运算符的单个操作数或二元运算符的两个操作数组成。
argument-list:argumentargument-list,argume
argument:expressionrefvariable-referenceout
expression,指示将实参以值形参(第
后跟variable-reference(第
对于值形参,计算实参表达式并执行到相应的形参类型的隐式转换(第
对于引用形参或输出形参,计算对应的变量引用,所得的存储位置在函数成员调用中成为该形参表示的存储位置。
当以其正常形式调用带有形参数组的函数成员时,为该形参数组指定的实参必须是属于某个类型的单个表达式,而
当以其展开形式调用带有形参数组的函数成员时,调用必须为形参数组指定零个或多个实参,其中每个实参均为某
classTest{staticvoidF(intx,inty,intz)
staticvoidMain(){inti=0;F(i++,i++
x=0,y=1,z=2
classTest{staticvoidF(refobjectx){...}
staticvoidMain(){object[]a=newobject[
voidF(intx,inty,paramsobject[]args);
F(10,20);F(10,20,30,40);F(10,20,1,"hello"
F(10,20,newobject[]{});F(10,20,newobject[]
类型推断
classChooser{staticRandomrand=newRandom(
publicstaticTChoose(Tfirst,Tsecond){
inti=Chooser.Choose(5,213);//CallsChoos
strings=Chooser.Choose("foo","bar");//Calls
TrM(T1x1…Tmxm)
第一阶段
第二阶段
输入类型
输出类型
依赖
输出类型推断
如果E是具有推断出的返回类型U(第
否则,如果E为方法组,T为具有参数类型T1…Tk和返回类型Tb的委托类型或表达式目录树
否则,如果E是一个类型为U的表达式,则从U到T进行下限推断。
否则,不进行任何推断。
参数类型显式推断
如果E为具有参数类型U1…Uk的显式类型匿名函数,T为具有参数类型V1…Vk的委托类型
精确推断
如果V是未固定的Xi之一,则将U添加到Xi的界限集中。
否则,如果U是数组类型Ue[…]而V是具有相同秩的数组类型Ve[…],则进行从Ue
否则,如果V是构造类型C而U是构造类型C,则进行从每个U
否则,不进行任何推断。
下限推断
如果V是未固定的Xi之一,则将U添加到Xi的界限集中。
否则,如果U是数组类型Ue[…]而V是具有相同秩的数组类型Ve[…];或者如果U是
如果已知Ue为引用类型,则进行从Ue到Ve的下限推断
否则,进行从Ue到Ve的精确推断
否则,如果V是构造类型C并且有唯一的U1…Uk类型集,以存在从U到C
否则,不进行任何推断。
固定
候选类型Uj的集以所有类型的集形式在Xi的界限集中开始。
然后我们为Xi依次检查每个界限:对于Xi的每个界限U,将所有特定类型Uj(不存在从U
如果在其余的候选类型Uj中,存在唯一类型V(该类型可经标准隐式转换而转换为其他所有候选类型),
否则,类型推断将失败。
推断返回类型
如果F的函数体是一个expression,则F的推断返回类型为该表达式的类型。
如果F的函数体是一个block并且该块的return语句中的表达式集具有最通用类型T
否则,无法为E推断返回类型。
namespaceSystem.Linq{publicstaticclassEnum
Listcustomers=GetCustomerList();IEnu
IEnumerablenames=Enumerable.Select(cust
Sequence.Select(customers,(Custo
staticZF(Xvalue,Funcf1,Func
doubleseconds=F("1:15:30",s=>TimeSpan.Parse(
方法组转换的类型推断
TrM(T1x1…Tmxm)
M
查找一组表达式的最通用类型
TrM(Xx1…Xxm)
重载决策
调用在invocation-expression(第
调用在object-creation-expression(第
通过element-access(第
调用表达式(第
如果给定了适用的候选函数成员集,则在其中选出最佳函数成员。如果该集只包含一个函数成员,则该函数成员为
适用函数成员
A中的实参数目与函数成员声明中的形参数目相同。
对于A中的每个实参,实参的形参传递模式(即值、ref或out)与相应形参的形参传递模式相同,
对于值形参或形参数组,存在从实参到对应形参的类型的隐式转换(第
对于ref或out参数,实参的类型与相应形参的类型相同。ref或out参数毕竟只是传递
构造展开形式的方法是:用形参数组的元素类型的零个或更多值参数替换函数成员声明中的形参数组,使实参列表
否则,如果对于A中的每个实参,它的实参传递模式与相应形参的形参传递模式相同,并且下列条件成立,则
对于固定值形参或展开操作所创建的值形参,存在从实参类型到对应的形参类型的隐式转换(第
对于ref或out参数,实参的类型与相应形参的类型相同。
更好的函数成员
对于每个实参,从EX到QX的隐式转换不如从EX到PX的隐式转换好,并且
对于至少一个参数,从EX到PX的转换比从EX到QX的转换更好。
如果MP是非泛型方法而MQ是泛型方法,则MP比MQ好。
否则,如果MP在正常形式下适用,MQ有一个params数组并且仅在其展开形式下适用,则M
否则,如果MP具有比MQ更少的已声明形参,则MP比MQ好。如果两个方法都有para
否则,如果MP具有比MQ更明确的形参类型,则MP比MQ好。假设{R1,R2,…
类型形参不如非类型形参明确。
递归地,如果某个构造类型至少有一个类型实参更明确,并且没有类型实参比另一个构造类型(两者具有相同数目
如果一个数组类型的元素类型比另一个数组类型的元素类型更明确,则第一个数组类型比第二个数组类型(具有相
否则,如果一个成员是非提升运算符而另一个是提升运算符,则非提升运算符更佳。
否则,两个函数成员都不是更好的。
表达式的更佳转换
T1具有返回类型Y且T2返回void
类型的更佳转换
给定从类型S转换到类型T1的转换C1和从类型S转换到类型T2的转换C2,如果
S是T1
存在从T1到T2的隐式转换,不存在从T2到T1的隐式转换
T1为有符号的整型,T2为无符号的整型。具体包括:
T1为sbyte,T2为byte、ushort、uint或ulong
T1为short,T2为ushort、uint或ulong
T1为int,T2为uint或ulong
T1为long,T2为ulong
泛型类中的重载
interfaceI1{...}
interfaceI2{...}
classG1{intF1(Uu);//Overloadresul
voidF2(I1a);//ValidoverloadvoidF2
classG2{voidF3(Uu,Vv);//Valid,b
voidF4(Uu,I1v);//Valid,butoverloadres
voidF5(Uu1,I1v2);//Validoverloadvoi
voidF6(refUu);//validoverloadvoidF6
函数成员调用
静态函数成员。包括实例构造函数、静态方法、静态属性访问器和用户定义的运算符。静态函数成员总是非虚的。
实例函数成员。包括实例方法、实例属性访问器和索引器访问器。实例函数成员不是非虚的就是虚的,并且总是在
如果M是静态函数成员,则:
实参列表按照第
调用M。
如果M是在value-type中声明的实例函数成员,则:
计算E。如果该计算导致异常,则不执行进一步的操作。
如果E没有被归类为一个变量,则创建一个与E同类型的临时局部变量,并将E的值赋给该变量。这
实参列表按照第
调用M。E引用的变量成为this引用的变量。
如果M是在reference-type中声明的实例函数成员,则:
计算E。如果该计算导致异常,则不执行进一步的操作。
实参列表按照第
如果E的类型为value-type,则执行装箱转换(第
检查E的值是否有效。如果E的值为null,则引发System.NullReference
要调用的函数成员实现按以下规则确定:
如果E的编译时类型是接口,则调用的函数成员是M的实现,此实现是由E引用的实例在运行时所属
否则,如果M是虚函数成员,则调用的函数成员是由E引用的实例运行时类型提供的M实现。确定此
否则,M是非虚函数成员,调用的函数成员是M本身。
调用在上一步中确定的函数成员实现。E引用的对象成为this引用的对象。
已装箱实例上的调用
当该函数成员是从object类型继承的,且具有override修饰符,并通过object
当函数成员是接口函数成员的实现并且通过interface-type的实例表达式被调用时。
当函数成员通过委托被调用时。
基本表达式
primary-expression:primary-no-array-creation-exp
primary-no-array-creation-expression:literalsimp
objecto=newint[3][1];
objecto=(newint[3])[1];
文本
简单名称
simple-name:identifiertype-argument-listopt
如果K为零,simple-name在某个block内出现,并且该block(或包容bl
如果K为零,并且simple-name出现在泛型方法声明体中,并且该声明包含名为I的类型
否则,对于每个实例类型 T(第
如果K为零,并且T的声明包含名为 I的类型形参,则simple-name将引用该类型形
否则,如果在T中对具有K 个类型实参的I进行成员查找(第
如果T为直接包容类或结构类型的实例类型,并且该查找标识了一个或多个方法,则结果是一个具有thi
否则,如果T为直接包容类或结构类型的实例类型,如果查找标识出一个实例成员,并且引用发生在实例构造
否则,对于每个命名空间 N,从出现simple-name的命名空间开始,依次继续每个包容命名空间
如果K为零,并且I为 N中的命名空间的名称,则:
如果出现simple-name的位置包含在N的命名空间声明中,并且该命名空间声明中包含将名称
否则,simple-name引用N中名为I的命名空间。
否则,如果N包含一个具有名称 I且有K 个类型形参的可访问类型,则:
如果K为零,并且出现simple-name的位置包含在N的命名空间声明中,并且该命名空间
否则,namespace-or-type-name引用利用给定类型实参构造的该类型。
否则,如果出现simple-name的位置包含在N的命名空间声明中:
如果K为零,并且该命名空间声明中包含一个将名称I与一个导入的命名空间或类型关联的exter
否则,如果该命名空间声明的using-namespace-directives导入的命名空间中只
否则,如果该命名空间声明的using-namespace-directives导入的命名空间中包
否则,simple-name是未定义的,并将出现编译时错误。
块中的固定含义
classTest{doublex;
voidF(boolb){x=1.0;if(b){int
classTest{doublex;
voidF(boolb){if(b){x=1.0;}
structPoint{intx,y;
publicPoint(intx,inty){this.x=x;t
带括号的表达式
parenthesized-expression:(expression)
成员访问
member-access:primary-expression.identifier
predefined-type:以下类型之一boolbytechardecimal
如果K为零,E是命名空间,并且E包含名为 I的嵌套命名空间,则结果为该命名空间。
否则,如果E为命名空间,并且E包含具有名称为 I且有K 个类型形参的可访问类型,则结果为
如果E是一个predefined-type或一个归类为类型的primary-express
如果I标识一个类型,则结果为使用给定类型实参构造的该类型。
如果I标识一个或多个方法,则结果为一个没有关联的实例表达式的方法组。如果指定了类型实参列表,则将
如果I标识一个static属性,则结果为一个没有关联的实例表达式的属性访问。
如果I标识一个static字段,则:
如果该字段为readonly并且引用发生在声明该字段的类或结构的静态构造函数外,则结果为值,即
否则,结果为变量,即E中的静态字段I。
如果I标识一个static事件,则:
如果引用发生在声明了该事件的类或结构内,并且事件不是用event-accessor-declara
否则,结果为没有关联的实例表达式的事件访问。
如果I标识一个常量,则结果为值,即该常量的值。
如果I标识枚举成员,则结果为值,即该枚举成员的值。
否则,E.I是无效成员引用,并且会出现编译时错误。
如果E是类型为T的属性访问、索引器访问、变量或值,并且在T中对具有K 个类型实参的I
首先,如果E为属性访问或索引器访问,则获取该属性访问或索引器访问的值(第7.1.1节),并将
如果I标识一个或多个方法,则结果为具有E的关联实例表达式的方法组。如果指定了类型实参列表,则
如果I标识实例属性,则结果为具有E的关联实例表达式的属性访问。
如果T为class-type并且I标识此class-type的一个实例字段,则:
如果E的值为null,则引发System.NullReferenceException。
否则,如果字段为readonly并且引用发生在声明字段的类的实例构造函数外,则结果为值,即E
否则,结果为变量,即E引用的对象中的字段I。
如果T为struct-type并且I标识此struct-type的实例字段,则:
如果E为值,或者如果字段为readonly并且引用发生在声明字段的结构的实例构造函数外,则结
否则,结果为变量,即E给定的结构实例中的字段I。
如果I标识实例事件,则:
如果引用发生在声明事件的类或结构内,并且事件不是用event-accessor-declarati
否则,结果为具有E的关联实例表达式的事件访问。
否则,将尝试将E.I当作扩展方法调用(第
相同的简单名称和类型名称
structColor{publicstaticreadonlyColorWhit
publicColorComplement(){...}}
classA{publicColorColor;//FieldColor
voidF(){Color=Color.Black;//Refere
staticvoidG(){Colorc=Color.White;//
语法多义性
()]}:;,.?==!=
x=yisC+z;
调用表达式
invocation-expression:primary-expression(ar
如果invocation-expression调用的方法或委托返回void,则结果为Noth
否则,结果是由方法或委托返回的类型的值。
方法调用
构造方法调用的候选方法集。对于与方法组M关联的每个方法F:
如果F是非泛型的,则在满足以下条件时,F是候选方法:
M没有类型实参列表,并且
对A来说,F是适用的(第
如果F是泛型的,并且M没有类型实参列表,则在满足以下条件时,F是候选方法:
类型推断(第7
一旦使用推断出的类型实参替换对应的方法类型形参,则F的形参列表中的所有构造类型都满足它们的约束(
如果F是泛型的,并且M包含类型实参列表,则在满足以下条件时,F是候选方法:
F具有的方法类型形参数目与类型实参列表中提供的数目相同,并且
一旦使用类型实参替换对应的方法类型形参,则F的形参列表中的所有构造类型都满足它们的约束(第
候选方法集被减少到仅包含派生程度最大的类型中的方法:对于该集中的每个方法C.F(其中C是声明了
如果得到的候选方法集为空,则将放弃后续步骤中的其他处理,而尝试以扩展方法调用(第
使用第7.4
所选最佳方法的最终验证按如下方式执行:
该方法在方法组的上下文中进行验证:如果该最佳方法是静态方法,则方法组必须是从simple-name
如果该最佳方法是泛型方法,则根据泛型方法上声明的约束(第
OLE_LINK2
扩展方法调用
expr.identifier()
expr.identifier(args)
expr.identifier()
expr.identifier(args)
C.identifier(expr)
C.identifier(expr,args)
C.identifier(expr)
C.identifier(expr,args)
从最接近的封闭命名空间声明开始,接下来是每个封闭命名空间声明,最后是包含编译单元,搜索将连续进行以找
如果给定的命名空间或编译单元直接包含具有适当扩展方法Mj的非泛型类型声明Ci,则这些扩展方法的
如果使用给定命名空间或编译单元中的命名空间指令导入的命名空间直接包含具有适当扩展方法Mj的非泛型
如果在任何封闭命名空间声明或编译单元中都找不到候选集,则会出现编译时错误。
否则,将对候选集应用重载决策,如(第
C是将最佳方法声明为扩展方法的类型。
如果将C用作目标,则将以静态方法调用(第
publicstaticclassE{publicstaticvoidF(thi
publicstaticvoidF(thisobjectobj,strings)
classA{}
classB{publicvoidF(inti){}}
classC{publicvoidF(objectobj){}}
classX{staticvoidTest(Aa,Bb,Cc){a
b.F(1);//B.F(int)b.F("hello");//E.F
c.F(1);//C.F(object)c.F("hello");//
publicstaticclassC{publicstaticvoidF(thi
namespaceN1{publicstaticclassD{publ
namespaceN2{usingN1;
publicstaticclassE{publicstaticvoid
classTest{staticvoidMain(string[]args
E.F(1)D.G(2)C.H(3)
委托调用
计算D。如果此计算导致异常,则不执行进一步的操作。
检查D的值是否有效。如果D的值为null,则引发System.NullReference
否则,D是一个对委托实例的引用。对该委托的调用列表中的每个可调用实体,执行函数成员调用(第
元素访问
element-access:primary-no-array-creation-expressi
expression-list:expressionexpression-list,
数组访问
计算P。如果此计算导致异常,则不执行进一步的操作。
expression-list的索引表达式按从左到右的顺序计算。计算每个索引表达式后,执行到下列类
检查P的值是否有效。如果P的值为null,则引发System.NullReference
针对由P引用的数组实例的每个维度的实际界限,检查expression-list中每个表达式的
计算由索引表达式给定的数组元素的位置,此位置将成为数组访问的结果。
索引器访问
构造由T提供的索引器集。该集由T或T的基类型中声明的所有符合下列条件的索引器组成:它们不
将该集缩减为那些适用的并且不被其他索引器隐藏的索引器。对该集中的每个索引器S.I(其中S为声明
如果I对于A(第
如果I对于A(第
如果I对于A(第
如果结果候选索引器集为空,则不存在适用的索引器,并发生编译时错误。
使用第7.4
expression-list的索引表达式按从左到右的顺序计算。索引器访问的处理结果是属于索引器访
this访问
this-access:this
当this在类的实例构造函数内的primary-expression中使用时,它属于值类别。
当this在类的实例方法或实例访问器内的primary-expression中使用时,它属于
当this在结构的实例构造函数内的primary-expression中使用时,它属于变量类
当this在结构的实例方法或实例访问器内的primary-expression中使用时,它属
如果方法或访问器不是迭代器(第
如果方法或访问器是迭代器,则this变量表示为其调用方法或访问器的结构的copy,并且其行为
base访问
base-access:base.identifierbase[expr
后缀增量和后缀减量运算符
post-increment-expression:primary-expression++
post-decrement-expression:primary-expression--
如果x属于变量:
计算x以产生变量。
保存x的值。
调用选定的运算符,将x的保存值作为参数。
运算符返回的值存储在由x的计算结果给定的位置中。
x的保存值成为运算结果。
如果x属于属性或索引器访问:
计算与x关联的实例表达式(如果x不是static)和参数列表(如果x是索引器访问),结
调用x的get访问器并保存返回的值。
调用选定的运算符,将x的保存值作为参数。
调用x的set访问器,将运算符返回的值作为value参数。
x的保存值成为运算结果。
new运算符
对象创建表达式用于创建类类型和值类型的新实例。
数组创建表达式用于创建数组类型的新实例。
委托创建表达式用于创建委托类型的新实例。
对象创建表达式
object-creation-expression:newtype(argum
object-or-collection-initializer:object-initializ
如果T是value-type且A不存在:
object-creation-expression是默认构造函数调用。object-creati
否则,如果T是type-parameter且A不存在:
如果还没有为T指定值类型约束或构造函数约束(第
object-creation-expression的结果是类型参数所绑定到的运行时类型的值,即调
否则,如果T是class-type或struct-type:
如果T是abstractclass-type,则会发生编译时错误。
使用第7.4
object-creation-expression的结果是T类型的值,即由调用在上面的步骤中
否则,object-creation-expression无效,并发生编译时错误。
如果T是class-type:
为T类的一个新实例分配存储位置。如果没有足够的可用内存来为新实例分配存储位置,则引发Syste
新实例的所有字段都将初始化为它们的默认值(第
根据函数成员调用(第
如果T是struct-type:
通过分配一个临时局部变量来创建类型T的实例。由于要求struct-type的实例构造函数为所
根据函数成员调用(第
对象初始值设定项
object-initializer:{member-initializer-listopt
member-initializer-list:member-initializermember
member-initializer:identifier=initializer-v
initializer-value:expressionobject-or-collection
publicclassPoint{intx,y;
publicintX{get{returnx;}set{x=value
Pointa=newPoint{X=0,Y=1};
Point__a=newPoint();__a.X=0;__a.Y=1;Po
publicclassRectangle{Pointp1,p2;
publicPointP1{get{returnp1;}set{p1=
Rectangler=newRectangle{P1=newPoint{X
Rectangle__r=newRectangle();Point__p1=new
publicclassRectangle{Pointp1=newPoint();
publicPointP1{get{returnp1;}}public
Rectangler=newRectangle{P1={X=0,Y=
Rectangle__r=newRectangle();__r.P1.X=0;__r
集合初始值设定项
collection-initializer:{element-initializer-li
element-initializer-list:element-initializerelem
element-initializer:non-assignment-expression{
Listdigits=newList{0,1,2,3,4,
publicclassContact{stringname;List
publicstringName{get{returnname;}set{
publicListPhoneNumbers{get{return
varcontacts=newList{newContact{
var__clist=newList();Contact__c1=
数组创建表达式
array-creation-expression:newnon-array-type
newint[,]{{0,1},{2,3},{4,5}}
newint[3,2]{{0,1},{2,3},{4,5}}
expression-list的维度长度表达式按从左到右的顺序计算。计算每个表达式后,执行到下列类
维度长度的计算值按下面这样验证。如果一个或多个值小于零,则引发System.OverflowExc
分配具有给定维度长度的数组实例。如果没有足够的可用内存来为新实例分配存储位置,则引发System.
将新数组实例的所有元素初始化为它们的默认值(第
如果数组创建表达式包含数组初始值设定项,则计算数组初始值设定项中的每个表达式的值,并将该值赋值给它的
int[][]a=newint[100][];
int[][]a=newint[100][5];//Error
int[][]a=newint[100][];for(inti=0;i<10
int[,]=newint[100,5];
vara=new[]{1,10,100,1000};//int[
varb=new[]{1,1.5,2,2.5};//double
varc=new[,]{{"hello",null},{"world","!"
vard=new[]{1,"one",2,"two"};//Err
varcontacts=new[]{new{Name="ChrisSm
委托创建表达式
delegate-creation-expression:newdelegate-type
如果E为方法组,则委托创建表达式的处理方式与从E到D的方法组转换(第
如果E为匿名函数,则委托创建表达式的处理方式与从E到D的匿名函数转换(第
如果E为委托类型的值,则E必须与D一致(第
如果E为方法组,则委托创建表达式的计算方式与从E到D的方法组转换(第
如果E为匿名函数,则委托创建的计算方式与从E到D的匿名函数转换(第
如果E是delegate-type的值:
计算E。如果此计算导致异常,则不执行进一步的操作。
如果E的值为null,则引发System.NullReferenceException,并且
为委托类型D的一个新实例分配存储位置。如果没有足够的可用内存来为新实例分配存储位置,则引发Sy
用与E给定的委托实例相同的调用列表初始化新委托实例。
delegatedoubleDoubleFunc(doublex);
classA{DoubleFuncf=newDoubleFunc(Square);
staticfloatSquare(floatx){returnx*x;
staticdoubleSquare(doublex){returnx*x
匿名对象创建表达式
anonymous-object-creation-expression:newanonym
anonymous-object-initializer:{member-declarato
member-declarator-list:member-declaratormember-d
member-declarator:simple-namemember-accessbase-
new{p1=e1,p2=e2,…pn=en}
class__Anonymous1{privatereadonlyT1f1;
public__Anonymous1(T1a1,T2a2,…,Tnan){
publicT1p1{get{returnf1;}}publicT2
publicoverrideboolEquals(objecto){…}pu
varp1=new{Name="Lawnmower",Price=495.00
identifierexpr.identifier
identifer=identifieridentifier=expr.ide
Grammar_typeof_expression
Grammar_unbound_type_name
Grammar_generic_dimension_specifier
Grammar_commas
typeof运算符
typeof-expression:typeof(type)typeof
unbound-type-name:identifiergeneric-dimension-
generic-dimension-specifier:
commas:,commas,
通过将每个generic-dimension-specifier替换为与每个type-argu
计算结果type-name,同时忽略所有类型形参约束。
unbound-type-name解析为与结果构造类型关联的未绑定的泛型类型(第
usingSystem;
classX{publicstaticvoidPrintTypes(){
classTest{staticvoidMain(){X.Prin
System.Int32System.Int32System.StringSystem.Dou
checked和unchecked运算符
checked-expression:checked(expression)
unchecked-expression:unchecked(expression
预定义的++和--一元运算符(第
预定义的-一元运算符(第
预定义的+、-、*和/二元运算符(第
从一个整型到另一个整型或从float或double到整型的显式数值转换(第
在checked上下文中,如果运算发生在一个常量表达式(第
在unchecked上下文中,计算的结果被截断,放弃不适合目标类型的任何高序位。
classTest{staticreadonlyintx=1000000;
staticintF(){returnchecked(x*y);//T
staticintG(){returnunchecked(x*y);//
staticintH(){returnx*y;//Depends
classTest{constintx=1000000;constint
staticintF(){returnchecked(x*y);//C
staticintG(){returnunchecked(x*y);//
staticintH(){returnx*y;//Compile
classTest{staticintMultiply(intx,inty){
staticintF(){returnchecked(Multiply(1000
classTest{publicconstintAllBits=unchecke
publicconstintHighBit=unchecked((int)0x8000
默认值表达式
default-value-expression:default(type)
匿名方法表达式
一元运算符
unary-expression:primary-expression+unary-exp
一元加运算符
intoperator+(intx);uintoperator+(uintx);lo
一元减运算符
整数否定:
intoperator–(intx);longoperator–(longx);
浮点否定:
floatoperator–(floatx);doubleoperator–(doubl
小数否定:
decimaloperator–(decimalx);
逻辑否定运算符
booloperator!(boolx);
按位求补运算符
intoperator~(intx);uintoperator~(uintx);lo
Eoperator~(Ex);
前缀增量和减量运算符
pre-increment-expression:++unary-expression
pre-decrement-expression:--unary-expression
如果x属于变量:
计算x以产生变量。
调用选定的运算符,将x的值作为参数。
运算符返回的值存储在由x的计算结果给定的位置中。
运算符返回的值成为该运算的结果。
如果x属于属性或索引器访问:
计算与x关联的实例表达式(如果x不是static)和参数列表(如果x是索引器访问),结
调用x的get访问器。
调用选定的运算符,将get访问器返回的值作为参数。
调用x的set访问器,将运算符返回的值作为value参数。
运算符返回的值成为该运算的结果。
强制转换表达式
cast-expression:(type)unary-expression
标记的序列对于type是正确的语法,但对于expression则不是。
标记的序列对于type是正确的语法,而且紧跟在右括号后面的标记是标记“~”、标记“!”、标记“(
算术运算符
multiplicative-expression:unary-expressionmultip
additive-expression:multiplicative-expressionadd
乘法运算符
整数乘法:
intoperator*(intx,inty);uintoperator*(uint
浮点乘法:
floatoperator*(floatx,floaty);doubleoperato
+y
–y
+0
–0
+∞
–∞
NaN
+x
+z
–z
+0
–0
+∞
–∞
NaN
–x
–z
+z
–0
+0
–∞
+∞
NaN
+0
+0
–0
+0
–0
NaN
NaN
NaN
–0
–0
+0
–0
+0
NaN
NaN
NaN
+∞
+∞
–∞
NaN
NaN
+∞
–∞
NaN
–∞
–∞
+∞
NaN
NaN
–∞
+∞
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
小数乘法:
decimaloperator*(decimalx,decimaly);
除法运算符
整数除法:
intoperator/(intx,inty);uintoperator/(uint
浮点除法:
floatoperator/(floatx,floaty);doubleoperato
+y
–y
+0
–0
+∞
–∞
NaN
+x
+z
–z
+∞
–∞
+0
–0
NaN
–x
–z
+z
–∞
+∞
–0
+0
NaN
+0
+0
–0
NaN
NaN
+0
–0
NaN
–0
–0
+0
NaN
NaN
–0
+0
NaN
+∞
+∞
–∞
+∞
–∞
NaN
NaN
NaN
–∞
–∞
+∞
–∞
+∞
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
小数除法:
decimaloperator/(decimalx,decimaly);
余数运算符
整数余数:
intoperator%(intx,inty);uintoperator%(uint
浮点余数:
floatoperator%(floatx,floaty);doubleoperato
+y
–y
+0
–0
+∞
–∞
NaN
+x
+z
+z
NaN
NaN
x
x
NaN
–x
–z
–z
NaN
NaN
–x
–x
NaN
+0
+0
+0
NaN
NaN
+0
+0
NaN
–0
–0
–0
NaN
NaN
–0
–0
NaN
+∞
NaN
NaN
NaN
NaN
NaN
NaN
NaN
–∞
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
小数余数:
decimaloperator%(decimalx,decimaly);
加法运算符
整数加法:
intoperator+(intx,inty);uintoperator+(uint
浮点加法:
floatoperator+(floatx,floaty);doubleoperato
y
+0
–0
+∞
–∞
NaN
x
z
x
x
+∞
–∞
NaN
+0
y
+0
+0
+∞
–∞
NaN
–0
y
+0
–0
+∞
–∞
NaN
+∞
+∞
+∞
+∞
+∞
NaN
NaN
–∞
–∞
–∞
–∞
NaN
–∞
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
小数加法:
decimaloperator+(decimalx,decimaly);
枚举加法。每个枚举类型都隐式提供下列预定义运算符,其中E为枚举类型,U为E的基础类型:
Eoperator+(Ex,Uy);Eoperator+(Ux,Ey);
字符串串联:
stringoperator+(stringx,stringy);stringoper
usingSystem;
classTest{staticvoidMain(){strings=
委托组合。每个委托类型都隐式提供以下预定义运算符,其中D是委托类型:
Doperator+(Dx,Dy);
减法运算符
整数减法:
intoperator–(intx,inty);uintoperator–(uint
浮点减法:
floatoperator–(floatx,floaty);doubleoperato
y
+0
–0
+∞
–∞
NaN
x
z
x
x
–∞
+∞
NaN
+0
–y
+0
+0
–∞
+∞
NaN
–0
–y
–0
+0
–∞
+∞
NaN
+∞
+∞
+∞
+∞
NaN
+∞
NaN
–∞
–∞
–∞
–∞
–∞
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
小数减法:
decimaloperator–(decimalx,decimaly);
枚举减法。每个枚举类型都隐式提供下列预定义运算符,其中E为枚举类型,U为E的基础类型:
Uoperator–(Ex,Ey);
Eoperator–(Ex,Uy);
委托移除。每个委托类型都隐式提供以下预定义运算符,其中D是委托类型:
Doperator–(Dx,Dy);
delegatevoidD(intx);
classC{publicstaticvoidM1(inti){/*…*/
classTest{staticvoidMain(){Dcd1=ne
cd3=cd1+cd2+cd2+cd1;//M1+M2+M2+
cd3=cd1+cd2+cd2+cd1;//M1+M2+M2+
cd3=cd1+cd2+cd2+cd1;//M1+M2+M2+
cd3=cd1+cd2+cd2+cd1;//M1+M2+M2+
移位运算符
shift-expression:additive-expressionshift-expre
左移位:
intoperator<<(intx,intcount);uintoperator<
右移位:
intoperator>>(intx,intcount);uintoperator>
当x的类型为int或uint时,位移计数由count的低序的5位给出。换言之,位
当x的类型为long或ulong时,位移计数由count的低序的6位给出。换言之
关系和类型测试运算符
relational-expression:shift-expressionrelational
equality-expression:relational-expressionequalit
运算
结果
x==y
如果x等于y,则为true,否则为false
x!=y
如果x不等于y,则为true,否则为false
x
如果x小于y,则为true,否则为false
x>y
如果x大于y,则为true,否则为false
x<=y
如果x小于等于y,则为true,否则为false
x>=y
如果x大于等于y,则为true,否则为false
整数比较运算符
booloperator==(intx,inty);booloperator==(u
booloperator!=(intx,inty);booloperator!=(u
booloperator<(intx,inty);booloperator<(uin
booloperator>(intx,inty);booloperator>(uin
booloperator<=(intx,inty);booloperator<=(u
booloperator>=(intx,inty);booloperator>=(u
浮点比较运算符
booloperator==(floatx,floaty);booloperator
booloperator!=(floatx,floaty);booloperator
booloperator<(floatx,floaty);booloperator<
booloperator>(floatx,floaty);booloperator>
booloperator<=(floatx,floaty);booloperator
booloperator>=(floatx,floaty);booloperator
如果两个操作数中的任何一个为NaN,则对于除!=(对于此运算符,结果为true)外的所有运算符
当两个操作数都不为NaN时,这些运算符就按下列顺序来比较两个浮点操作数的值
–∞<–max<...<–min<–0.0==+0.0<+min<...
负零和正零被视为相等。
负无穷大被视为小于所有其他值,但等于其他负无穷大。
正无穷大被视为大于所有其他值,但等于其他正无穷大。
小数比较运算符
booloperator==(decimalx,decimaly);
booloperator!=(decimalx,decimaly);
booloperator<(decimalx,decimaly);
booloperator>(decimalx,decimaly);
booloperator<=(decimalx,decimaly);
booloperator>=(decimalx,decimaly);
布尔相等运算符
booloperator==(boolx,booly);
booloperator!=(boolx,booly);
枚举比较运算符
booloperator==(Ex,Ey);
booloperator!=(Ex,Ey);
booloperator<(Ex,Ey);
booloperator>(Ex,Ey);
booloperator<=(Ex,Ey);
booloperator>=(Ex,Ey);
引用类型相等运算符
booloperator==(objectx,objecty);
booloperator!=(objectx,objecty);
两个操作数均为reference-type值或文本null。此外,还存在从一种操作数类型到另一
一个操作数是类型T(其中T是type-parameter)的值,另一个操作数是文本null
使用预定义的引用类型相等运算符比较两个在编译时已能确定是不相同的引用时,会导致编译时错误。例如,如果
预定义的引用类型相等运算符不允许比较值类型操作数。因此,除非结构类型声明自己的相等运算符,否则不可能
预定义的引用类型相等运算符从不会导致对它们的操作数执行装箱操作。执行此类装箱操作毫无意义,这是因为对
如果将类型参数的类型T的操作数与null进行比较,且T的运行时类型为值类型,则比较的结果
classC{voidF(Tx){if(x==null)thr
usingSystem;
classTest{staticvoidMain(){strings=
TrueFalseFalseFalse
classTest{staticvoidMain(){inti=123
字符串相等运算符
booloperator==(stringx,stringy);
booloperator!=(stringx,stringy);
两个值都为null。
两个值都是对字符串实例的非空引用,这两个字符串不仅具有相同的长度,而且在每个字符位置上的字符亦都彼此
委托相等运算符
booloperator==(System.Delegatex,System.Delegat
booloperator!=(System.Delegatex,System.Delegat
如果两个委托实例中有一个为null,则当且仅当它们都为null时相等。
如果两个委托具有不同的运行时类型,则它们永不相等。
如果两个委托实例都有调用列表(第
如果两个调用列表项都引用同一个静态方法,则这两个调用列表项相等。
如果两个调用列表项都引用同一个目标对象(引用相等运算符定义的目标对象)上的同一个非静态方法,则这两个
以被捕获外层变量实例的相同集(可能为空集)计算语义上相同的anonymous-function-e
相等运算符和null
x==nullnull==xx!=nullnull!=x
is运算符
如果E是匿名函数,则会发生编译时错误
如果E是方法组或null文本,或者如果E的类型是引用类型或可为null的类型并且E
否则,根据下列规则让D表示E的动态类型:
如果E的类型为引用类型,则D为E引用的实例的运行时类型。
如果E的类型为可以为null的类型,则D为该可以为null的类型的基础类型。
如果E的类型为不可以为null值的类型,则D为E的类型。
该操作的结果取决于D和T,具体如下:
如果T为引用类型,那么,在以下情况下结果为true:D和T为相同类型,或者D为引用类
如果T为可以为null的类型,那么,当D为T的基础类型时结果为true。
如果T为不可以为null值的类型,那么,如果D和T为相同类型,则结果为true。
否则,结果为false。
as运算符
存在从E到T的以下类型转换:标识(第6.1.1节)、隐式可以为null(第
E或T的类型为开放类型。
E为null文本。
EisT?(T)(E):(T)null
不同的只是:实际执行中E只计算一次。编译器应该优化EasT以最多执行一次动态类型检查,而
classX{
publicstringF(objecto){returnoasstrin
publicTG(objecto)whereT:Attribute{
publicUH(objecto){returnoasU;/
逻辑运算符
and-expression:equality-expressionand-expression
exclusive-or-expression:and-expressionexclusive-
inclusive-or-expression:exclusive-or-expressioni
整数逻辑运算符
intoperator&(intx,inty);uintoperator&(uint
intoperator|(intx,inty);uintoperator|(uint
intoperator^(intx,inty);uintoperator^(uint
枚举逻辑运算符
Eoperator&(Ex,Ey);Eoperator|(Ex,Ey);E
布尔逻辑运算符
booloperator&(boolx,booly);
booloperator|(boolx,booly);
booloperator^(boolx,booly);
可以为null的布尔逻辑运算符
bool?operator&(bool?x,bool?y);
bool?operator|(bool?x,bool?y);
x
y
x&y
x|y
true
true
true
true
true
false
false
true
true
null
null
true
false
true
false
true
false
false
false
false
false
null
false
null
null
true
null
true
null
false
false
null
null
null
null
null
条件逻辑运算符
conditional-and-expression:inclusive-or-expressio
conditional-or-expression:conditional-and-express
x&&y运算对应于x&y运算,但仅当x不为false时才计算y。
x||y运算对应于x|y运算,但仅当x不为true时才计算y。
如果重载决策未能找到单个最佳运算符,或者重载决策选择一个预定义的整数逻辑运算符,则发生编译时错误。
否则,如果选定的运算符是一个预定义的布尔逻辑运算符(第
否则,选定的运算符为用户定义的运算符,且运算按第
布尔条件逻辑运算符
运算x&&y的求值过程相当于x?y:false。换言之,首先计算x并将其转换为
运算x||y的求值过程相当于x?true:y。换言之,首先计算x并将其转换为
用户定义的条件逻辑运算符
选定运算符的返回类型和每个参数的类型都必须为T。换言之,该运算符必须计算类型为T的两个操作数的
T必须包含关于operatortrue和operatorfalse的声明。
x&&y运算按T.false(x)?x:T.&(x,y)进行计算,其中T.fa
x||y运算按T.true(x)?x:T.|(x,y)进行计算,其中T.tru
空合并运算符
null-coalescing-expression:conditional-or-express
如果A不是可以为null的类型或引用类型,则会发生编译时错误。
如果A是可为null的类型并且存在从b到A0的隐式转换,则结果类型为A0。在运行时
否则,如果存在从b到A的隐式转换,则结果类型为A。在运行时,首先计算a。如果a不为
否则,如果b具有类型B并且存在从A0到B的隐式转换,则结果类型为B。在运行时,首先
否则,a和b不兼容,并发生编译时错误。
条件运算符
conditional-expression:null-coalescing-expression
如果X和Y的类型相同,则此类型为该条件表达式的类型。
否则,如果存在从X到Y的隐式转换(第
否则,如果存在从Y到X的隐式转换(第
否则,无法确定条件表达式的类型,且发生编译时错误。
首先计算b,并确定b的bool值:
如果存在从b的类型到bool的隐式转换,则执行该隐式转换以产生bool值。
否则,调用b的类型中定义的operatortrue以产生bool值。
如果以上步骤产生的bool值为true,则计算x并将其转换为条件表达式的类型,且这成为条件
否则,计算y并将其转换为条件表达式的类型,且这成为条件表达式的结果。
匿名函数表达式
lambda-expression:anonymous-function-signature
anonymous-method-expression:delegateexplicit-a
anonymous-function-signature:explicit-anonymous-f
explicit-anonymous-function-signature:(explici
explicit-anonymous-function-parameter-listexplici
explicit-anonymous-function-parameter:anonymous-f
anonymous-function-parameter-modifier:refout
implicit-anonymous-function-signature:(implici
implicit-anonymous-function-parameter-listimplici
implicit-anonymous-function-parameter:identifier
anonymous-function-body:expressionblock
(param)=>expr
param=>expr
x=>x+1//Implicitlytyped,expression
x=>{returnx+1;}//Implicitlytyped,st
(intx)=>x+1//Explicitlytyped,expres
(intx)=>{returnx+1;}//Explicitlytyped
(x,y)=>x*y//Multipleparameters
()=>Console.WriteLine()//Noparameters
delegate(intx){returnx+1;}//Anonymousme
delegate{return1+1;}//Parameterlistom
anonymous-method-expressions允许完全省略参数列表,从而可以转换为任何值
lambda-expressions允许省略和推断参数类型,而anonymous-method-
lambda-expression体可以是表达式也可以是语句块,而anonymous-metho
由于仅lambda-expressions可以有expression体,因此anonymo
匿名函数签名
匿名函数体
如果匿名函数包括签名,则签名中指定的参数可在该函数体中使用。如果匿名函数没有签名,则它可转换为带有参
除了在最近的封闭匿名函数签名(如果存在)中指定的ref或out参数外,该函数体访问其他re
当this的类型为结构类型时,该函数体访问this将导致编译时错误。无论访问是显式(如th
该函数体可访问匿名函数的外层变量(第
该函数体包含目标在该函数体之外或该函数体之内所包含的匿名函数的goto语句、break语句或
该函数体中的return语句从最近的封闭匿名函数调用中返回控制,而不是从封闭函数成员中返回。re
重载决策
classItemList:List{publicintSum(Func
publicdoubleSum(Funcselector){
classDetail{publicintUnitCount;publicdo
voidComputeSums(){ItemListorderDetai
外层变量
捕获的外层变量
usingSystem;
delegateintD();
classTest{staticDF(){intx=0;Dr
staticvoidMain(){Dd=F();Console.Wr
123
局部变量实例化
staticvoidF(){for(inti=0;i<3;i++){
staticvoidF(){intx;for(inti=0;i<3
usingSystem;
delegatevoidD();
classTest{staticD[]F(){D[]result=ne
staticvoidMain(){foreach(DdinF())d()
135
staticD[]F(){D[]result=newD[3];intx;
555
staticD[]F(){D[]result=newD[3];for(i
333
staticD[]F(){D[]result=newD[3];intx
112131
usingSystem;
delegatevoidSetter(intvalue);
delegateintGetter();
classTest{staticvoidMain(){intx=0;
510
匿名函数表达式的计算
查询表达式
query-expression:from-clausequery-body
from-clause:fromtypeoptidentifierinex
query-body:query-body-clausesoptselect-or-grou
query-body-clauses:query-body-clausequery-body-c
query-body-clause:from-clauselet-clausewhere-cl
let-clause:letidentifier=expression
where-clause:whereboolean-expression
join-clause:jointypeoptidentifierinexpres
join-into-clause:jointypeoptidentifierine
orderby-clause:orderbyorderings
orderings:orderingorderings,ordering
ordering:expressionordering-directionopt
ordering-direction:ascendingdescending
select-or-group-clause:select-clausegroup-clause
select-clause:selectexpression
group-clause:groupexpressionbyexpression
query-continuation:intoidentifierquery-body
查询表达式中的多义性
查询表达式转换
带有延续部分的select和GroupBy子句
from…intox…
fromxin(from…)…
fromcincustomersgroupcbyc.Countryintogse
fromginfromcincustomersgroupcbyc.Cou
customers.GroupBy(c=>c.Country).Select(g=>ne
显式范围变量类型
fromTxine
fromxin(e).Cast()
joinTxineonk1equalsk2
joinxin(e).Cast()onk1equalsk2
fromCustomercincustomerswherec.City=="Lond
fromcincustomers.Cast()wherec.City
customers.Cast().Where(c=>c.City==
简并查询表达式
fromxineselectx
(e).Select(x=>x)
fromcincustomersselectc
customers.Select(c=>c)
from、let、where、join和orderby子句
fromx1ine1fromx2ine2selectv
(e1).SelectMany(x1=>e2,(x1,x2)=>v)
fromx1ine1fromx2ine2…
from*in(e1).SelectMany(x1=>e2,(x1,x
fromxinelety=f…
from*in(e).Select(x=>new{x,y=f}
fromxinewheref…
fromxin(e).Where(x=>f)…
fromx1ine1joinx2ine2onk1equalsk2select
(e1).Join(e2,x1=>k1,x2=>k2,(x1,x
fromx1ine1joinx2ine2onk1equalsk2…
from*in(e1).Join(e2,x1=>k1,x2=>k
fromx1ine1joinx2ine2onk1equalsk2intog
(e1).GroupJoin(e2,x1=>k1,x2=>k2,(x
fromx1ine1joinx2ine2onk1equalsk2intog
from*in(e1).GroupJoin(e2,x1=>k1,x2
fromxineorderbyk1,k2,…,kn…
fromxin(e).OrderBy(x=>k1).ThenBy(
fromcincustomersfromoinc.Ordersselectnew
customers.SelectMany(c=>c.Orders,(c,o)=>n
fromcincustomersfromoinc.Ordersorderbyo.T
from*incustomers.SelectMany(c=>c.Orders,(
customers.SelectMany(c=>c.Orders,(c,o)=>new
fromoinorderslett=o.Details.Sum(d=>d.Unit
from*inorders.Select(o=>new{o,t=o.Det
orders.Select(o=>new{o,t=o.Details.Sum(d=
fromcincustomersjoinoinordersonc.Customer
customers.Join(orders,c=>c.CustomerID,o=>o.C
fromcincustomersjoinoinordersonc.Customer
from*incustomers.GroupJoin(orders,c=>c.Cu
customers.GroupJoin(orders,c=>c.CustomerID,o
fromoinordersorderbyo.Customer.Name,o.Total
orders.OrderBy(o=>o.Customer.Name).ThenByDesce
select子句
fromxineselectv
(e).Select(x=>v)
(e)
fromcincustomers.Where(c=>c.City==“London”)
customers.Where(c=>c.City==“London”)
GroupBy子句
fromxinegroupvbyk
(e).GroupBy(x=>k,x=>v)
(e).GroupBy(x=>k)
fromcincustomersgroupc.Namebyc.Country
customers.GroupBy(c=>c.Country,c=>c.Name)
透明标识符
当透明标识符以匿名函数的参数形式出现时,关联的匿名类型的成员将自动位于匿名函数体的范围中。
当带有透明标识符的成员位于范围中时,该成员的各个成员也将位于该范围中。
当透明标识符以匿名对象初始值设定项中的成员声明符的形式出现时,它将引入带有透明标识符的成员。
fromcincustomersfromoinc.Ordersorderbyo.T
from*incustomers.SelectMany(c=>c.Orders,(
customers.SelectMany(c=>c.Orders,(c,o)=>new
customers.SelectMany(c=>c.Orders,(c,o)=>new
fromcincustomersjoinoinordersonc.Customer
from*incustomers.Join(orders,c=>c.Custome
customers.Join(orders,c=>c.CustomerID,o=>o.
customers.Join(orders,c=>c.CustomerID,o=>o.
查询表达式模式
delegateRFunc(T1arg1);
delegateRFunc(T1arg1,T2arg2);
classC{publicCCast();}
classC:C{publicCWhere(Func
publicCSelect(Funcselector);
publicCSelectMany(Func>selecto
publicCJoin(Cinner,Funcou
publicCGroupJoin(Cinner,Func
publicOOrderBy(FunckeySelector);
publicOOrderByDescending(FunckeySe
publicC>GroupBy(FunckeySelecto
publicC>GroupBy(FunckeySelec
classO:C{publicOThenBy(Func
publicOThenByDescending(FunckeySel
classG:C{publicKKey{get;}}
赋值运算符
assignment:unary-expressionassignment-operator
assignment-operator:=+=-=*=/=%=&=|=^=<<=
简单赋值
如果x属于变量:
计算x以产生变量。
计算y,必要时还需通过隐式转换(第
如果x给定的变量是reference-type的数组元素,则执行运行时检查以确保为y计算
y的计算和转换后所产生的值存储在x的计算所确定的位置中。
如果x属于属性或索引器访问:
计算与x关联的实例表达式(如果x不是static)和参数列表(如果x是索引器访问),结
计算y,必要时还需通过隐式转换(第
调用x的set访问器,并将y的上述结果值作为该访问器的value参数。
string[]sa=newstring[10];object[]oa=sa;
oa[0]=null;//Okoa[1]="Hello";//Ok
structPoint{intx,y;
publicPoint(intx,inty){this.x=x;t
publicintX{get{returnx;}set{x=
publicintY{get{returny;}set{y=
structRectangle{Pointa,b;
publicRectangle(Pointa,Pointb){this.a=
publicPointA{get{returna;}set{a
publicPointB{get{returnb;}set{b
Pointp=newPoint();p.X=100;p.Y=100;Recta
Rectangler=newRectangle();r.A.X=10;r.A.Y=
复合赋值
如果选定的运算符的返回类型可“隐式”转换为x的类型,则运算按x=xopy计算,但x
否则,如果选定运算符是预定义的运算符,选定运算符的返回类型可“显式”转换为x的类型,并且y可
否则,复合赋值无效,且发生编译时错误。
byteb=0;charch='\0';inti=0;
b+=1;//Okb+=1000;//Error,b=1000n
ch+=1;//Error,ch=1notpermittedch+=(
int?i=0;i+=1;//Ok
事件赋值
计算事件访问的实例表达式(如果有)。
计算+=或-=运算符的右操作数,如果需要,通过隐式转换(第
调用该事件的事件访问器,所需的参数列表由右操作数(经过计算和必要的转换后)组成。如果运算符为+=,
表达式
expression:non-assignment-expressionassignment
non-assignment-expression:conditional-expression
常量表达式
constant-expression:expression
文本(包括null)
对类和结构类型的const成员的引用
对枚举类型的成员的引用
对const参数或局部变量的引用
带括号的子表达式,其自身是常量表达式
强制转换表达式(前提是目标类型为以上列出的类型之一)
checked和unchecked表达式
默认值表达式
预定义的一元运算符+、–、!和~
预定义的二元运算符+、–、*、/、%、<<、>>、&、|、^、&&、||、==、!=、<、>、<
条件运算符?:
标识转换
数值转换
枚举转换
常量表达式转换
隐式和显式引用转换,条件是转换的源是计算结果为Null值的常量表达式。
classC{constobjecti=5;//error:boxin
常量声明(第
枚举成员声明(第
switch语句的case标签(第
gotocase语句(第
包含初始值设定项的数组创建表达式(第
属性(第17
布尔表达式
boolean-expression:expression
语句
statement:labeled-statementdeclaration-statement
embedded-statement:blockempty-statementexpressi
voidF(boolb){if(b)inti=44;}
结束点和可到达性
voidF(){Console.WriteLine("reachable");got
voidF(){constinti=1;if(i==2)Consol
voidF(){inti=1;if(i==2)Console.Writ
voidF(intx){Console.WriteLine("start");if
第一个Console.WriteLine表达式语句是可到达的,原因是F方法的块是可到达的。
第一个Console.WriteLine表达式语句的结束点是可到达的,原因是该语句是可到达的。
if语句是可到达的,原因是第一个Console.WriteLine表达式语句的结束点是可到达的
第二个Console.WriteLine表达式语句是可到达的,原因是if语句的布尔表达式不是
由于switch语句不允许一个switch节“贯穿”到下一个switch节,因此如果一个
如果一个计算某个值的函数成员的块的结束点是可到达的,则会出现编译时错误。如果发生此错误,则通常表明该
块
block:{statement-listopt}
如果块是空的,控制转到块的结束点。
如果块不是空的,控制转到语句列表。当(如果)控制到达语句列表的结束点时,控制转到块的结束点。
迭代器块中出现return语句时也会产生编译时错误(但是允许yieldreturn语句)。
迭代器块包含不安全的上下文(第18.1节)时将导致编译时错误。迭代器块总是定义安全的上下文,即使
语句列表
statement-list:statementstatement-liststateme
该语句是第一个语句且语句列表本身是可到达的。
前一个语句的结束点是可到达的。
该语句本身是一个标记语句,并且该标签已被一个可到达的goto语句引用。
空语句
empty-statement:;
boolProcessMessage(){...}
voidProcessMessages(){while(ProcessMessage()
voidF(){...
if(done)gotoexit;...
exit:;}
标记语句
labeled-statement:identifier:statement
intF(intx){if(x>=0)gotox;x=-x;x
声明语句
declaration-statement:local-variable-declaration
局部变量声明
local-variable-declaration:local-variable-type
local-variable-type:typevar
local-variable-declarators:local-variable-declara
local-variable-declarator:identifieridentifier
local-variable-initializer:expressionarray-initi
local-variable-declaration不能包括多个local-variable-d
local-variable-declarator必须包括一个local-variable-in
local-variable-initializer必须为expression。
初始值设定项expression必须具有编译时类型。
初始值设定项expression不能引用声明的变量本身。
varx;//Error,noinitializertoinfertype
voidF(){intx=1,y,z=x*2;}
voidF(){intx;x=1;inty;intz;z=x
vari=5;vars="Hello";vard=1.0;varnumbe
inti=5;strings="Hello";doubled=1.0;int
局部常量声明
local-constant-declaration:consttypeconstan
constant-declarators:constant-declaratorconstant
constant-declarator:identifier=constant-exp
表达式语句
expression-statement:statement-expression;
statement-expression:invocation-expressionobject
选择语句
selection-statement:if-statementswitch-statement
if语句
if-statement:if(boolean-expression)em
if(x)if(y)F();elseG();
if(x){if(y){F();}else{G();
计算boolean-expression(第
如果布尔表达式产生true,则控制转到第一个嵌入语句。当(如果)控制到达那条语句的结束点时,控制将
如果布尔表达式产生false且如果存在else部分,则控制转到第二个嵌入语句。当(如果)控制
如果布尔表达式产生false且如果不存在else部分,则控制转到if语句的结束点。
switch语句
switch-statement:switch(expression)sw
switch-block:{switch-sectionsopt}
switch-sections:switch-sectionswitch-sections
switch-section:switch-labelsstatement-list
switch-labels:switch-labelswitch-labelsswitch
switch-label:caseconstant-expression:defau
计算switch表达式并将其转换为主导类型。
如果在该switch语句的case标签中,有一个指定的常量恰好等于switch表达式的值
如果在该switch语句的case标签中,指定的常量都不等于switch表达式的值,且如
如果在该switch语句的case标签中,指定的常量都不等于switch表达式的值,且如
switch(i){case0:CaseZero();break;case1
switch(i){case0:CaseZero();case1:CaseZ
switch(i){case0:CaseZero();gotocase1;
switch(i){case0:CaseZero();break;case1
switch(i){default:CaseAny();break;case1
switch(i){case0:while(true)F();case1:
voidDoCommand(stringcommand){switch(command
switch表达式是一个非常量值。
switch表达式是一个与该switch节中的某个case标签匹配的常量值。
switch表达式是一个不与任何case标签匹配的常量值,且该switch节包含defa
该switch节的某个switch标签由一个可到达的gotocase或gotode
switch语句包含一个可到达的break语句(它用于退出switch语句)。
switch语句是可到达的,switch表达式是非常量值,并且不存在default标签。
switch语句是可到达的,switch表达式是不与任何case标签匹配的常量值,并且不存在
迭代语句
iteration-statement:while-statementdo-statement
while语句
while-statement:while(boolean-expression
计算boolean-expression(第
如果布尔表达式产生true,控制将转到嵌入语句。当(如果)控制到达嵌入语句的结束点(可能是通过执行
如果布尔表达式产生false,控制将转到while语句的结束点。
while语句包含一个可到达的break语句(它用于退出while语句)。
while语句是可到达的且布尔表达式不具有常量值true。
do语句
do-statement:doembedded-statementwhile(
控制转到嵌入语句。
当(如果)控制到达嵌入语句的结束点(可能是由于执行了一个continue语句)时,计算bool
do语句包含一个可到达的break语句(它用于退出do语句)。
嵌入语句的结束点是可到达的且布尔表达式不具有常量值true。
for语句
for-statement:for(for-initializeropt;
for-initializer:local-variable-declarationstatem
for-condition:boolean-expression
for-iterator:statement-expression-list
statement-expression-list:statement-expressionst
如果存在for-initializer,则按变量初始值设定项或语句表达式的编写顺序执行它们。此步骤
如果存在for-condition,则计算它。
如果不存在for-condition或如果计算产生true,控制将转到嵌入语句。当(如果)控制
如果存在for-condition,且计算产生false,控制将转到for语句的结束点。
for语句是可到达的且不存在for-condition。
for语句是可到达的,并且存在一个for-condition,它不具有常量值false。
for语句包含一个可到达的break语句(它用于退出for语句)。
for语句是可到达的,并且存在一个for-condition,它不具有常量值true。
foreach语句
foreach-statement:foreach(local-variable-ty
如果expression的类型X是数组类型,则存在从X到System.Collecti
否则,确定类型X是否具有相应的GetEnumerator方法:
在带有标识符GetEnumerator和不带类型参数的类型X上执行成员查找。如果成员查找没有
使用产生的方法组和空的参数列表执行重载决策。如果重载决策产生了不适用的方法、多义性或者单个最佳方法(
如果GetEnumerator方法的返回类型E不是类、结构或接口类型,则将产生错误,并且不再
在带有标识符Current和不带类型参数的E上执行成员查找。如果成员查找没有产生匹配项,结果
在带有标识符MoveNext和不带类型参数的E上执行成员查找。如果成员查找没有产生匹配项,结
使用空的参数列表对方法组执行重载决策。如果重载决策产生了不适用的方法、多义性、单个最佳方法(但该方法
集合类型(collectiontype)为X,枚举器类型(enumeratortype)
否则,检查可枚举的接口:
如果恰好有一种类型T,以致存在从X到接口System.Collections.Generic
否则,如果存在多个此种类型T,则将产生错误并且不再执行进一步的操作。
否则,如果存在从X到System.Collections.IEnumerable接口的隐式转
否则,将产生错误并且不再执行进一步的操作。
如果存在从E到System.IDisposable接口的隐式转换,则
如果E为不可以为null值的类型,则finally子句扩展到下面子句的语义等效项:
否则finally子句扩展到下面子句的语义等效项:
否则,如果E是密封类型,finally子句将扩展为一个空块:
否则,finally子句将扩展为:
局部变量d对于任何用户代码均不可见或不可访问。尤其是,它不会与范围包括该finally块的其
usingSystem;
classTest{staticvoidMain(){double[,]v
foreach(doubleelementValueinvalues)Con
Console.WriteLine();}}
1.22.33.44.55.66.77.88.9
int[]numbers={1,3,5,7,9};foreach(varn
跳转语句
jump-statement:break-statementcontinue-statement
usingSystem;
classTest{staticvoidMain(){while(true
BeforebreakInnermostfinallyblockOutermostfin
break语句
break-statement:break;
如果break语句退出一个或多个具有关联finally块的try块,则控制最初会被转到最
控制转到break语句的目标。
continue语句
continue-statement:continue;
如果continue语句退出一个或多个具有关联finally块的try块,则控制最初会被
控制转到continue语句的目标。
goto语句
goto-statement:gotoidentifier;gotocase
usingSystem;
classTest{staticvoidMain(string[]args){
foreach(stringstrinargs){introw,col
Console.WriteLine("{0}notfound",str);c
如果goto语句退出一个或多个具有关联finally块的try块,则控制最初会被转到最里
控制转到goto语句的目标。
return语句
return-statement:returnexpressionopt;
如果return语句指定一个表达式,则计算该表达式,并将结果隐式转换为包含它的函数成员的返回类型
如果return语句由一个或多个具有关联finally块的try块封闭,则控制最初转到最
控制返回到包含它们的函数成员的调用方。
throw语句
throw-statement:throwexpressionopt;
在当前函数成员中,检查每个封闭着引发点的try语句。对于每个语句S(按从最里层的try语句
如果S的try块封闭着引发点,并且如果S具有一个或多个catch子句,则按其出现的顺
否则(如果找不到匹配的catch子句),如果S的try块或catch块封闭着引发点并
如果在当前函数成员调用中没有找到异常处理程序,则终止对该函数成员的调用。然后,为该函数成员的调用方重
如果上述异常处理终止了当前线程中的所有函数成员调用,这表明此线程没有该异常的处理程序,那么线程本身将
try语句
try-statement:tryblockcatch-clausestryb
catch-clauses:specific-catch-clausesgeneral-ca
specific-catch-clauses:specific-catch-clausespec
specific-catch-clause:catch(class-typeid
general-catch-clause:catchblock
finally-clause:finallyblock
一个try块后接一个或多个catch块。
一个try块后接一个finally块。
一个try块后接一个或多个catch块,后面再跟一个finally块。
usingSystem;
classTest{staticvoidF(){try{G();
staticvoidG(){thrownewException("G");
staticvoidMain(){try{F();}c
ExceptioninF:GExceptioninMain:G
ExceptioninF:GExceptioninMain:F
控制转到try块。
当(如果)控制到达try块的结束点时:
如果该try语句具有finally块,则执行finally块。
控制转到try语句的结束点。
如果在try块执行期间有一个异常传播到try语句:
按catch子句出现的顺序(如果有)逐个对其进行检查,以找到一个合适的异常处理程序。第一个指定了
如果匹配的catch子句声明一个异常变量,则异常对象被赋给该异常变量。
控制转到匹配的catch块。
当(如果)控制到达catch块的结束点时:
如果该try语句具有finally块,则执行finally块。
控制转到try语句的结束点。
如果在try块执行期间有一个异常传播到catch语句:
如果该try语句具有finally块,则执行finally块。
该异常就传播到更外面一层(封闭)的try语句。
如果该try语句没有catch子句或如果没有与异常匹配的catch子句:
如果该try语句具有finally块,则执行finally块。
该异常就传播到更外面一层(封闭)的try语句。
try块的结束点是可到达的或者至少一个catch块的结束点是可到达的。
如果存在一个finally块,此finally块的结束点是可到达的。
checked语句和unchecked语句
checked-statement:checkedblock
unchecked-statement:uncheckedblock
lock语句
lock-statement:lock(expression)embedd
lock(x)...
System.Threading.Monitor.Enter(x);try{...}f
classCache{privatestaticobjectsynchronizat
publicstaticvoidAdd(objectx){lock(Cac
publicstaticvoidRemove(objectx){lock(C
using语句
using-statement:using(resource-acquisition
resource-acquisition:local-variable-declaratione
using(ResourceTyperesource=expression)stateme
{ResourceTyperesource=expression;try{
{ResourceTyperesource=expression;try{
using(expression)statement
using(ResourceTyper1=e1,r2=e2,...,rN=eN
using(ResourceTyper1=e1)using(ResourceType
usingSystem;usingSystem.IO;
classTest{staticvoidMain(){using(Text
using(TextReaderr=File.OpenText("log.txt"))
}}}
yield语句
yield-statement:yieldreturnexpression;y
如果yield语句(包括两种形式)出现在method-body、operator-body或
如果yield语句(包括两种形式)出现在匿名函数内部,则会引起编译时错误。
如果yield语句(包括两种形式)出现在try语句的finally子句之内,则会引起编译
如果yieldreturn语句出现在包含任何catch子句的try语句内的任何位置,则
delegateIEnumerableD();
IEnumeratorGetEnumerator(){try{yiel
try{yieldreturn3;//Error,yieldreturn
Dd=delegate{yieldreturn5;//Error,
intMyMethod(){yieldreturn1;//Error,wro
计算该语句中给出的表达式,隐式转换为产生类型,并赋给枚举器对象的Current属性。
迭代器块的执行被挂起。如果yieldreturn语句在一个或多个try块内,则与之关联的
枚举器对象的MoveNext方法向其调用方返回true,指示枚举器对象成功前进到下一项。
如果yieldbreak语句包含在一个或多个具有关联finally块的try块中,则控
控制返回给迭代器块的调用方。这是枚举器对象的MoveNext方法或Dispose方法。
命名空间
编译单元
compilation-unit:extern-alias-directivesoptusi
classA{}
classB{}
命名空间声明
namespace-declaration:namespacequalified-ident
qualified-identifier:identifierqualified-identif
namespace-body:{extern-alias-directivesoptu
namespaceN1.N2{classA{}
classB{}}
namespaceN1{namespaceN2{classA{}
classB{}}}
namespaceN1.N2{classA{}}
namespaceN1.N2{classB{}}
Extern别名
extern-alias-directives:extern-alias-directivee
extern-alias-directive:externaliasidentifie
externaliasX;externaliasY;
classTest{X::N.Aa;X::N.Bb1;Y::N.Bb2;
using指令
using-directives:using-directiveusing-directives
using-directive:using-alias-directiveusing-names
using别名指令
using-alias-directive:usingidentifier=na
namespaceN1.N2{classA{}}
namespaceN3{usingA=N1.N2.A;
classB:A{}}
namespaceN3{usingR=N1.N2;
classB:R.A{}}
namespaceN3{classA{}}
namespaceN3{usingA=N1.N2.A;//Error,Aa
namespaceN3{usingR=N1.N2;}
namespaceN3{classB:R.A{}//Error,Runk
usingR=N1.N2;
namespaceN3{classB:R.A{}}
namespaceN3{classC:R.A{}}
usingR=N1.N2;
namespaceN3{classR{}
classB:R.A{}//Error,RhasnomemberA}
namespaceN1.N2{}
namespaceN3{externaliasE;
usingR1=E.N;//OK
usingR2=N1;//OK
usingR3=N1.N2;//OK
usingR4=R2.N2;//Error,R2unknown}
namespaceN1.N2{classA{}}
namespaceN3{usingR1=N1;usingR2=N1.N2
classB{N1.N2.Aa;//referstoN1.N2.A
namespaceN1{classA{classB{}}
namespaceN2{usingW=N1.A;//Error,canno
usingX=N1.A.B;//Error,cannotnameunboun
usingY=N1.A;//Ok,cannameclosedcon
usingZ=N1.A;//Error,usingaliascann
Using命名空间指令
using-namespace-directive:usingnamespace-name
namespaceN1.N2{classA{}}
namespaceN3{usingN1.N2;
classB:A{}}
namespaceN1.N2{classA{}}
namespaceN3{usingN1;
classB:N2.A{}//Error,N2unknown}
namespaceN1.N2{classA{}
classB{}}
namespaceN3{usingN1.N2;
classA{}}
namespaceN1{classA{}}
namespaceN2{classA{}}
namespaceN3{usingN1;
usingN2;
classB:A{}//Error,Aisambiguous}
namespaceN3{usingN1;
usingN2;
usingA=N1.A;
classB:A{}//AmeansN1.A}
命名空间成员
namespace-member-declarations:namespace-member-de
namespace-member-declaration:namespace-declaratio
类型声明
type-declaration:class-declarationstruct-declara
在编译单元或命名空间中声明的类型可以具有public或internal访问属性。默认为in
在类中声明的类型可以具有public、protectedinternal、protected、i
在结构中声明的类型可以具有public、internal或private访问属性。默认为p
命名空间别名限定符
qualified-alias-member:identifier::identifi
N::I,其中N和I表示标识符。(在此情况下,K视作0。)
如果N为标识符global,则搜索全局命名空间以查找I:
如果全局命名空间包含名为I的命名空间,并且K为0,则qualified-alias-me
否则,如果该全局命名空间包含名为I的非泛型类型,并且K为0,则qualified-ali
否则,如果该全局命名空间包含名为I的带有K 个类型形参的类型,则qualified-alia
否则,qualified-alias-member是不确定的,并发生编译时错误。
否则,从直接包含qualified-alias-member的命名空间声明(第9.2节)开始
如果命名空间声明或编译单元包含将N与某个类型相关联的using-alias-directive
否则,如果命名空间声明或编译单元包含将N与某个命名空间相关联的extern-alias-di
如果与N关联的命名空间包含名为I的命名空间,并且K为0,则qualified-ali
否则,如果与N关联的命名空间包含名为I的非泛型类型,并且K为0,则qualified
否则,如果与N关联的命名空间包含名为I的带有K 个类型形参的类型,则qualified-
否则,qualified-alias-member即为未定义,并发生编译时错误。
否则,qualified-alias-member即为未定义,并发生编译时错误。
别名的唯一性
namespaceN{publicclassA{}
publicclassB{}}
namespaceN{usingA=System.IO;
classX{A.Streams1;//Error,Aisamb
A::Streams2;//Ok}}
类
类声明
class-declaration:attributesoptclass-modifiers
类修饰符
class-modifiers:class-modifierclass-modifiers
class-modifier:newpublicprotectedinternalpriv
抽象类
抽象类不能直接实例化,并且对抽象类使用new运算符会导致编译时错误。虽然一些变量和值在编译时的类
允许(但不要求)抽象类包含抽象成员。
抽象类不能被密封。
abstractclassA{publicabstractvoidF();}
abstractclassB:A{publicvoidG(){}}
classC:B{publicoverridevoidF(){//ac
密封类
静态类
静态类不可包含sealed或abstract修饰符。但是,注意,因为无法实例化静态类或从静态
静态类不可包括class-base规范(第
静态类只能包含静态成员(第
静态类不能含有声明的可访问性为protected或protectedinternal的成员
引用静态类类型
namespace-or-type-name是T.I形式的namespace-or-type
namespace-or-type-name是typeof(T)形式的typeof-expr
primary-expression为E.I形式的member-access(第7.5.4
分部修饰符
类型形参
type-parameter-list:
type-parameters:attributesopttype-parameterty
type-parameter:identifier
类基本规范
class-base::class-type:interface-type-list
interface-type-list:interface-typeinterface-type
classExtend:V{}//Error,typeparameteru
基类
classA{}
classB:A{}
classB{...}
classG:B{...}
classA{
publicclassB{}
}
classC:A{}
classA{...}
classB:A{...}
classC:B>{...}
classD:C{...}
classA:A{}
classA:B{}
classB:C{}
classC:A{}
classA:B.C{}
classB:A{publicclassC{}}
classA{classB:A{}}
sealedclassA{}
classB:A{}//Error,cannotderivefromasea
接口实现
类型形参约束
type-parameter-constraints-clauses:type-parameter
type-parameter-constraints-clause:wheretype-pa
type-parameter-constraints:primary-constraintsec
primary-constraint:class-typeclassstruct
secondary-constraints:interface-typetype-paramet
constructor-constraint:new()
该类型必须是类类型。
该类型一定不能是sealed。
该类型不能是以下类型之一:System.Array、System.Delegate、System.E
该类型一定不能是object。由于所有类型都派生自object,允许这样的约束没有任何作用。
给定的类型形参至多只能有一个约束可以是类类型。
该类型必须是接口类型。
不能在给定的where子句中多次指定某个类型。
该类型必须是类型形参。
不能在给定的where子句中多次指定某个类型。
如果类型形参T用作类型形参S的约束,则S依赖(dependon)T。
如果类型形参S依赖类型形参T,并且T依赖类型形参U,则S依赖(dependon)
T一定不能具有值类型约束。否则,T被有效地密封,使得S将被强制为与T相同的类型,从而消除
如果S具有值类型约束,则T不能具有class-type约束。
如果S具有class-type约束A,T具有class-type约束B,则必须存在
如果S还依赖类型形参U,并且U具有class-type约束A,T具有class-
interfaceIPrintable{voidPrint();}
interfaceIComparable{intCompareTo(Tvalue
interfaceIKeyProvider{
TGetKey();}
classPrinterwhereT:IPrintable{...}
classSortedListwhereT:IComparable{...}
classDictionarywhereK:IComparable
classCircularwhereS:TwhereT:S/
classSealedwhereS:TwhereT:struct
classA{...}
classB{...}
classIncompatwhereS:A,TwhereT:B
classStructWithClasswhereS:struct,T
如果T没有主要约束或类型形参约束,则其有效基类为object。
如果T具有值类型约束,则其有效基类为System.ValueType。
如果T具有class-type约束C,但是没有type-parameter约束,则其有
如果T没有class-type约束,但是有一个或多个type-parameter约束,则
如果T同时具有class-type约束和一个或多个type-parameter约束,则其
如果T具有引用类型约束,但是没有class-type约束,则其有效基类为object。
如果T没有secondary-constraints,则其有效接口集为空。
如果T具有interface-type约束,但是没有type-parameter约束,则
如果T没有interface-type约束,但是具有type-parameter约束,则
如果T同时具有interface-type约束和type-parameter约束,则其有
interfaceIPrintable{voidPrint();}
classPrinterwhereT:IPrintable{voidPrin
类体
class-body:{class-member-declarationsopt}
分部类型
属性
[Attr1,Attr2("hello")]partialclassA{}
[Attr3,Attr2("goodbye")]partialclassA{}
[Attr1,Attr2("hello"),Attr3,Attr2("goodbye")]c
修饰符
类型形参和约束
partialclassDictionarywhereK:IComparab
partialclassDictionarywhereV:IPersista
partialclassDictionary{...}
基类
基接口
partialclassC:IA,IB{...}
partialclassC:IC{...}
partialclassC:IA,IB{...}
partialclassX{intIComparable.CompareTo(obje
partialclassX:IComparable{...}
成员
partialclassA{intx;//Error,cannot
partialclassInner//Ok,Innerisapartialt
partialclassA{intx;//Error,cannotd
partialclassInner//Ok,Innerisapartial
分部方法
partialclassCustomer{stringname;
publicstringName{
get{returnname;}
set{OnNameChanging(value);name=val
}
partialvoidOnNameChanging(stringnewName);
partialvoidOnNameChanged();}
classCustomer{stringname;
publicstringName{
get{returnname;}
set{name=value;}}}
partialclassCustomer{partialvoidOnNameChan
partialvoidOnNameChanged(){Console.Writ
classCustomer{stringname;
publicstringName{
get{returnname;}
set{OnNameChanging(value);name=val
}
voidOnNameChanging(stringnewName){Conso
voidOnNameChanged(){Console.WriteLine(“C
名称绑定
namespaceN{usingList=System.Collections.Ar
partialclassA{Listx;//xhastype
namespaceN{usingList=Widgets.LinkedList;
partialclassA{Listy;//yhastype
类成员
class-member-declarations:class-member-declaratio
class-member-declaration:constant-declarationfie
常量,表示与该类相关联的常量值(第
字段,即该类的变量(第
方法,用于实现可由该类执行的计算和操作(第
属性,用于定义一些命名特性以及与读取和写入这些特性相关的操作(第
事件,用于定义可由该类生成的通知(第
索引器,使该类的实例可按与数组相同的(语法)方式进行索引(第
运算符,用于定义表达式运算符,通过它对该类的实例进行运算(第
实例构造函数,用于实现初始化该类的实例所需的操作(第
析构函数,用于实现在永久地放弃该类的一个实例之前需要做些什么(第
静态构造函数,用于实现初始化该类自身所需的操作(第
类型,用于表示一些类型,它们是该类的局部类型(第
实例构造函数、静态构造函数和析构函数必须具有与直接包容它们的类相同的名称。所有其他成员的名称必须与该
常量、字段、属性、事件或类型的名称必须不同于在同一个类中声明的所有其他成员的名称。
方法的名称必须不同于在同一个类中声明的所有其他非方法的名称。此外,方法的签名(第
实例构造函数的签名必须不同于在同一类中声明的所有其他实例的签名,并且在同一类中声明的两个构造函数的签
索引器的签名必须不同于在同一个类中声明的所有其他索引器的签名。
运算符的签名必须不同于在同一个类中声明的所有其他运算符的签名。
实例类型
classA//instancetype:A{class
classC{}//instancetype:A.C}
classD{}//instancetype:D
构造类型的成员
classGen{publicT[,]a;
publicvoidG(inti,Tt,Gengt){...}
publicUProp{get{...}set{...}}
publicintH(doubled){...}}
publicint[,][]a;
publicvoidG(inti,int[]t,Gen
publicIComparableProp{get{...}set{.
publicintH(doubled){...}
classC{publicVf1;publicCf2=nul
publicC(Vx){this.f1=x;this.f2=thi
classApplication{staticvoidMain(){C
Cx2=newC(3.1415);Consol
继承
继承是可传递的。如果C从B派生,而B从A派生,那么C就会既继承在B中声明的成
派生类扩展它的直接基类。派生类能够在继承基类的基础上添加新的成员,但是它不能移除继承成员的定义。
实例构造函数、析构函数和静态构造函数是不可继承的,但所有其他成员是可继承的,无论它们所声明的可访问性
派生类可以通过声明具有相同名称或签名的新成员来隐藏(hide)(第
类的实例含有在该类中以及它的所有基类中声明的所有实例字段集,并且存在一个从派生类类型到它的任一基类类
类可以声明虚的方法、属性和索引器,而派生类可以重写这些函数成员的实现。这使类展示出“多态性行为”特征
classB{publicUF(longindex){...}}
classD:B{publicTG(strings){...}
new修饰符
访问修饰符
构成类型
静态成员和实例成员
在E.M形式的member-access(第
静态字段只标识一个要由给定的封闭类类型的所有实例共享的存储位置。无论对一个给定的封闭式类类型创建了多
静态函数成员(方法、属性、事件、运算符或构造函数)不能作用于具体的实例,在这类函数成员中引用thi
在E.M形式的member-access(第
类的每个实例分别包含一组该类的所有实例字段。
实例函数成员(方法、属性、索引器、实例构造函数或析构函数)作用于类的给定实例,此实例可以用this
classTest{intx;staticinty;
voidF(){x=1;//Ok,sameasthis.x=1
staticvoidG(){x=1;//Error,cannota
staticvoidMain(){Testt=newTest();
嵌套类型
usingSystem;
classA{classB{staticvoidF(){C
完全限定名
已声明可访问性
在类中声明的嵌套类型可以具有五种已声明可访问性(public、protectedinternal、
在结构中声明的嵌套类型可以具有三种已声明可访问性(public、internal或private
publicclassList{//Privatedatastructure
publicNode(objectdata,Nodenext){this.
privateNodefirst=null;privateNodelast=
//Publicinterface
publicvoidAddToFront(objecto){...}
publicvoidAddToBack(objecto){...}
publicobjectRemoveFromFront(){...}
publicobjectRemoveFromBack(){...}
publicintCount{get{...}}}
隐藏
usingSystem;
classBase{publicstaticvoidM(){Console
classDerived:Base{newpublicclassM{
classTest{staticvoidMain(){Derived.M.
this访问
usingSystem;
classC{inti=123;
publicvoidF(){Nestedn=newNested(this)
publicclassNested{Cthis_c;
publicNested(Cc){this_c=c;}
publicvoidG(){Console.WriteLine(this_c.
classTest{staticvoidMain(){Cc=newC
对包含类型的私有和受保护成员的访问
usingSystem;
classC{privatestaticvoidF(){Console.
publicclassNested{publicstaticvoidG
classTest{staticvoidMain(){C.Nested.G
usingSystem;
classBase{protectedvoidF(){Console.Wr
classDerived:Base{publicclassNested{
classTest{staticvoidMain(){Derived.Ne
泛型类中的嵌套类型
classOuter{classInner{publicst
staticvoidF(Tt){Outer.Inner.F
Outer.Inner.F(3,"abc");//Thist
Outer.Inner.F(t,"abc");//Error,Ou
classOuter{classInner//Valid,hides
保留成员名称
使基础的实现可以通过将普通标识符用作一个方法名称,从而对C#语言的功能进行get或set
使其他语言可以通过将普通标识符用作一个方法名称,对C#语言的功能进行get或set访问,
使保留成员名称的细节在所有的C#实现中保持一致,这有助于确保被一个符合本规范的编译器所接受的源程
为属性保留的成员名称
Tget_P();voidset_P(Tvalue);
usingSystem;
classA{publicintP{get{return123;}
classB:A{newpublicintget_P(){return
newpublicvoidset_P(intvalue){}}
classTest{staticvoidMain(){Bb=newB
123123456
为事件保留的成员名称
voidadd_E(Thandler);voidremove_E(Thandler);
为索引器保留的成员名称
Tget_Item(L);voidset_Item(L,Tvalue);
为析构函数保留的成员名称
voidFinalize();
常量
constant-declaration:attributesoptconstant-mod
constant-modifiers:constant-modifierconstant-mod
constant-modifier:newpublicprotectedinternalp
constant-declarators:constant-declaratorconstant
constant-declarator:identifier=constant-exp
classA{publicconstdoubleX=1.0,Y=2.0,
classA{publicconstdoubleX=1.0;public
classA{publicconstintX=B.Z+1;public
classB{publicconstintZ=A.Y+1;}
字段
field-declaration:attributesoptfield-modifiers
field-modifiers:field-modifierfield-modifiers
field-modifier:newpublicprotectedinternalpriv
variable-declarators:variable-declaratorvariable
variable-declarator:identifieridentifier=v
variable-initializer:expressionarray-initializer
classA{publicstaticintX=1,Y,Z=100;}
classA{publicstaticintX=1;publicstat
静态字段和实例字段
classC{staticintcount=0;
publicC(){count++;}
publicstaticintCount{get{returncount;
classApplication{staticvoidMain(){C
Cx2=newC();Console.Writ
Cx3=newC();Console.WriteLine(
只读字段
在用于引入该字段的variable-declarator中(通过在声明中包括一个variabl
对于实例字段,在包含字段声明的类的实例构造函数中;对于静态字段,在包含字段声明的类的静态构造函数中。
对常量使用静态只读字段
publicclassColor{publicstaticreadonlyColo
privatebytered,green,blue;
publicColor(byter,byteg,byteb){red=
常量和静态只读字段的版本控制
usingSystem;
namespaceProgram1{publicclassUtils{p
namespaceProgram2{classTest{staticvo
可变字段
读取一个可变字段称为可变读取(volatileread)。可变读取具有“获取语义”;也就是说,按
写入一个可变字段称为可变写入(volatilewrite)。可变写入具有“释放语义”;也就是说,
reference-type。
类型byte、sbyte、short、ushort、int、uint、char、float、boo
枚举基类型为byte、sbyte、short、ushort、int或uint的enum-t
usingSystem;usingSystem.Threading;
classTest{publicstaticintresult;publ
staticvoidThread2(){result=143;
staticvoidMain(){finished=false;
//RunThread2()inanewthreadnewThread(
//WaitforThread2tosignalthatithasares
result=143
字段初始化
usingSystem;
classTest{staticboolb;inti;
staticvoidMain(){Testt=newTest();
b=False,i=0
变量初始值设定项
usingSystem;
classTest{staticdoublex=Math.Sqrt(2.0);
staticvoidMain(){Testa=newTest();
x=1.4142135623731,i=100,s=Hello
usingSystem;
classTest{staticinta=b+1;staticint
staticvoidMain(){Console.WriteLine("a={
a=1,b=2
静态字段初始化
usingSystem;
classTest{staticvoidMain(){Console.W
publicstaticintF(strings){Console.Write
classA{publicstaticintX=Test.F("InitA")
classB{publicstaticintY=Test.F("InitB")
InitAInitB11
InitBInitA11
usingSystem;
classTest{staticvoidMain(){Console.Wri
publicstaticintF(strings){Console.Write
classA{staticA(){}
publicstaticintX=Test.F("InitA");}
classB{staticB(){}
publicstaticintY=Test.F("InitB");}
InitBInitA11
实例字段初始化
classA{intx=1;inty=x+1;//Error,
OLE_LINK1
方法
method-declaration:method-headermethod-body
method-header:attributesoptmethod-modifiersopt
method-modifiers:method-modifiermethod-modifiers
method-modifier:newpublicprotectedinternalpri
return-type:typevoid
member-name:identifierinterface-type.ident
method-body:block;
该声明包含一个由访问修饰符(第
该声明中所含的修饰符没有彼此相同的。
该声明最多包含下列修饰符中的一个:static、virtual和override。
该声明最多包含下列修饰符中的一个:new和override。
如果声明中包含abstract修饰符,则该声明不包含下列任何修饰符:static、virtual
如果声明中包含private修饰符,则该声明不包含下列任何修饰符:virtual、overrid
如果声明包含sealed修饰符,则该声明还包含override修饰符。
如果声明中包含partial修饰符,则该声明不包含下列任一修饰符:new、public、prot
方法形参
formal-parameter-list:fixed-parametersfixed-para
fixed-parameters:fixed-parameterfixed-parameters
fixed-parameter:attributesoptparameter-modifie
parameter-modifier:refoutthis
parameter-array:attributesoptparamsarray-ty
值形参,声明时不带任何修饰符。
引用形参,用ref修饰符声明。
输出形参,用out修饰符声明。
形参数组,用params修饰符声明。
值形参
引用形参
usingSystem;
classTest{staticvoidSwap(refintx,refint
staticvoidMain(){inti=1,j=2;Swa
i=2,j=1
classA{strings;
voidF(refstringa,refstringb){s="One
voidG(){F(refs,refs);}}
输出形参
usingSystem;
classTest{staticvoidSplitPath(stringpath,
staticvoidMain(){stringdir,name;Spl
c:\Windows\System\hello.txt
形参数组
赋予形参数组的实参可以是一个表达式,它的类型可以隐式转换(第
或者,此调用可以为形参数组指定零个或多个实参,其中每个实参都是一个表达式,它的类型可隐式转换(第
usingSystem;
classTest{staticvoidF(paramsint[]args){
staticvoidMain(){int[]arr={1,2,3};
Arraycontains3elements:123Arraycontains4
F(newint[]{10,20,30,40});F(newint[]{});
usingSystem;
classTest{staticvoidF(paramsobject[]a){
staticvoidF(){Console.WriteLine("F()");
staticvoidF(objecta0,objecta1){Console
staticvoidMain(){F();F(1);F(1,2)
F();F(object[]);F(object,object);F(object[]);F
usingSystem;
classTest{staticvoidF(paramsobject[]args)
staticvoidMain(){object[]a={1,"Hello"
System.Int32System.StringSystem.DoubleSystem.Ob
静态方法和实例方法
虚方法
首先,将重载决策应用于C、N和A,以从在C中声明的和由C继承的方法集中选择一个特定的方
然后,如果M为非虚方法,则调用M。
否则(M为虚方法),就会调用就R而言M的派生程度最大的那个实现。
如果R中含有引入的M的virtual声明,则这是M的派生程度最大的实现。
如果R含有关于M的override,则这是M的派生程度最大的实现。
否则,就R而言M的派生程度最大的实现与就R的直接基类而言M的派生程度最大的实现相同。
usingSystem;
classA{publicvoidF(){Console.WriteLine("A
publicvirtualvoidG(){Console.WriteLine("A.G
classB:A{newpublicvoidF(){Console.Write
publicoverridevoidG(){Console.WriteLine("B.
classTest{staticvoidMain(){Bb=newB
A.FB.FB.GB.G
usingSystem;
classA{publicvirtualvoidF(){Console.Writ
classB:A{publicoverridevoidF(){Console.
classC:B{newpublicvirtualvoidF(){Conso
classD:C{publicoverridevoidF(){Console.
classTest{staticvoidMain(){Dd=newD
B.FB.FD.FD.F
重写方法
可以按照上面描述的规则找到一个已重写了的基方法。
只有一个此类重写的基方法。此限制仅在基类类型是构造类型时(在这种情况下,用类型实参替换会使两个方法的
该已重写了的基方法是一个虚的、抽象或重写方法。换句话说,已重写了的基方法不能是静态或非虚方法。
已重写了的基方法不是密封方法。
重写方法和已重写了的基方法具有相同的返回类型。
重写声明和已重写了的基方法具有相同的声明可访问性。换句话说,重写声明不能更改所对应的虚方法的可访问性
重写声明不指定type-parameter-constraints-clauses,而是从重写的基
abstractclassC{publicvirtualTF(){...}
publicvirtualCG(){...}
publicvirtualvoidH(Cx){...}}
classD:C{publicoverridestringF()
publicoverrideCG(){...}//Ok
publicoverridevoidH(Cx){...}//Error,
classE:C{publicoverrideUF(){...}
publicoverrideCG(){...}//Ok
publicoverridevoidH(Cx){...}//Error,
classA{intx;
publicvirtualvoidPrintFields(){Console.W
classB:A{inty;
publicoverridevoidPrintFields(){base.Pri
classA{publicvirtualvoidF(){}}
classB:A{publicvirtualvoidF(){}//Warn
classA{publicvirtualvoidF(){}}
classB:A{newprivatevoidF(){}//Hides
classC:B{publicoverridevoidF(){}//Ok,
密封方法
usingSystem;
classA{publicvirtualvoidF(){Console.W
publicvirtualvoidG(){Console.WriteLine("
classB:A{sealedoverridepublicvoidF(){
overridepublicvoidG(){Console.WriteLine(
classC:B{overridepublicvoidG(){Conso
抽象方法
publicabstractclassShape{publicabstractvo
publicclassEllipse:Shape{publicoverridevo
publicclassBox:Shape{publicoverridevoidP
abstractclassA{publicabstractvoidF();}
classB:A{publicoverridevoidF(){base.
usingSystem;
classA{publicvirtualvoidF(){Console.W
abstractclassB:A{publicabstractoverridev
classC:B{publicoverridevoidF(){Conso
外部方法
usingSystem.Text;usingSystem.Security.Permissio
classPath{[DllImport("kernel32",SetLastError
[DllImport("kernel32",SetLastError=true)]sta
[DllImport("kernel32",SetLastError=true)]sta
[DllImport("kernel32",SetLastError=true)]sta
分部方法
扩展方法
publicstaticclassExtensions{publicstatici
publicstaticT[]Slice(thisT[]source,int
staticclassProgram{staticvoidMain(){s
staticclassProgram{staticvoidMain(){s
方法体
classA{publicintF(){}//Error,returnv
publicintG(){return1;}
publicintH(boolb){if(b){return1;
方法重载
属性
property-declaration:attributesoptproperty-mod
property-modifiers:property-modifierproperty-mod
property-modifier:newpublicprotectedinternalp
member-name:identifierinterface-type.ident
静态属性和实例属性
访问器
accessor-declarations:get-accessor-declaration
get-accessor-declaration:attributesoptaccessor
set-accessor-declaration:attributesoptaccessor
accessor-modifier:protectedinternalprivateprot
accessor-body:block;
accessor-modifier不可用在接口中或显式接口成员实现中。
对于没有override修饰符的属性或索引器,仅当该属性或索引器同时带有get和set访
对于包含override修饰符的属性或索引器,访问器必须匹配被重写的访问器的accessor-
accessor-modifier声明的可访问性的限制性必须严格高于属性或索引器本身所声明的可访问
如果属性或索引器具有已声明可访问性public,则accessor-modifier可能是p
如果属性或索引器声明了protectedinternal可访问性,则accessor-mod
如果属性或索引器声明了internal或protected可访问性,则accessor-m
如果属性或索引器声明了private可访问性,则任何accessor-modifier都不可
同时包含get访问器和set访问器的属性称为读写(read-write)属性。
只具有get访问器的属性称为只读(read-only)属性。将只读属性作为赋值目标会导致编译
只具有set访问器的属性称为只写(write-only)属性。除了作为赋值的目标外,在表达式
publicclassButton:Control{privatestringca
publicstringCaption{get{returncapt
publicoverridevoidPaint(Graphicsg,Rectangle
ButtonokButton=newButton();okButton.Caption=
classA{privatestringname;
publicstringName{//Error,duplicatememb
publicstringName{//Error,duplicatememb
classA{publicintP{set{...}}}
classB:A{newpublicintP{get{...}}
Bb=newB();b.P=1;//Error,B.Pisread-on
classLabel{privateintx,y;privatestring
publicLabel(intx,inty,stringcaption){
publicintX{get{returnx;}}
publicintY{get{returny;}}
publicPointLocation{get{returnnewPoin
publicstringCaption{get{returncaption;
classLabel{privatePointlocation;private
publicLabel(intx,inty,stringcaption){
publicintX{get{returnlocation.x;}}
publicintY{get{returnlocation.y;}}
publicPointLocation{get{returnlocation
publicstringCaption{get{returncaption;
classCounter{privateintnext;
publicintNext{get{returnnext++;}}
usingSystem.IO;
publicclassConsole{privatestaticTextReader
publicstaticTextReaderIn{get{if(r
publicstaticTextWriterOut{get{if(
publicstaticTextWriterError{get{if
Console.Out.WriteLine("hello,world");
自动实现的属性
publicclassPoint{publicintX{get;set;}
publicclassPoint{privateintx;privatein
publicclassReadOnlyPoint{publicintX{get;
可访问性
如果作为值(第7.1.1节)使用,则get访问器必须存在并且可访问。
如果作为简单赋值的目标使用(第
如果作为复合赋值的目标(第
classA{publicstringText{get{return"
publicintCount{get{return5;}set{
classB:A{privatestringtext="goodbye";
newpublicstringText{get{returntext;}
newprotectedintCount{get{returncount
classM{staticvoidMain(){Bb=newB();
publicinterfaceI{stringProp{get;}}
publicclassC:I{publicProp{get{retur
虚、密封、重写和抽象访问器
get访问器相当于一个无形参方法,该方法具有属性类型的返回值以及与包含属性相同的修饰符。
set访问器相当于一个方法,该方法具有单个属性类型的值形参、void返回类型以及与包含属性相同的
abstractclassA{inty;
publicvirtualintX{get{return0;}}
publicvirtualintY{get{returny;}s
publicabstractintZ{get;set;}}
classB:A{intz;
publicoverrideintX{get{returnbase.X+
publicoverrideintY{set{base.Y=value
publicoverrideintZ{get{returnz;}
publicclassB{publicvirtualintP{prote
publicclassD:B{publicoverrideintP{p
事件
event-declaration:attributesoptevent-modifiers
event-modifiers:event-modifierevent-modifiers
event-modifier:newpublicprotectedinternalpriv
event-accessor-declarations:add-accessor-declarat
add-accessor-declaration:attributesoptaddbl
remove-accessor-declaration:attributesoptremov
publicdelegatevoidEventHandler(objectsender,E
publicclassButton:Control{publiceventEven
publicclassLoginDialog:Form{ButtonOkButton
publicLoginDialog(){OkButton=newButton(
voidOkButtonClick(objectsender,EventArgse){
voidCancelButtonClick(objectsender,EventArgs
类似字段的事件
publicdelegatevoidEventHandler(objectsender,E
publicclassButton:Control{publiceventEven
protectedvoidOnClick(EventArgse){if(Cli
publicvoidReset(){Click=null;}}
b.Click+=newEventHandler(…);
b.Click–=newEventHandler(…);
classX{publiceventDEv;}
classX{privateD__Ev;//fieldtoholdthe
publiceventDEv{add{lock(this){__
remove{lock(this){__Ev=__Ev-value;
classX{publicstaticeventDEv;}
classX{privatestaticD__Ev;//fieldtoho
publicstaticeventDEv{add{lock(typ
remove{lock(typeof(X)){__Ev=__Ev-va
事件访问器
classControl:Component{//Uniquekeysforev
//Returneventhandlerassociatedwithkeypr
//Addeventhandlerassociatedwithkeyprote
//Removeeventhandlerassociatedwithkeypr
//MouseDowneventpubliceventMouseEventHand
//MouseUpeventpubliceventMouseEventHandle
//InvoketheMouseUpeventprotectedvoidOnM
静态事件和实例事件
虚、密封、重写和抽象访问器
索引器
indexer-declaration:attributesoptindexer-modif
indexer-modifiers:indexer-modifierindexer-modifi
indexer-modifier:newpublicprotectedinternalpr
indexer-declarator:typethis[formal-param
属性由它的名称标识,而索引器由它的签名标识。
属性是通过simple-name(第
属性可以是static成员,而索引器始终是实例成员。
属性的get访问器对应于不带形参的方法,而索引器的get访问器对应于与索引器具有相同的形参表
属性的set访问器对应于具有名为value的单个形参的方法,而索引器的set访问器对应于
若在索引器访问器内使用与该索引器的形参相同的名称来声明局部变量,就会导致一个编译时错误。
在重写属性声明中,被继承的属性是使用语法base.P访问的,其中P为属性名称。在重写索引器声
usingSystem;
classBitArray{int[]bits;intlength;
publicBitArray(intlength){if(length<0)
publicintLength{get{returnlength;}
publicboolthis[intindex]{get{if(i
classCountPrimes{staticintCount(intmax){
staticvoidMain(string[]args){intmax=i
usingSystem;
classGrid{constintNumRows=26;constint
int[,]cells=newint[NumRows,NumCols];
publicintthis[charc,intcol]{get{
set{c=Char.ToUpper(c);if(c<'A'
索引器重载
运算符
operator-declaration:attributesoptoperator-mod
operator-modifiers:operator-modifieroperator-mod
operator-modifier:publicstaticextern
operator-declarator:unary-operator-declaratorbin
unary-operator-declarator:typeoperatoroverloa
overloadable-unary-operator:以下运算符之一+-!~
binary-operator-declarator:typeoperatoroverlo
overloadable-binary-operator:+-*/%&|^<
conversion-operator-declarator:implicitoperato
operator-body:block;
运算符声明必须同时包含一个public和一个static修饰符。
运算符的形参必须是值形参。在运算符声明中指定ref或out形参会导致编译时错误。
运算符的签名(第
运算符声明中引用的所有类型都必须具有与运算符本身相同的可访问性(第
同一修饰符在一个运算符声明中多次出现是错误的。
一元运算符
一元+、-、!或~运算符必须具有单个T或T?类型的形参,并且可以返回任何类型。
一元++或--运算符必须带有单个T或T?类型的形参并且必须返回与它相同或由它派生的类
一元true或false运算符必须具有单个T或T?类型的形参并且必须返回类型boo
publicclassIntVector{publicIntVector(intle
publicintLength{...}//read-onlypropert
publicintthis[intindex]{...}//read-write
publicstaticIntVectoroperator++(IntVectoriv
classTest{staticvoidMain(){IntVectori
iv2=iv1++;//iv2contains4x0,iv1contain
二元运算符
二元非移位运算符必须带有两个形参,其中至少有一个必须为类型T或T?,并且可返回其中的任一类型。
二元<<或>>运算符必须带有两个形参,其中第一个必须具有类型T或T?,第二个必须具有类
operator==和operator!=
operator>和operator<
operator>=和operator<=
转换运算符
S0和T0是不同的类型。
S0和T0中总有一个是声明了该运算符的类类型或结构类型。
S0和T0都不是interface-type。
除用户定义的转换之外,不存在从S到T或从T到S的转换。
classC{...}
classD:C{publicstaticimplicitoperat
publicstaticimplicitoperatorC(Dv
publicstaticimplicitoperatorC(Dvalue)
structConvertible{publicstaticimplicito
publicstaticexplicitoperatorT(Convertible
如果存在从类型S到类型T的预定义隐式转换(第6.1节),则从S到T的所有用户定义
如果存在从类型S到类型T的预定义显式转换(第6.2节),则从S到T的所有用户定义
voidF(inti,Convertiblen){i=n;
voidF(objecto,Convertible
usingSystem;
publicstructDigit{bytevalue;
publicDigit(bytevalue){if(value<0||v
publicstaticimplicitoperatorbyte(Digitd){
publicstaticexplicitoperatorDigit(byteb){
实例构造函数
constructor-declaration:attributesoptconstruct
constructor-modifiers:constructor-modifierconstr
constructor-modifier:publicprotectedinternalpr
constructor-declarator:identifier(formal-pa
constructor-initializer::base(argument-l
constructor-body:block;
构造函数初始值设定项
base(argument-listopt)形式的实例构造函数初始值设定项导致调用直接基类中的实例
this(argument-listopt)形式的实例构造函数初始值设定项导致调用该类本身所声明的
C(...){...}
C(...):base(){...}
classA{publicA(intx,inty){}}
classB:A{publicB(intx,inty):base(x+y,
实例变量初始值设定项
构造函数执行
usingSystem;
classA{publicA(){PrintFields();}
publicvirtualvoidPrintFields(){}
}
classB:A{intx=1;inty;
publicB(){y=-1;}
publicoverridevoidPrintFields(){Console.
x=1,y=0
usingSystem;usingSystem.Collections;
classA{intx=1,y=-1,count;
publicA(){count=0;}
publicA(intn){count=n;}}
classB:A{doublesqrt2=Math.Sqrt(2.0);Ar
publicB():this(100){items.Add("default");
publicB(intn):base(n–1){max=n;}}
usingSystem.Collections;
classA{intx,y,count;
publicA(){x=1;//Variableinitia
publicA(intn){x=1;//Variablei
classB:A{doublesqrt2;ArrayListitems;
publicB():this(100){B(100);//Inv
publicB(intn):base(n–1){sqrt2=Math.S
默认构造函数
protectedC():base(){}
publicC():base(){}
classMessage{objectsender;stringtext;}
classMessage{objectsender;stringtext;
publicMessage():base(){}}
私有构造函数
publicclassTrig{privateTrig(){}//Preven
publicconstdoublePI=3.14159265358979323846;
publicstaticdoubleSin(doublex){...}publi
可选的实例构造函数形参
classText{publicText():this(0,0,null){}
publicText(intx,inty):this(x,y,null){}
publicText(intx,inty,strings){//Actu
Textt1=newText();//SameasText(0,0,nu
静态构造函数
static-constructor-declaration:attributesoptst
static-constructor-modifiers:externoptstatics
static-constructor-body:block;
创建类类型的实例。
引用类类型的任何静态成员。
usingSystem;
classTest{staticvoidMain(){A.F();B
classA{staticA(){Console.WriteLine("Ini
classB{staticB(){Console.WriteLine("Ini
InitAA.FInitBB.F
usingSystem;
classA{publicstaticintX;
staticA(){X=B.Y+1;}}
classB{publicstaticintY=A.X+1;
staticB(){}
staticvoidMain(){Console.WriteLine("X={
X=1,Y=2
classGenwhereT:struct{staticGen(){
析构函数
destructor-declaration:attributesoptexternopt
destructor-body:block;
usingSystem;
classA{~A(){Console.WriteLine("A'sdestr
classB:A{~B(){Console.WriteLine("B'sde
classTest{staticvoidMain(){Bb=new
B’sdestructorA’sdestructor
classA{overrideprotectedvoidFinalize(){}
publicvoidF(){this.Finalize();//e
classA{voidFinalize(){}//permitted
迭代器
枚举器接口
可枚举接口
产生类型
返回IEnumerator或IEnumerable的迭代器的产生类型是object。
返回IEnumerator或IEnumerable的迭代器的产生类型是T。
枚举器对象
它实现了IEnumerator和IEnumerator,其中T为迭代器的产生类型。
它实现了System.IDisposable。
它以传递给该函数成员的实参值(如果存在)和实例值的副本进行初始化。
它有四种可能的状态:运行前(before)、运行中(running)、挂起(suspended
MoveNext方法
如果枚举器对象的状态为运行前(before),则调用MoveNext会:
将状态更改为运行中(running)。
将迭代器块的形参(包括this)初始化为实参值以及初始化该枚举器对象时所保存的实例值。
从头开始执行迭代器块,直到执行被中断(如后文所述)。
如果枚举器对象的状态为运行中(running),则调用MoveNext的结果不确定。
如果枚举器对象的状态为挂起(suspended),则调用MoveNext会:
将状态更改为运行中(running)。
将所有局部变量和形参(包括this)的值恢复为迭代器块的执行上次挂起时保存的值。注意,这些变量所
恢复执行紧跟在引起执行挂起的yieldreturn语句后面的迭代器块,并一直继续,直到执行中断
如果枚举器对象的状态为运行后(after),则调用MoveNext将返回false。
当遇到yieldreturn语句时(第
计算该语句中给出的表达式,隐式转换为产生类型,并赋给枚举器对象的Current属性。
迭代器体的执行被挂起。所有局部变量和形参(包括this)的值被保存,此yieldreturn
枚举器对象的状态更改为挂起(suspended)。
MoveNext方法向其调用方返回true,指示迭代成功前进至下一个值。
当遇到yieldbreak语句时(第
如果yieldbreak语句在一个或多个try块内,则执行与之关联的finally块。
枚举器对象的状态更改为运行后(after)。
MoveNext方法向其调用方返回false,指示迭代完成。
当遇到迭代器体的结束处时:
枚举器对象的状态更改为运行后(after)。
MoveNext方法向其调用方返回false,指示迭代完成。
当引发异常并传播到迭代器块之外时:
通过异常传播机制执行迭代器体内的相应finally块。
枚举器对象的状态更改为运行后(after)。
异常继续传播至MoveNext方法的调用方。
Current属性
Dispose方法
如果枚举器对象的状态为运行前(before),则调用Dispose将把状态更改为运行后(af
如果枚举器对象的状态为运行中(running),则调用Dispose的结果不确定。
如果枚举器对象的状态为挂起(suspended),则调用Dispose将:
将状态更改为运行中(running)。
执行所有finally块,就好像最后执行的yieldreturn语句为yieldbre
将状态更改为运行后(after)。
如果枚举器对象的状态为运行后(after),则调用Dispose没有任何作用。
可枚举对象
它实现了IEnumerable和IEnumerable,其中T为迭代器的产生类型。
它以传递给该函数成员的实参值(如果存在)和实例值的副本进行初始化。
GetEnumerator方法
实现示例
usingSystem;usingSystem.Collections;usingSyst
classStack:IEnumerable{T[]items;in
publicvoidPush(Titem){if(items==null)
publicTPop(){Tresult=items[--count];
publicIEnumeratorGetEnumerator(){for(
classStack:IEnumerable{...
publicIEnumeratorGetEnumerator(){retur
class__Enumerator1:IEnumerator,IEnumerator
public__Enumerator1(Stack__this){thi
publicTCurrent{get{return__current;
objectIEnumerator.Current{get{return_
publicboolMoveNext(){switch(__state){
publicvoidDispose(){__state=2;}
voidIEnumerator.Reset(){thrownewNotSup
usingSystem;usingSystem.Collections.Generic;
classTest{staticIEnumerableFromTo(int
staticvoidMain(){IEnumerablee=Fro
usingSystem;usingSystem.Threading;usingSystem
classTest{...
staticIEnumerableFromTo(intfrom,intto)
class__Enumerable1:IEnumerable,IEnume
public__Enumerable1(int__from,intto){
publicIEnumeratorGetEnumerator(){_
IEnumeratorIEnumerable.GetEnumerator(){r
publicintCurrent{get{return__current
objectIEnumerator.Current{get{return_
publicboolMoveNext(){switch(__state){
publicvoidDispose(){__state=2;}
voidIEnumerator.Reset(){thrownewNotSup
usingSystem;usingSystem.Collections.Generic;
classTree:IEnumerable{Tvalue;Tree<
publicTree(Tvalue,Treeleft,Treeright
publicIEnumeratorGetEnumerator(){if(l
classProgram{staticTreeMakeTree(T[]i
staticTreeMakeTree(paramsT[]items){
//Theoutputoftheprogramis://12345
staticvoidMain(){Treeints=MakeTre
Treestrings=MakeTree("Mon","Tu
classTree:IEnumerable{...
publicIEnumeratorGetEnumerator(){retur
class__Enumerator1:IEnumerator,IEnumerato
public__Enumerator1(Node__this){this
publicTCurrent{get{return__current;
objectIEnumerator.Current{get{return_
publicboolMoveNext(){try{switch
case0:__state=-1;if(__this.
case1:__state=-2;if(!__left
__left_dispose:__state=-1;__l
__yield_value:__current=__this.value
case2:__state=-1;if(__this.
case3:__state=-3;if(!__righ
__right_dispose:__state=-1;__
__end:__state=4;break;
}}finally{if(__state<0)D
publicvoidDispose(){try{switch(
case1:case-2:__left.Dispose();
case3:case-3:__right.Dispose()
}}finally{__state=4;}
voidIEnumerator.Reset(){thrownewNotSup
结构
结构声明
struct-declaration:attributesoptstruct-modifie
结构修饰符
struct-modifiers:struct-modifierstruct-modifiers
struct-modifier:newpublicprotectedinternalpri
OLE_LINK3
分部修饰符
结构接口
struct-interfaces::interface-type-list
结构体
struct-body:{struct-member-declarationsopt}
结构成员
struct-member-declarations:struct-member-declarat
struct-member-declaration:constant-declarationfi
类和结构的区别
结构是值类型(第
所有结构类型都隐式地从类System.ValueType(第
对结构类型变量进行赋值意味着将创建所赋的值的一个副本(第
结构的默认值的计算如下:将所有值类型字段设置为它们的默认值,并将所有引用类型字段设置为null,这
使用装箱和取消装箱操作在结构类型和object之间进行转换(第
对于结构,this的意义不同(第
在结构中,实例字段声明中不能含有变量初始值设定项(第
在结构中不能声明无形参的实例构造函数(第
在结构中不允许声明析构函数(第
值语义
structNode{intdata;
Nodenext;//error,Nodedirectlydependsonit
}
structA{Bb;}
structB{Cc;}
structC{Aa;}
structPoint{publicintx,y;
publicPoint(intx,inty){this.x=x;t
Pointa=newPoint(10,10);Pointb=a;a.x=10
继承
赋值
默认值
Point[]a=newPoint[100];
usingSystem;
structKeyValuePair{stringkey;stringvalue
publicKeyValuePair(stringkey,stringvalue){
装箱和取消装箱
usingSystem;
structCounter{intvalue;
publicoverridestringToString(){value++;
classProgram{staticvoidTest()whereT:n
staticvoidMain(){Test();}}
123
usingSystem;
interfaceICounter{voidIncrement();}
structCounter:ICounter{intvalue;
publicoverridestringToString(){returnva
voidICounter.Increment(){value++;}}
classProgram{staticvoidTest()whereT:I
staticvoidMain(){Test();}}
011
this的含义
字段初始值设定项
structPoint{publicintx=1;//Error,init
构造函数
structPoint{intx,y;
publicPoint(intx,inty){this.x=x;t
Pointp1=newPoint();
Pointp2=newPoint(0,0);
structPoint{intx,y;
publicintX{set{x=value;}}
publicintY{set{y=value;}}
publicPoint(intx,inty){X=x;//error
析构函数
静态构造函数
结构类型的实例成员被引用。
结构类型的静态成员被引用。
结构类型的显式声明的构造函数被调用。
结构示例
数据库整数类型
usingSystem;
publicstructDBInt{//TheNullmemberreprese
publicstaticreadonlyDBIntNull=newDBInt();
//Whenthedefinedfieldistrue,thisDBIntre
intvalue;booldefined;
//Privateinstanceconstructor.CreatesaDBInt
DBInt(intvalue){this.value=value;thi
//TheIsNullpropertyistrueifthisDBIntrep
publicboolIsNull{get{return!defined;}}
//TheValuepropertyistheknownvalueofthis
publicintValue{get{returnvalue;}}
//ImplicitconversionfrominttoDBInt.
publicstaticimplicitoperatorDBInt(intx){
//ExplicitconversionfromDBInttoint.Throws
publicstaticexplicitoperatorint(DBIntx){
publicstaticDBIntoperator+(DBIntx){ret
publicstaticDBIntoperator-(DBIntx){ret
publicstaticDBIntoperator+(DBIntx,DBInty)
publicstaticDBIntoperator-(DBIntx,DBInty)
publicstaticDBIntoperator*(DBIntx,DBInty)
publicstaticDBIntoperator/(DBIntx,DBInty)
publicstaticDBIntoperator%(DBIntx,DBInty)
publicstaticDBBooloperator==(DBIntx,DBInt
publicstaticDBBooloperator!=(DBIntx,DBInt
publicstaticDBBooloperator>(DBIntx,DBInty
publicstaticDBBooloperator<(DBIntx,DBInty
publicstaticDBBooloperator>=(DBIntx,DBInt
publicstaticDBBooloperator<=(DBIntx,DBInt
publicoverrideboolEquals(objectobj){if
publicoverrideintGetHashCode(){returnva
publicoverridestringToString(){returnde
数据库布尔类型
usingSystem;
publicstructDBBool{//ThethreepossibleDBB
publicstaticreadonlyDBBoolNull=newDBBool(
//Privatefieldthatstores–1,0,1forFalse,
sbytevalue;
//Privateinstanceconstructor.Thevalueparam
DBBool(intvalue){this.value=(sbyte)value
//PropertiestoexaminethevalueofaDBBool.
publicboolIsNull{get{returnvalue==0;}
publicboolIsFalse{get{returnvalue<0;}
publicboolIsTrue{get{returnvalue>0;}}
//ImplicitconversionfrombooltoDBBool.Maps
publicstaticimplicitoperatorDBBool(boolx){
//ExplicitconversionfromDBBooltobool.Thro
publicstaticexplicitoperatorbool(DBBoolx){
//Equalityoperator.ReturnsNullifeitherope
publicstaticDBBooloperator==(DBBoolx,DBBoo
//Inequalityoperator.ReturnsNullifeithero
publicstaticDBBooloperator!=(DBBoolx,DBBoo
//Logicalnegationoperator.ReturnsTrueifth
publicstaticDBBooloperator!(DBBoolx){r
//LogicalANDoperator.ReturnsFalseifeither
publicstaticDBBooloperator&(DBBoolx,DBBool
//LogicalORoperator.ReturnsTrueifeithero
publicstaticDBBooloperator|(DBBoolx,DBBool
//Definitelytrueoperator.Returnstrueifthe
publicstaticbooloperatortrue(DBBoolx){
//Definitelyfalseoperator.Returnstrueifth
publicstaticbooloperatorfalse(DBBoolx){
publicoverrideboolEquals(objectobj){if
publicoverrideintGetHashCode(){returnva
publicoverridestringToString(){if(value
数组
数组类型
array-type:non-array-typerank-specifiers
non-array-type:type
rank-specifiers:rank-specifierrank-specifiers
rank-specifier:[dim-separatorsopt]
dim-separators:,dim-separators,
形式为T[R]的数组类型是秩为R、元素类型为非数组元素类型T的数组。
形式为T[R][R1]...[RN]的数组类型是秩为R、元素类型为T[R1]...[RN]
System.Array类型
数组和泛型IList接口
usingSystem.Collections.Generic;
classTest{staticvoidMain(){string[]sa
IListlst1=sa;//OkIList
IListlst5=(IList)oa1;//Exc
数组创建
数组元素访问
数组成员
数组协变
classTest{staticvoidFill(object[]array,in
staticvoidMain(){string[]strings=news
数组初始值设定项
array-initializer:{variable-initializer-listop
variable-initializer-list:variable-initializerva
variable-initializer:expressionarray-initializer
int[]a={0,2,4,6,8};
int[]a=newint[]{0,2,4,6,8};
a[0]=0;a[1]=2;a[2]=4;a[3]=6;a[4]=8;
int[,]b={{0,1},{2,3},{4,5},{6,7},{8,9}
int[,]b=newint[5,2];
b[0,0]=0;b[0,1]=1;b[1,0]=2;b[1,1]=3
int[,]c={};
int[,]c=newint[0,0];
inti=3;int[]x=newint[3]{0,1,2};//OK
接口
接口声明
interface-declaration:attributesoptinterface-m
接口修饰符
interface-modifiers:interface-modifierinterface-
interface-modifier:newpublicprotectedinternal
分部修饰符
基接口
interface-base::interface-type-list
interfaceIControl{voidPaint();}
interfaceITextBox:IControl{voidSetText(stri
interfaceIListBox:IControl{voidSetItems(str
interfaceIComboBox:ITextBox,IListBox{}
接口体
interface-body:{interface-member-declarationso
接口成员
interface-member-declarations:interface-member-de
interface-member-declaration:interface-method-dec
publicdelegatevoidStringListEvent(IStringLists
publicinterfaceIStringList{voidAdd(strings
intCount{get;}
eventStringListEventChanged;
stringthis[intindex]{get;set;}}
方法的名称必须与同一接口中声明的所有属性和事件的名称不同。此外,方法的签名(第
属性或事件的名称必须与同一接口中声明的所有其他成员的名称不同。
一个索引器的签名必须区别于在同一接口中声明的其他所有索引器的签名。
接口方法
interface-method-declaration:attributesoptnewo
接口属性
interface-property-declaration:attributesoptne
interface-accessors:attributesoptget;attri
接口事件
interface-event-declaration:attributesoptnewop
接口索引器
interface-indexer-declaration:attributesoptnew
接口成员访问
interfaceIList{intCount{get;set;}}
interfaceICounter{voidCount(inti);}
interfaceIListCounter:IList,ICounter{}
classC{voidTest(IListCounterx){x.Count
interfaceIInteger{voidAdd(inti);}
interfaceIDouble{voidAdd(doubled);}
interfaceINumber:IInteger,IDouble{}
classC{voidTest(INumbern){n.Add(1);
interfaceIBase{voidF(inti);}
interfaceILeft:IBase{newvoidF(inti);}
interfaceIRight:IBase{voidG();}
interfaceIDerived:ILeft,IRight{}
classA{voidTest(IDerivedd){d.F(1);
完全限定接口成员名
interfaceIControl{voidPaint();}
interfaceITextBox:IControl{voidSetText(stri
namespaceSystem{publicinterfaceICloneable
接口实现
interfaceICloneable{objectClone();}
interfaceIComparable{intCompareTo(objectoth
classListEntry:ICloneable,IComparable{publi
publicintCompareTo(objectother){...}}
interfaceIControl{voidPaint();}
interfaceITextBox:IControl{voidSetText(stri
classTextBox:ITextBox{publicvoidPaint(){.
publicvoidSetText(stringtext){...}}
classC{}
interfaceI1{}
classD:C,I1{}
classE:C,I1{}
显式接口成员实现
interfaceIList{T[]GetElements();}
interfaceIDictionary{Vthis[Kkey];
voidAdd(Kkey,Vvalue);}
classList:IList,IDictionary{T[
TIDictionary.this[intindex]{...}
voidIDictionary.Add(intindex,Tvalue)
interfaceIDisposable{voidDispose();}
classMyFile:IDisposable{voidIDisposable.Dis
publicvoidClose(){//Dowhat'snecessary
由于显式接口成员实现不能通过类或结构实例来访问,因此它们就不属于类或结构的自身的公共接口。当需在一个
显式接口成员实现可以消除因同时含有多个相同签名的接口成员所引起的多义性。如果没有显式接口成员实现,一
classShape:ICloneable{objectICloneable.Clon
intIComparable.CompareTo(objectother){...}//
classShape:ICloneable{objectICloneable.Clon
classEllipse:Shape{objectICloneable.Clone()
interfaceIControl{voidPaint();}
interfaceITextBox:IControl{voidSetText(stri
classTextBox:ITextBox{voidIControl.Paint()
voidITextBox.SetText(stringtext){...}}
所实现接口的唯一性
interfaceI{voidF();}
classX:I,I//Error:IandI<
Ix=newX();x.F();
假设L是泛型类、结构或接口声明C中直接指定的接口列表。
将已经在L中的接口的所有基接口添加到L。
移除L中的所有重复接口。
在将类型实参替换到L中之后,如果从C创建的任何可能的构造类型导致L中的两个接口完全相同,
interfaceI{voidF();}
classBase:I{voidI.F(){…}}
classDerived:Base,I//Ok{voidI
Ix=newDerived();x.F();
泛型方法的实现
classC:I
classC:I
publicvoidH(Uu)whereU:class{...}
voidI
接口映射
如果S包含一个与I和M匹配的显式接口成员实现的声明,那么此成员就是I.M的实现。
否则,如果S包含与M匹配的非静态的public成员声明,则此成员就是I.M的实现。如
A和B都是方法,并且A和B的名称、类型和形参表都相同。
A和B都是属性,A和B的名称和类型相同,并且A与B具有相同的访问器(如果A不
A和B都是事件,并且A和B的名称和类型相同。
A和B都是索引器,A和B的类型和形参表相同,并且A与B具有相同的访问器(如果A
在类或结构成员中确定哪个实现了接口成员时,显式接口成员实现比同一个类或结构中的其他成员具有更高的优先
接口映射不涉及非公共成员和静态成员。
interfaceICloneable{objectClone();}
classC:ICloneable{objectICloneable.Clone()
publicobjectClone(){...}}
interfaceIControl{voidPaint();}
interfaceIForm{voidPaint();}
classPage:IControl,IForm{publicvoidPaint(
interfaceIBase{intP{get;}}
interfaceIDerived:IBase{newintP();}
classC:IDerived{intIBase.P{get{...}}
intIDerived.P(){...}}
classC:IDerived{publicintP{get{...}}
intIDerived.P(){...}}
classC:IDerived{intIBase.P{get{...}}
publicintP(){...}}
interfaceIControl{voidPaint();}
interfaceITextBox:IControl{voidSetText(stri
interfaceIListBox:IControl{voidSetItems(str
classComboBox:IControl,ITextBox,IListBox{v
voidITextBox.SetText(stringtext){...}
voidIListBox.SetItems(string[]items){...}}
interfaceInterface1{voidF();}
classClass1{publicvoidF(){}
publicvoidG(){}}
classClass2:Class1,Interface1{newpublicvo
接口实现继承
interfaceIControl{voidPaint();}
classControl:IControl{publicvoidPaint(){.
classTextBox:Control{newpublicvoidPaint()
Controlc=newControl();TextBoxt=newTextBox
interfaceIControl{voidPaint();}
classControl:IControl{publicvirtualvoidPa
classTextBox:Control{publicoverridevoidPa
Controlc=newControl();TextBoxt=newTextBox
interfaceIControl{voidPaint();}
classControl:IControl{voidIControl.Paint()
protectedvirtualvoidPaintControl(){...}}
classTextBox:Control{protectedoverridevoid
接口重新实现
interfaceIControl{voidPaint();}
classControl:IControl{voidIControl.Paint()
classMyControl:Control,IControl{publicvoid
interfaceIMethods{voidF();voidG();voi
classBase:IMethods{voidIMethods.F(){}vo
classDerived:Base,IMethods{publicvoidF()
interfaceIBase{voidF();}
interfaceIDerived:IBase{voidG();}
classC:IDerived{voidIBase.F(){...}
voidIDerived.G(){...}}
classD:C,IDerived{publicvoidF(){...}
publicvoidG(){...}}
抽象类和接口
interfaceIMethods{voidF();voidG();}
abstractclassC:IMethods{publicabstractvoi
interfaceIMethods{voidF();voidG();}
abstractclassC:IMethods{voidIMethods.F(){
voidIMethods.G(){GG();}
protectedabstractvoidFF();
protectedabstractvoidGG();}
枚举
enumColor{Red,Green,Blue}
枚举声明
enum-declaration:attributesoptenum-modifiersop
enum-base::integral-type
enum-body:{enum-member-declarationsopt}{
enumColor:long{Red,Green,Blue}
枚举修饰符
enum-modifiers:enum-modifierenum-modifiersenu
enum-modifier:newpublicprotectedinternalpriva
枚举成员
enum-member-declarations:enum-member-declaration
enum-member-declaration:attributesoptidentifie
enumColor:uint{Red=-1,Green=-2,Blu
enumColor{Red,Green,Blue,
Max=Blue}
如果枚举成员是在枚举类型中声明的第一个枚举成员,则它的关联值为零。
否则,枚举成员的关联值是通过将前一个枚举成员(按照文本顺序)的关联值加1得到的。这样增加后的值必
usingSystem;
enumColor{Red,Green=10,Blue}
classTest{staticvoidMain(){Console.Wri
staticstringStringFromColor(Colorc){swit
caseColor.Green:returnString.Format("G
caseColor.Blue:returnString.Format("Bl
default:return"Invalidcolor";}}
Red=0Green=10Blue=11
枚举成员Red被自动赋予零值(因为它不具有初始值设定项并且是第一个枚举成员);
枚举成员Green被显式赋予值10;
而枚举成员Blue被自动赋予比文本上位于它前面的成员大1的值。
enumCircular{A=B,B}
System.Enum类型
枚举值和运算
委托
委托声明
delegate-declaration:attributesoptdelegate-mod
delegate-modifiers:delegate-modifierdelegate-mod
delegate-modifier:newpublicprotectedinternalp
delegateintD1(inti,doubled);
classA{publicstaticintM1(inta,doubleb)
classB{delegateintD2(intc,doubled);
publicstaticintM1(intf,doubleg){...}
publicstaticvoidM2(intk,doublel){...}
publicstaticintM3(intg){...}
publicstaticvoidM4(intg){...}}
delegateboolPredicate(Tvalue);
classX{staticboolF(inti){...}
staticboolG(strings){...}}
delegatevoidD(intx);
classC{publicstaticvoidM1(inti){...}
publicstaticvoidM2(inti){...}
}
classTest{staticvoidMain(){Dcd1=new
}
委托兼容性
D和M有着相同数目的参数,并且D中的每一个参数都具有与M中的对应参数相同的ref或
对于每一个值参数(没有ref或out修饰符的参数),都存在从D中的参数类型到M中的对
对于每个ref或out参数,D中的参数类型与M中的参数类型相同。
存在从M的返回类型到D的返回类型的标识或隐式引用转换。
委托实例化
delegate-creation-expression中引用的静态方法,或者
delegate-creation-expression中引用的目标对象(此对象不能为null)
另一个委托。
delegatevoidD(intx);
classC{publicstaticvoidM1(inti){...}p
classTest{staticvoidMain(){Dcd1=ne
委托调用
usingSystem;
delegatevoidD(intx);
classC{publicstaticvoidM1(inti){Cons
publicstaticvoidM2(inti){Console.WriteL
publicvoidM3(inti){Console.WriteLine("C.
classTest{staticvoidMain(){Dcd1=ne
Dcd2=newD(C.M2);cd2(-2);//callM2
Dcd3=cd1+cd2;cd3(10);//callM1th
cd3+=cd1;cd3(20);//callM1,M2,then
Cc=newC();Dcd4=newD(c.M3);cd3+
cd3-=cd1;//removelastM1cd3(40);
cd3-=cd4;cd3(50);//callM1thenM2
cd3-=cd2;cd3(60);//callM1
cd3-=cd2;//impossibleremovalisbenign
cd3-=cd1;//invocationlistisemptysocd
//cd3(70);//System.NullReferenceException
cd3-=cd1;//impossibleremovalisbenign
C.M1:-1C.M2:-2C.M1:10C.M2:10C.M1:20C.M2:
异常
在C#中,所有的异常必须由从System.Exception派生的类类型的实例来表示。在C
在C#中,利用finally块(第
在C#中,系统级的异常如溢出、被零除和null等都对应地定义了与其匹配的异常类,并且与应用程
导致异常的原因
throw语句(第
在执行C#语句和表达式的过程中,有时会出现一些例外情况,使某些操作无法正常完成,此时就会引发一个
System.Exception类
Message是string类型的一个只读属性,它包含关于所发生异常的原因的描述(易于人工阅读
InnerException是Exception类型的一个只读属性。如果它的值不是null,
异常的处理方式
如果对匹配的catch子句的搜索到达一个静态构造函数(第
如果对匹配的catch子句的搜索到达最初启动当前线程的代码处,则该线程的执行就会终止。此类终止会
公共异常类
System.ArithmeticException
在算术运算期间发生的异常(如System.DivideByZeroException和Syst
System.ArrayTypeMismatchException
当存储一个数组时,如果由于被存储的元素的实际类型与数组的实际类型不兼容而导致存储失败,就会引发此异常
System.DivideByZeroException
在试图用零除整数值时引发。
System.IndexOutOfRangeException
在试图使用小于零或超出数组界限的下标索引数组时引发。
System.InvalidCastException
当从基类型或接口到派生类型的显式转换在运行时失败时,就会引发此异常。
System.NullReferenceException
在需要使用引用对象的场合,如果使用null引用,就会引发此异常。
System.OutOfMemoryException
在分配内存(通过new)的尝试失败时引发。
System.OverflowException
在checked上下文中的算术运算溢出时引发。
System.StackOverflowException
当执行堆栈由于保存了太多挂起的方法调用而耗尽时,就会引发此异常;这通常表明存在非常深或无限的递归。
System.TypeInitializationException
在静态构造函数引发异常并且没有可以捕捉到它的catch子句时引发。
属性
属性类
属性用法
usingSystem;
[AttributeUsage(AttributeTargets.Class|Attribute
[Simple]classClass1{...}
[Simple]interfaceInterface1{...}
[SimpleAttribute]classClass1{...}
[SimpleAttribute]interfaceInterface1{...}
usingSystem;
[AttributeUsage(AttributeTargets.Class,AllowMulti
publicAuthorAttribute(stringname){this.na
publicstringName{get{returnname;}}
[Author("BrianKernighan"),Author("DennisRitchie
usingSystem;
classX:Attribute{...}
usingSystem;
[AttributeUsage(AttributeTargets.All,AllowMu
定位和命名参数
usingSystem;
[AttributeUsage(AttributeTargets.Class)]publiccl
publicstringTopic{//Namedparameter
publicstringUrl{get{...}}}
[Help("http://www.mycompany.com/.../Class1.htm")]
[Help("http://www.mycompany.com/.../Misc.htm",Top
属性参数类型
以下类型之一:bool、byte、char、double、float、int、long、sbyte、
类型object。
类型System.Type。
枚举类型,前提是该枚举类型具有public可访问性,而且所有嵌套着它的类型(如果有)也必须具有
以上类型的一维数组。
没有这些类型之一的构造函数参数或公共字段在属性说明中不能用作定位参数或命名参数。
属性说明
global-attributes:global-attribute-sections
global-attribute-sections:global-attribute-sectio
global-attribute-section:[global-attribute-tar
global-attribute-target-specifier:global-attribut
global-attribute-target:assemblymodule
attributes:attribute-sections
attribute-sections:attribute-sectionattribute-se
attribute-section:[attribute-target-specifiero
attribute-target-specifier:attribute-target:
attribute-target:fieldeventmethodparampropert
attribute-list:attributeattribute-list,att
attribute:attribute-nameattribute-argumentsopt
attribute-name:type-name
attribute-arguments:(positional-argument-listo
positional-argument-list:positional-argumentposi
positional-argument:attribute-argument-expression
named-argument-list:named-argumentnamed-argument
named-argument:identifier=attribute-argumen
attribute-argument-expression:expression
classClass1{}
[Class1]classClass2{}//Error
在全局范围指定的属性可以应用于目标程序集或目标模块。系统没有为此上下文提供默认形式,所以在此上下文中
在委托声明上指定的属性,或者适用于所声明的委托,或者适用于它的返回值。如果不存在attribute
在方法声明上指定的属性,或者适用于所声明的方法,或者适用于它的返回值。如果不存在attribute
在运算符声明上指定的属性,或者适用于所声明的运算符,或者适用于它的返回值。如果不存在attribu
对于在省略了事件访问器的事件声明上指定的属性,它的目标对象有三种可能的选择:所声明的事件;与该事件关
在属性或索引器声明中的get访问器声明上指定的属性,或者适用于该访问器关联的方法,或者适用于它的
在属性或索引器声明中的set访问器上指定的属性,或者可适用于该访问器关联的方法,或者适用于它的独
在事件声明的添加或移除访问器声明上指定的属性,或者适用于该访问器关联的方法,或者适用于它的独立参数。
[type:Author("BrianKernighan")]classClass1{}
[Author("DennisRitchie")]classClass2{}
[param:Author("BrianKernighan")]//Errorclass
usingSystem;
[AttributeUsage(AttributeTargets.All)]publicclas
[AttributeUsage(AttributeTargets.All)]publicclas
[X]//Error:ambiguityclassClass1{}
[XAttribute]//ReferstoXAttributeclassClass
[@X]//ReferstoXclassClass3{}
[@XAttribute]//ReferstoXAttributeclassClas
usingSystem;
[AttributeUsage(AttributeTargets.All)]publicclas
[X]//ReferstoXAttributeclassClass1{}
[XAttribute]//ReferstoXAttributeclassClass
[@X]//Error:noattributenamed"X"classC
usingSystem;
[AttributeUsage(AttributeTargets.Class)]publiccl
publicHelpStringAttribute(stringvalue){th
publicstringValue{get{...}}}
[HelpString("DescriptionofClass1")][HelpString(
E的类型是属性参数类型(第
在编译时,E的值可以解析为下列之一:
常量值。
System.Type对象。
attribute-argument-expression的一维数组。
usingSystem;
[AttributeUsage(AttributeTargets.Class)]publiccl
publicTypeP2{get{...}set{...}}
publicobjectP3{get{...}set{...}}
[Test(P1=1234,P3=newint[]{1,3,5},P2=ty
classA:Attribute{publicA(Typet){...}}
classG{[A(typeof(T))]Tt;//Error,o
classX{[A(typeof(List))]intx;//Ok,
属性实例
属性的编译
遵循形式为newT(P)的object-creation-expression的编译规则所
如果C不具有公共可访问性,则发生编译时错误。
对于N中的每个named-argumentArg:
将Name设为named-argumentArg的identifier。
Name必须标识T中的一个非静态读写public字段或属性。如果T没有这样的字段或属性
保留下面的信息以供在运行时实例化该属性时调用:属性类T、T上的实例化构造函数C、positio
属性实例的运行时检索
遵循执行newT(P)形式的object-creation-expression(使用在编译
对于N中的每个named-argumentArg,按以下顺序进行处理:
将Name设为named-argumentArg的identifier。如果Name
将Value设为Arg的attribute-argument-expression的计算
如果Name标识O上的一个字段,则将此字段设置为Value。
否则,Name就标识O上的一个属性。将此属性设置为Value。
结果为O,它是已经用positional-argument-listP和named-arg
保留属性
System.AttributeUsageAttribute(第
System.Diagnostics.ConditionalAttribute(第
System.ObsoleteAttribute(第
AttributeUsage属性
namespaceSystem{[AttributeUsage(AttributeTarg
publicvirtualboolAllowMultiple{get{...}s
publicvirtualboolInherited{get{...}set{
publicvirtualAttributeTargetsValidOn{get{
publicenumAttributeTargets{Assembly=
All=Assembly|Module|Class|Struct|Enum
Conditional属性
namespaceSystem.Diagnostics{[AttributeUsage(A
publicstringConditionString{get{...}}}
条件方法
条件方法必须是class-declaration或struct-declaration中的方
条件方法必须具有void返回类型。
不能用override修饰符标记条件方法。但是,可以用virtual修饰符标记条件方法。此类
条件方法不能是接口方法的实现。否则将发生编译时错误。
#defineDEBUG
usingSystem;usingSystem.Diagnostics;
classClass1{[Conditional("DEBUG")]public
classClass2{publicstaticvoidTest(){Cl
usingSystem.Diagnostics;
classClass1{[Conditional("DEBUG")]public
#defineDEBUG
classClass2{publicstaticvoidG(){Class
#undefDEBUG
classClass3{publicstaticvoidH(){Class
usingSystem;usingSystem.Diagnostics;
classClass1{[Conditional("DEBUG")]public
usingSystem;
classClass2:Class1{publicoverridevoidM()
#defineDEBUG
usingSystem;
classClass3{publicstaticvoidTest(){Cl
条件属性类
usingSystem;usingSystem.Diagnostics;[Condition
usingSystem;usingSystem.Diagnostics;
[Conditional(“DEBUG”)]
publicclassTestAttribute:Attribute{}
#defineDEBUG
[Test]//TestAttributeisspecified
classClass1{}
#undefDEBUG
[Test]//TestAttributeisnotspecified
classClass2{}
Obsolete属性
namespaceSystem{[AttributeUsage(Attribute
publicObsoleteAttribute(stringmessage){...}
publicObsoleteAttribute(stringmessage,boole
publicstringMessage{get{...}}
publicboolIsError{get{...}}}}
[Obsolete("Thisclassisobsolete;useclassBins
classB{publicvoidF(){}}
classTest{staticvoidMain(){Aa=newA
交互操作的属性
与COM和Win32组件的交互操作
与其他.NET语言的交互操作
IndexerName属性
namespaceSystem.Runtime.CompilerServices.CSharp{
publicstringValue{get{...}}}}
不安全代码
不安全上下文
类、结构、接口或委托的声明可以包含一个unsafe修饰符,在这种情况下,该类型声明的整个文本范围
在字段、方法、属性、事件、索引器、运算符、实例构造函数、析构函数或静态构造函数的声明中,也可以包含一
unsafe-statement使得可以在block内使用不安全上下文。该语句关联的bloc
class-modifier:...unsafe
struct-modifier:...unsafe
interface-modifier:...unsafe
delegate-modifier:...unsafe
field-modifier:...unsafe
method-modifier:...unsafe
property-modifier:...unsafe
event-modifier:...unsafe
indexer-modifier:...unsafe
operator-modifier:...unsafe
constructor-modifier:...unsafe
destructor-declaration:attributesoptexternopt
static-constructor-modifiers:externoptunsafeop
embedded-statement:...unsafe-statement
unsafe-statement:unsafeblock
publicunsafestructNode{publicintValue;
publicstructNode{publicintValue;public
publicclassA{publicunsafevirtualvoidF()
publicclassB:A{publicoverridevoidF(){
publicunsafeclassA{publicvirtualvoidF(ch
publicclassB:A{publicunsafeoverridevoid
指针类型
type:...pointer-type
pointer-type:unmanaged-type*void*
unmanaged-type:type
sbyte、byte、short、ushort、int、uint、long、ulong、char、f
任何enum-type。
任何pointer-type。
任何由用户定义的只包含unmanaged-types字段的struct-type。
示例
说明
byte*
指向byte的指针
char*
指向char的指针
int**
指向int的指针的指针
int*[]
一维数组,它的元素是指向int的指针
void*
指向未知类型的指针
int*pi,pj;//NOTasint*pi,*pj;
usingSystem;
classTest{staticintvalue=20;
unsafestaticvoidF(outint*pi1,refint*pi2)
fixed(int*pj=&value){//...pi2=
staticvoidMain(){inti=10;unsafe{
F(outpx1,refpx2);
Console.WriteLine("*px1={0},*px2={1}",
unsafestaticint*Find(int*pi,intsize,intval
*运算符可用于执行指针间接寻址(第
->运算符可用于通过指针访问结构的成员(第
[]运算符可用于索引指针(第
&运算符可用于获取变量的地址(第
++和--运算符可以用于递增和递减指针(第
+和-运算符可用于执行指针算术运算(第
==、!=、<、>、<=和=>运算符可以用于比较指针(第
stackalloc运算符可用于从调用堆栈中分配内存(第
fixed语句可用于临时固定一个变量,以便可以获取它的地址(第
固定和可移动变量
用引用局部变量或值参数的simple-name(第
用V.I形式的member-access(第
用*P形式的pointer-indirection-expression(第
指针转换
从任何pointer-type到void*类型。
从null文本到任何pointer-type。
从任何pointer-type到任何其他pointer-type。
从sbyte、byte、short、ushort、int、uint、long或ulong到任
从任何pointer-type到sbyte、byte、short、ushort、int、uin
从任何pointer-type到void*类型。
charc='A';char*pc=&c;void*pv=pc;int*p
usingSystem;
classTest{unsafestaticvoidMain(){
指针数组
从任意array-type到System.Array及其实现的接口的隐式引用转换(第
从一维数组类型S[]到System.Collections.Generic.IList
从System.Array及其实现的接口到任意array-type的显式引用转换(第
从System.Collections.Generic.IList及其基接口到一维数组类型
表达式中的指针
primary-no-array-creation-expression:...pointer-
unary-expression:...pointer-indirection-expressi
指针间接寻址
pointer-indirection-expression:*unary-expressi
指针成员访问
pointer-member-access:primary-expression->i
usingSystem;
structPoint{publicintx;publicinty;
publicoverridestringToString(){return"(
classTest{staticvoidMain(){Pointpoint
classTest{staticvoidMain(){Pointpoint
指针元素访问
pointer-element-access:primary-no-array-creation-
classTest{staticvoidMain(){unsafe{
classTest{staticvoidMain(){unsafe{
address-of运算符
addressof-expression:&unary-expression
usingSystem;
classTest{staticvoidMain(){inti;u
指针递增和递减
T*operator++(T*x);
T*operator--(T*x);
指针算术运算
T*operator+(T*x,inty);T*operator+(T*x,ui
T*operator+(intx,T*y);T*operator+(uintx,
T*operator–(T*x,inty);T*operator–(T*x,ui
longoperator–(T*x,T*y);
usingSystem;
classTest{
staticvoidMain(){unsafe{int*values
p-q=-14q-p=14
指针比较
booloperator==(void*x,void*y);
booloperator!=(void*x,void*y);
booloperator<(void*x,void*y);
booloperator>(void*x,void*y);
booloperator<=(void*x,void*y);
booloperator>=(void*x,void*y);
sizeof运算符
sizeof-expression:sizeof(unmanaged-type)
表达式
结果
sizeof(sbyte)
1
sizeof(byte)
1
sizeof(short)
2
sizeof(ushort)
2
sizeof(int)
4
sizeof(uint)
4
sizeof(long)
8
sizeof(ulong)
8
sizeof(char)
2
sizeof(float)
4
sizeof(double)
8
sizeof(bool)
1
fixed语句
embedded-statement:...fixed-statement
fixed-statement:fixed(pointer-typefixed-
fixed-pointer-declarators:fixed-pointer-declarato
fixed-pointer-declarator:identifier=fixed-p
fixed-pointer-initializer:&variable-reference
“&”标记,后接一个variable-reference(第
元素类型为非托管类型T的array-type的表达式,前提是类型T*可隐式转换为fix
string类型的表达式,前提是类型char*可以隐式转换为fixed语句中给出的指针类型
引用可移动变量的固定大小缓冲区成员的simple-name或member-access,前提是
classTest{staticintx;inty;
unsafestaticvoidF(int*p){*p=1;}
staticvoidMain(){Testt=newTest();
classTest{staticstringname="xx";
unsafestaticvoidF(char*p){for(inti=
staticvoidMain(){unsafe{fixed(char
usingSystem;
classTest{staticvoidMain(){int[,,]a=
for(inti=0;i<2;++i)for(intj=0;
[0,0,0]=0[0,0,1]=1[0,0,2]=2[0,0,3]=
classTest{unsafestaticvoidFill(int*p,int
staticvoidMain(){int[]a=newint[100];
unsafestructFont{publicintsize;publicf
classTest{unsafestaticvoidPutString(string
Fontf;
unsafestaticvoidMain(){Testtest=new
固定大小缓冲区
固定大小缓冲区的声明
struct-member-declaration:…fixed-size-buffer-dec
fixed-size-buffer-declaration:attributesoptfix
fixed-size-buffer-modifiers:fixed-size-buffer-mod
fixed-size-buffer-modifier:newpublicprotectedi
buffer-element-type:type
fixed-size-buffer-declarators:fixed-size-buffer-d
fixed-size-buffer-declarator:identifier[con
unsafestructA{publicfixedintx[5],y[10],
unsafestructA{publicfixedintx[5];pub
表达式中的固定大小缓冲区
如果表达式E.I不属于不安全上下文,则发生编译时错误。
如果E归类为值类别,则发生编译时错误。
否则,如果E为可移动变量(第18.3节)并且表达式E.I不是fixed-pointer
否则,E引用固定变量,并且该表达式的结果为指向E中的固定大小缓冲区成员I的第一个元素的指针
unsafestructFont{publicintsize;publicf
classTest{unsafestaticvoidPutString(string
unsafestaticvoidMain(){Fontf;f.si
明确赋值检查
堆栈分配
local-variable-initializer:…stackalloc-initializ
stackalloc-initializer:stackallocunmanaged-typ
usingSystem;
classTest{staticstringIntToString(intvalue
staticvoidMain(){Console.WriteLine(IntToS
动态内存分配
usingSystem;usingSystem.Runtime.InteropServices
publicunsafeclassMemory{//Handleforthep
staticintph=GetProcessHeap();
//Privateinstanceconstructortopreventinsta
privateMemory(){}
//Allocatesamemoryblockofthegivensize.T
publicstaticvoid*Alloc(intsize){void*r
//Copiescountbytesfromsrctodst.Thesourc
publicstaticvoidCopy(void*src,void*dst,in
//Freesamemoryblock.
publicstaticvoidFree(void*block){if(!H
//Re-allocatesamemoryblock.Ifthereallocat
publicstaticvoid*ReAlloc(void*block,intsiz
//Returnsthesizeofamemoryblock.
publicstaticintSizeOf(void*block){intr
//HeapAPIflags
constintHEAP_ZERO_MEMORY=0x00000008;
//HeapAPIfunctions
[DllImport("kernel32")]staticexternintGetP
[DllImport("kernel32")]staticexternvoid*He
[DllImport("kernel32")]staticexternboolHea
[DllImport("kernel32")]staticexternvoid*He
[DllImport("kernel32")]staticexternintHeap
classTest{staticvoidMain(){unsafe{
文档注释
简介
single-line-doc-comment:///input-charactersopt
delimited-doc-comment:/**delimited-comment-cha
///ClassPointmodelsapointin
标记用于描述参数。如果使用这样的标记,文档生成器必须验证指定参数是否存在以及文档注释 cref属性可以附加到任意标记,以提供对代码元素的参考。文档生成器必须验证此代码元素是否存在。如果
标记旨在标出可由文档查看器显示的有关类型或成员的额外信息。
标记表示应该包含的来自外部XML文件的信息。
建议的标记
标记
章节
用途
A.2.1
将文本设置为类似代码的字体
A.2.2
将一行或多行源代码或程序输出设置为某种字体
A.2.3
表示所含的是示例
A.2.4
标识方法可能引发的异常
A.2.5
包括来自外部文件的XML
A.2.6
创建列表或表
A.2.7
用于将结构添加到文本中
A.2.8
描述方法或构造函数的参数
A.2.9
确认某个单词是参数名
A.2.10
描述成员的安全性和访问权限
A.2.11
描述有关类型的更多信息
A.2.12
描述方法的返回值
A.2.13
指定链接
A.2.14
生成“请参见”项
A.2.15
描述类型或类型的成员
A.2.16
描述属性
描述泛型类型参数
确认某个单词是类型参数名
text
///ClassPointmodelsapointin
publicclassPoint{//...}
sourcecodeorprogramoutput
///Thismethodchangesthepoint'slocat
publicvoidTranslate(intxor,intyor){X+=x
description
description
publicclassDataBaseOperations{///
file="filename"
path="xpath"
///
//////Containsalistofintegers.
publicclassMyClass{///Hereisane
///ThisistheentrypointofthePoint
///Thismethodchangesthepoint'slocat
///Thisconstructorinitializesthenew
publicPoint(intxor,intyor){X=xor;Y=
publicstaticvoidTest(){//...}
description
///ClassPointmodelsapointin
description
///Reportapoint'slocationasastring
///Thismethodchangesthepoint'slocat
///Thismethodchangesthepoint'slocat
///ThismethoddetermineswhethertwoPo
description
///Thisconstructorinitializesthenew
propertydescription
///PropertyXrepresentsthepoint'
description
///Agenericlistclass.///<
///Thismethodfetchesdataandreturns
处理文档文件
ID字符串格式
不在字符串中放置空白。
字符串的第一部分通过单个字符后接一个冒号来标识被标识成员的种类。定义以下几种成员:
字符
说明
E
事件
F
字段
M
方法(包括构造函数、析构函数和运算符)
N
命名空间
P
属性(包括索引器)
T
类型(如类、委托、枚举、接口和结构)
!
错误字符串;字符串的其他部分提供有关错误的信息。例如,文档生成器对无法解析的链接生成错误信息。
字符串的第二部分是元素的完全限定名,从命名空间的根开始。元素的名称、包含着它的类型和命名空间都以句点
对于带有参数的方法和属性,接着是用括号括起来的参数列表。对于那些不带参数的方法和属性,则省略括号。多
参数由其基于完全限定名的文档名称来表示,并做如下修改:
表示泛型类型的实参附加了一个“’”字符,后接类型形参个数。
具有out或ref修饰符的参数在其类型名后接有@符。对于由值传递或通过params传
数组参数表示为[lowerbound:size,…,lowerbound:siz
指针类型为非void的参数用类型名后面跟一个*的形式来表示。void指针用类型名Syst
引用在类型上定义的泛型类型形参的实参使用“`”字符进行编码,后接类型形参从零开始的索引。
引用在方法中定义的泛型类型形参的实参使用双反引号“``”,而不使用用于类型的“`”。
引用构造泛型类型的参数使用该泛型类型进行编码,后面依次跟“{”、逗号分隔的类型参数列表以及“}”。
ID字符串示例
类型用它们的完全限定名来表示,并使用泛型信息进行扩充:
enumColor{Red,Blue,Green}
namespaceAcme{interfaceIProcess{...}
structValueType{...}
classWidget:IProcess{publicclassNeste
publicinterfaceIMenuItem{...}
publicdelegatevoidDel(inti);
publicenumDirection{North,South,East,Wes
classMyList{classHelper{...}
"T:Color""T:Acme.IProcess""T:Acme.ValueType""T:
字段用它们的完全限定名来表示:
namespaceAcme{structValueType{private
classWidget:IProcess{publicclassNeste
privatestringmessage;privatestaticColor
"F:Acme.ValueType.total""F:Acme.Widget.NestedClas
构造函数。
namespaceAcme{classWidget:IProcess{s
publicWidget(){...}
publicWidget(strings){...}}}
"M:Acme.Widget.#cctor""M:Acme.Widget.#ctor""M:Ac
析构函数。
namespaceAcme{classWidget:IProcess{~
"M:Acme.Widget.Finalize"
方法。
namespaceAcme{structValueType{public
classWidget:IProcess{publicclassNeste
publicstaticvoidM0(){...}publicvoidM1
classMyList{publicvoidTest(Tt){}
classUseList{publicvoidProcess(MyList<
"M:Acme.ValueType.M(System.Int32)""M:Acme.Widget.
属性和索引器。
namespaceAcme{classWidget:IProcess{p
"P:Acme.Widget.Width""P:Acme.Widget.Item(System.I
事件。
namespaceAcme{classWidget:IProcess{p
"E:Acme.Widget.AnEvent"
一元运算符。
namespaceAcme{classWidget:IProcess{p
"M:Acme.Widget.op_UnaryPlus(Acme.Widget)"
二元运算符。
namespaceAcme{classWidget:IProcess{p
"M:Acme.Widget.op_Addition(Acme.Widget,Acme.Widget
转换运算符具有一个尾随“~”,然后再跟返回类型。
namespaceAcme{classWidget:IProcess{p
"M:Acme.Widget.op_Explicit(Acme.Widget)~System.Int
示例
C#源代码
namespaceGraphics{///ClassPoint<
///Instancevariablexrepresen
///Instancevariableyrepresen
///PropertyXrepresentsthepoin
///PropertyYrepresentsthepoin
///Thisconstructorinitializesthene
///Thisconstructorinitializesthene
///Thismethodchangesthepoint'sloc
///Thismethodchangesthepoint'sloc
///Thismethoddetermineswhethertwo
if(this==o){returntrue;}
if(GetType()==o.GetType()){Pointp=(
///Reportapoint'slocationasastri
///Thisoperatordetermineswhethertw
///Thisoperatordetermineswhethertw
///ThisistheentrypointofthePoin
产生的XML
语法
词法文法
input:input-sectionopt
input-section:input-section-partinput-section
input-section-part:input-elementsoptnew-linep
input-elements:input-elementinput-elementsinp
input-element:whitespacecommenttoken
行结束符
new-line:回车符(U+000D)换行符(U+000A)回车符(U+000D)后
注释
comment:single-line-commentdelimited-comment
single-line-comment://input-charactersopt
input-characters:input-characterinput-characters
input-character:除new-line-character之外的任何Unicod
new-line-character:回车符(U+000D)换行符(U+000A)下一行符
delimited-comment:/*delimited-comment-textopt
delimited-comment-text:delimited-comment-section
delimited-comment-section:/asterisksoptnot-sl
asterisks:*asterisks*
not-slash-or-asterisk:除/或*之外的任何Unicode字符
空白
whitespace:任何含Unicode类Zs的字符水平制表符(U+0009)垂直
标记
token:identifierkeywordinteger-literalreal-lit
Unicode字符转义序列
unicode-escape-sequence:\uhex-digithex-digi
标识符
identifier:available-identifier@identifier-or
available-identifier:不是keyword的identifier-or-k
identifier-or-keyword:identifier-start-character
identifier-start-character:letter-character_(下划线
identifier-part-characters:identifier-part-charac
identifier-part-character:letter-characterdecima
letter-character:类Lu、Ll、Lt、Lm、Lo或Nl的Unicode
combining-character:类Mn或Mc的Unicode字符表示类Mn
decimal-digit-character:类Nd的Unicode字符表示类Nd
connecting-character:类Pc的Unicode字符表示类Pc的
formatting-character:类Cf的Unicode字符表示类Cf的
关键字
keyword:以下关键字之一abstractasbaseboolbre
文本
literal:boolean-literalinteger-literalreal-lite
boolean-literal:truefalse
integer-literal:decimal-integer-literalhexadecim
decimal-integer-literal:decimal-digitsinteger-
decimal-digits:decimal-digitdecimal-digitsdec
decimal-digit:0123456789之一
integer-type-suffix:UuLlULUluLul
hexadecimal-integer-literal:0xhex-digitsint
hex-digits:hex-digithex-digitshex-digit
hex-digit:0123456789ABC
real-literal:decimal-digits.decimal-digits
exponent-part:esignoptdecimal-digitsEsi
sign:+-之一
real-type-suffix:FfDdMm之一
character-literal:'character'
character:single-charactersimple-escape-sequence
single-character:除'(U+0027)、\(U+005C)和new-li
simple-escape-sequence:\'\"\\\0\a\b\
hexadecimal-escape-sequence:\xhex-digithex-
string-literal:regular-string-literalverbatim-st
regular-string-literal:"regular-string-literal
regular-string-literal-characters:regular-string-
regular-string-literal-character:single-regular-s
single-regular-string-literal-character:除"(U+00
verbatim-string-literal:@"verbatim-string-lit
verbatim-string-literal-characters:verbatim-strin
verbatim-string-literal-character:single-verbatim
single-verbatim-string-literal-character:除"之外的任
quote-escape-sequence:""
null-literal:null
运算符和标点符号
operator-or-punctuator:以下符号之一{}[]().
right-shift:>|>
right-shift-assignment:>|>=
预处理指令
pp-directive:pp-declarationpp-conditionalpp-lin
conditional-symbol:除true或false外的任何identifier
pp-expression:whitespaceoptpp-or-expression
pp-or-expression:pp-and-expressionpp-or-expressi
pp-and-expression:pp-equality-expressionpp-and-e
pp-equality-expression:pp-unary-expressionpp-equ
pp-unary-expression:pp-primary-expression!whi
pp-primary-expression:truefalseconditional-symb
pp-declaration:whitespaceopt#whitespaceopt
pp-new-line:whitespaceoptsingle-line-commentop
pp-conditional:pp-if-sectionpp-elif-sectionsop
pp-if-section:whitespaceopt#whitespaceopt
pp-elif-sections:pp-elif-sectionpp-elif-sections
pp-elif-section:whitespaceopt#whitespaceopt
pp-else-section:whitespaceopt#whitespaceopt
pp-endif:whitespaceopt#whitespaceoptendi
conditional-section:input-sectionskipped-section
skipped-section:skipped-section-partskipped-sect
skipped-section-part:skipped-charactersoptnew-
skipped-characters:whitespaceoptnot-number-sig
not-number-sign:除#外的任何input-character
pp-diagnostic:whitespaceopt#whitespaceopt
pp-message:new-linewhitespaceinput-characters
pp-region:pp-start-regionconditional-sectionop
pp-start-region:whitespaceopt#whitespaceopt
pp-end-region:whitespaceopt#whitespaceopt
pp-line:whitespaceopt#whitespaceoptline
line-indicator:decimal-digitswhitespacefile
file-name:"file-name-characters"
file-name-characters:file-name-characterfile-nam
file-name-character:除"之外的任何input-character
pp-pragma:whitespaceopt#whitespaceoptpra
pragma-body:pragma-warning-body
pragma-warning-body:warningwhitespacewarnin
warning-action:disablerestore
warning-list:decimal-digitswarning-listwhites
句法文法
基本概念
namespace-name:namespace-or-type-name
type-name:namespace-or-type-name
namespace-or-type-name:identifiertype-argument
类型
type:value-typereference-typetype-parameter
value-type:struct-typeenum-type
struct-type:type-namesimple-typenullable-type
simple-type:numeric-typebool
numeric-type:integral-typefloating-point-typede
integral-type:sbytebyteshortushortintuintlo
floating-point-type:floatdouble
nullable-type:non-nullable-value-type?
non-nullable-value-type:type
enum-type:type-name
reference-type:class-typeinterface-typearray-ty
class-type:type-nameobjectstring
interface-type:type-name
array-type:non-array-typerank-specifiers
non-array-type:type
rank-specifiers:rank-specifierrank-specifiers
rank-specifier:[dim-separatorsopt]
dim-separators:,dim-separators,
delegate-type:type-name
type-argument-list:
type-arguments:type-argumenttype-arguments,
type-argument:type
type-parameter:identifier
变量
variable-reference:expression
表达式
argument-list:argumentargument-list,argume
argument:expressionrefvariable-referenceout
primary-expression:primary-no-array-creation-exp
primary-no-array-creation-expression:literalsimp
simple-name:identifiertype-argument-listopt
parenthesized-expression:(expression)
member-access:primary-expression.identifier
predefined-type:以下类型之一boolbytechardecimal
invocation-expression:primary-expression(ar
element-access:primary-no-array-creation-expressi
expression-list:expressionexpression-list,
this-access:this
base-access:base.identifierbase[expr
post-increment-expression:primary-expression++
post-decrement-expression:primary-expression--
object-creation-expression:newtype(argum
object-or-collection-initializer:object-initializ
object-initializer:{member-initializer-listopt
member-initializer-list:member-initializermember
member-initializer:identifier=initializer-v
initializer-value:expressionobject-or-collection
collection-initializer:{element-initializer-li
element-initializer-list:element-initializerelem
element-initializer:non-assignment-expression{
array-creation-expression:newnon-array-type
delegate-creation-expression:newdelegate-type
anonymous-object-creation-expression:newanonym
anonymous-object-initializer:{member-declarato
member-declarator-list:member-declaratormember-d
member-declarator:simple-namemember-accessident
typeof-expression:typeof(type)typeof
unbound-type-name:identifiergeneric-dimension-
generic-dimension-specifier:
commas:,commas,
checked-expression:checked(expression)
unchecked-expression:unchecked(expression
default-value-expression:default(type)
unary-expression:primary-expression+unary-exp
pre-increment-expression:++unary-expression
pre-decrement-expression:--unary-expression
cast-expression:(type)unary-expression
multiplicative-expression:unary-expressionmultip
additive-expression:multiplicative-expressionadd
shift-expression:additive-expressionshift-expre
relational-expression:shift-expressionrelational
equality-expression:relational-expressionequalit
and-expression:equality-expressionand-expression
exclusive-or-expression:and-expressionexclusive-
inclusive-or-expression:exclusive-or-expressioni
conditional-and-expression:inclusive-or-expressio
conditional-or-expression:conditional-and-express
null-coalescing-expression:conditional-or-express
conditional-expression:null-coalescing-expression
lambda-expression:anonymous-function-signature
anonymous-method-expression:delegateexplicit-a
anonymous-function-signature:explicit-anonymous-f
explicit-anonymous-function-signature:(explici
explicit-anonymous-function-parameter-listexplici
explicit-anonymous-function-parameter:anonymous-f
anonymous-function-parameter-modifier:refout
implicit-anonymous-function-signature:(implici
implicit-anonymous-function-parameter-listimplici
implicit-anonymous-function-parameter:identifier
anonymous-function-body:expressionblock
query-expression:from-clausequery-body
from-clause:fromtypeoptidentifierinex
query-body:query-body-clausesoptselect-or-grou
query-body-clauses:query-body-clausequery-body-c
query-body-clause:from-clauselet-clausewhere-cl
let-clause:letidentifier=expression
where-clause:whereboolean-expression
join-clause:jointypeoptidentifierinex
join-into-clause:jointypeoptidentifierin
orderby-clause:orderbyorderings
orderings:orderingorderings,ordering
ordering:expressionordering-directionopt
ordering-direction:ascendingdescending
select-or-group-clause:select-clausegroup-clause
select-clause:selectexpression
group-clause:groupexpressionbyexpression
query-continuation:intoidentifierquery-body
assignment:unary-expressionassignment-operator
assignment-operator:=+=-=*=/=%=&=|=^=<<=
expression:non-assignment-expressionassignment
non-assignment-expression:conditional-expression
constant-expression:expression
boolean-expression:expression
语句
statement:labeled-statementdeclaration-statement
embedded-statement:blockempty-statementexpressi
block:{statement-listopt}
statement-list:statementstatement-liststateme
empty-statement:;
labeled-statement:identifier:statement
declaration-statement:local-variable-declaration
local-variable-declaration:local-variable-type
local-variable-type:typevar
local-variable-declarators:local-variable-declara
local-variable-declarator:identifieridentifier
local-variable-initializer:expressionarray-initi
local-constant-declaration:consttypeconstan
constant-declarators:constant-declaratorconstant
constant-declarator:identifier=constant-exp
expression-statement:statement-expression;
statement-expression:invocation-expressionobject
selection-statement:if-statementswitch-statement
if-statement:if(boolean-expression)em
switch-statement:switch(expression)sw
switch-block:{switch-sectionsopt}
switch-sections:switch-sectionswitch-sections
switch-section:switch-labelsstatement-list
switch-labels:switch-labelswitch-labelsswitch
switch-label:caseconstant-expression:defau
iteration-statement:while-statementdo-statement
while-statement:while(boolean-expression
do-statement:doembedded-statementwhile(
for-statement:for(for-initializeropt;
for-initializer:local-variable-declarationstatem
for-condition:boolean-expression
for-iterator:statement-expression-list
statement-expression-list:statement-expressionst
foreach-statement:foreach(local-variable-ty
jump-statement:break-statementcontinue-statement
break-statement:break;
continue-statement:continue;
goto-statement:gotoidentifier;gotocase
return-statement:returnexpressionopt;
throw-statement:throwexpressionopt;
try-statement:tryblockcatch-clausestryb
catch-clauses:specific-catch-clausesgeneral-ca
specific-catch-clauses:specific-catch-clausespec
specific-catch-clause:catch(class-typeid
general-catch-clause:catchblock
finally-clause:finallyblock
checked-statement:checkedblock
unchecked-statement:uncheckedblock
lock-statement:lock(expression)embedd
using-statement:using(resource-acquisition
resource-acquisition:local-variable-declaratione
yield-statement:yieldreturnexpression;y
命名空间
compilation-unit:extern-alias-directivesoptusi
namespace-declaration:namespacequalified-ident
qualified-identifier:identifierqualified-identif
namespace-body:{extern-alias-directivesoptu
extern-alias-directives:extern-alias-directiveex
extern-alias-directive:externaliasidentifie
using-directives:using-directiveusing-directives
using-directive:using-alias-directiveusing-names
using-alias-directive:usingidentifier=na
using-namespace-directive:usingnamespace-name
namespace-member-declarations:namespace-member-de
namespace-member-declaration:namespace-declaratio
type-declaration:class-declarationstruct-declara
qualified-alias-member:identifier::identifi
类
class-declaration:attributesoptclass-modifiers
class-modifiers:class-modifierclass-modifiers
class-modifier:newpublicprotectedinternalpriv
type-parameter-list:
type-parameters:attributesopttype-parameterty
type-parameter:identifier
class-base::class-type:interface-type-list
interface-type-list:interface-typeinterface-type
type-parameter-constraints-clauses:type-parameter
type-parameter-constraints-clause:wheretype-pa
type-parameter-constraints:primary-constraintsec
primary-constraint:class-typeclassstruct
secondary-constraints:interface-typetype-paramet
constructor-constraint:new()
class-body:{class-member-declarationsopt}
class-member-declarations:class-member-declaratio
class-member-declaration:constant-declarationfie
constant-declaration:attributesoptconstant-mod
constant-modifiers:constant-modifierconstant-mod
constant-modifier:newpublicprotectedinternalp
constant-declarators:constant-declaratorconstant
constant-declarator:identifier=constant-exp
field-declaration:attributesoptfield-modifiers
field-modifiers:field-modifierfield-modifiers
field-modifier:newpublicprotectedinternalpriv
variable-declarators:variable-declaratorvariable
variable-declarator:identifieridentifier=v
variable-initializer:expressionarray-initializer
method-declaration:method-headermethod-body
method-header:attributesoptmethod-modifiersopt
method-modifiers:method-modifiermethod-modifiers
method-modifier:newpublicprotectedinternalpri
return-type:typevoid
member-name:identifierinterface-type.ident
method-body:block;
formal-parameter-list:fixed-parametersfixed-para
fixed-parameters:fixed-parameterfixed-parameters
fixed-parameter:attributesoptparameter-modifie
parameter-modifier:refoutthis
parameter-array:attributesoptparamsarray-ty
property-declaration:attributesoptproperty-mod
property-modifiers:property-modifierproperty-mod
property-modifier:newpublicprotectedinternalp
member-name:identifierinterface-type.ident
accessor-declarations:get-accessor-declaration
get-accessor-declaration:attributesoptaccessor
set-accessor-declaration:attributesoptaccessor
accessor-modifier:protectedinternalprivateprot
accessor-body:block;
event-declaration:attributesoptevent-modifiers
event-modifiers:event-modifierevent-modifiers
event-modifier:newpublicprotectedinternalpriv
event-accessor-declarations:add-accessor-declarat
add-accessor-declaration:attributesoptaddbl
remove-accessor-declaration:attributesoptremov
indexer-declaration:attributesoptindexer-modif
indexer-modifiers:indexer-modifierindexer-modifi
indexer-modifier:newpublicprotectedinternalpr
indexer-declarator:typethis[formal-param
operator-declaration:attributesoptoperator-mod
operator-modifiers:operator-modifieroperator-mod
operator-modifier:publicstaticextern
operator-declarator:unary-operator-declaratorbin
unary-operator-declarator:typeoperatoroverloa
overloadable-unary-operator:以下运算符之一+-!~
binary-operator-declarator:typeoperatoroverlo
overloadable-binary-operator:+-*/%&|^<
conversion-operator-declarator:implicitoperato
operator-body:block;
constructor-declaration:attributesoptconstruct
constructor-modifiers:constructor-modifierconstr
constructor-modifier:publicprotectedinternalpr
constructor-declarator:identifier(formal-pa
constructor-initializer::base(argument-l
constructor-body:block;
static-constructor-declaration:attributesoptst
static-constructor-modifiers:externoptstaticsta
static-constructor-body:block;
destructor-declaration:attributesoptexternopt
destructor-body:block;
结构
struct-declaration:attributesoptstruct-modifie
struct-modifiers:struct-modifierstruct-modifiers
struct-modifier:newpublicprotectedinternalpri
struct-interfaces::interface-type-list
struct-body:{struct-member-declarationsopt}
struct-member-declarations:struct-member-declarat
struct-member-declaration:constant-declarationfi
数组
array-type:non-array-typerank-specifiers
non-array-type:type
rank-specifiers:rank-specifierrank-specifiers
rank-specifier:[dim-separatorsopt]
dim-separators:,dim-separators,
array-initializer:{variable-initializer-listop
variable-initializer-list:variable-initializerva
variable-initializer:expressionarray-initializer
接口
interface-declaration:attributesoptinterface-mo
interface-modifiers:interface-modifierinterface-
interface-modifier:newpublicprotectedinternal
interface-base::interface-type-list
interface-body:{interface-member-declarationso
interface-member-declarations:interface-member-de
interface-member-declaration:interface-method-dec
interface-method-declaration:attributesoptnewo
interface-property-declaration:attributesoptne
interface-accessors:attributesoptget;attri
interface-event-declaration:attributesoptnewop
interface-indexer-declaration:attributesoptnew
枚举
enum-declaration:attributesoptenum-modifiersop
enum-base::integral-type
enum-body:{enum-member-declarationsopt}{
enum-modifiers:enum-modifierenum-modifiersenu
enum-modifier:newpublicprotectedinternalpriva
enum-member-declarations:enum-member-declaration
enum-member-declaration:attributesoptidentifie
委托
delegate-declaration:attributesoptdelegate-mod
delegate-modifiers:delegate-modifierdelegate-mod
delegate-modifier:newpublicprotectedinternalp
属性
global-attributes:global-attribute-sections
global-attribute-sections:global-attribute-sectio
global-attribute-section:[global-attribute-tar
global-attribute-target-specifier:global-attribut
global-attribute-target:assemblymodule
attributes:attribute-sections
attribute-sections:attribute-sectionattribute-se
attribute-section:[attribute-target-specifiero
attribute-target-specifier:attribute-target:
attribute-target:fieldeventmethodparampropert
attribute-list:attributeattribute-list,att
attribute:attribute-nameattribute-argumentsopt
attribute-name:type-name
attribute-arguments:(positional-argument-listo
positional-argument-list:positional-argumentposi
positional-argument:attribute-argument-expression
named-argument-list:named-argumentnamed-argument
named-argument:identifier=attribute-argumen
attribute-argument-expression:expression
不安全代码的语法扩展
class-modifier:...unsafe
struct-modifier:...unsafe
interface-modifier:...unsafe
delegate-modifier:...unsafe
field-modifier:...unsafe
method-modifier:...unsafe
property-modifier:...unsafe
event-modifier:...unsafe
indexer-modifier:...unsafe
operator-modifier:...unsafe
constructor-modifier:...unsafe
destructor-declaration:attributesoptexternopt
static-constructor-modifiers:externoptunsafeop
embedded-statement:...unsafe-statement
unsafe-statement:unsafeblock
type:...pointer-type
pointer-type:unmanaged-type*void*
unmanaged-type:type
primary-no-array-creation-expression:...pointer-
unary-expression:...pointer-indirection-expressi
pointer-indirection-expression:*unary-expressi
pointer-member-access:primary-expression->i
pointer-element-access:primary-no-array-creation-
addressof-expression:&unary-expression
sizeof-expression:sizeof(unmanaged-type)
embedded-statement:...fixed-statement
fixed-statement:fixed(pointer-typefixed-
fixed-pointer-declarators:fixed-pointer-declarato
fixed-pointer-declarator:identifier=fixed-p
fixed-pointer-initializer:&variable-reference
struct-member-declaration:…fixed-size-buffer-dec
fixed-size-buffer-declaration:attributesoptfix
fixed-size-buffer-modifiers:fixed-size-buffer-mod
fixed-size-buffer-modifier:newpublicprotectedi
buffer-element-type:type
fixed-size-buffer-declarators:fixed-size-buffer-d
fixed-size-buffer-declarator:identifier[con
local-variable-initializer:…stackalloc-initializ
stackalloc-initializer:stackallocunmanaged-typ
参考资料