Вы находитесь на странице: 1из 896

32.973.2-018.

1
004.43
55

.
55 CLR via C#. Microsoft .NET Framework 4.5
C#. 4- . .: , 2013. 896 .: . ( -).

ISBN 978-5-496-00433-6
,
, (CLR) Microsoft .NET Framework 4.5. ,
.NET Framework Microsoft,
- ,
Microsoft Silverlight, ASP.NET, Windows Presentation Foundation . .

.NET Framework 4.5, Visual Studio 2012 C# 5.0.
12+ ( 12 . 29 2010 .
436-.)

32.973.2-018.1
004.43

Microsoft Press. .
.
, , , . , , ,
.

ISBN 978-0735667457 .

Authorized Russian translation of the English edition of titled CLR via C#,
4 edition 2012 Jeffrey Richter (ISBN 9780735667457). This translation
is published and sold by permission of OReilly Media, Inc., which owns or
controls all rights to publish and sell the same.

ISBN 978-5-496-00433-6

, 2013

, , 2013

. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 22
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 24

I. CLR
1. CLR . .. .. .. .. .. .. .. .. .. .. 28
2. , ,
. .. .. .. .. .. .. .. .. .. .. .. .. . 58
3.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 94

II.
4. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 122
5. , . .. .. .. .. .. 142
6. . .. .. .. .. .. .. .. .. .. .. 186
7. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..210
8. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 215
9. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 245
10. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..263
11. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 286
12. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 302
13. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 333

III.
14. , . .. .. .. .. .. .. .. .. .. 356
15. . .. .. .. .. .. .. .. .. .. 403
16. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..416
17. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 434
18. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 464
19. Null- . .. .. .. .. .. .. .. .. .. .. ..485

IV.
20. . .. .. .. .. .. .. .. ..496
21.
(). .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 554
22. CLR . .. .. .. .. .. .. .. .. .. .. 606
23. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. 636
24. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 666
25. WinRT . .. .. .. .. .. .. ..698

V.
26. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..724
27. . .. .. .. .. .. .. .747
28. - . .. .. .. .. .. .. .. .. 787
29.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 820
30. . .. 854

. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..893

. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 22
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 24
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 26

I. CLR
1. CLR . .. .. .. .. .. .. .. .. .. .. 28
. .. .. .. .. .. .. .. .. .. .. 28
. .. .. .. .. .. .. .. .. .. .. .. .. .. . 32
CLR. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 34
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 37
IL- . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 44
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 45
IL . .. .. .. .. .. .. .. .. .. .. .. .. . 46
NGen.exe. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
FCL . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
CTS. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
CLS . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .

47
47
49
52
57

2. , ,
. .. .. .. .. .. .. .. .. .. .. .. .. . 58
.NET Framework. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 58
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 60
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 61
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 64

. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .
Visual Studio . .. .. .. .. .. .. .. .. .. ..
Assembly Linker. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .

71
78
79
81

. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 82
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 86
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
(.
). .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
( ). .. ..
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .

87
88
90
92

3.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 94
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 95
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 96
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 102
, . .. ..104
.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..106
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 107
. .. .. .. .. .. .. .. 110
. .. .. .. .. .. .. .. .. .. 111
.
( ). .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..115
. .. .. .. .. .. .. .. 117

II.
4. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 122
System.Object . .. .. .. .. .. .. .. .. .. .. .. .. .. .. 122
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..124
C# is as. .. .. .. .. .. .. ..126
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 128
. .. .. .. .. .. .. .. .. .. .. .. 132
. .. .. 133

5. , . .. .. .. .. .. 142
. .. .. .. .. .. .. .. .. .. .. .. 142
.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..146
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 150
CLR . .. .. .. .. .. .. .. .. .. ..155
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .156

( ). .. .. .. .. .. .. .. .. .. ..169
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..172
- . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 175
dynamic . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 177

6. . .. .. .. .. .. .. .. .. .. .. 186
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..186
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 189
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..189
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..191
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 193
, . .. .. .. .. .. .. .. .. .. .. .. .. .. .. 194
, . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 196
, CLR. .. .. .. .. .. .. ..198
.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 202
.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 205

7. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..210
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 210
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..212

8. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 215
( ) . .. .. .. .. .. .. .. 215
( ) . .. .. .. .. .. .. 219
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..222
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 226
. .. .. .. .. ..229

10

Microsoft,.
. .. .. .. .. .. .. .. .. .. .. .. ..229
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 230
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..234
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..237
. .. .. .. .. .. .. .. .. ..238
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 240
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..241
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..244

9. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 245
. .. .. .. .. .. .. .. .. .. .. .. .. .. ..245
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 246
DefaultParameterValue . .. .. .. ..248
. .. .. .. .. .. .. .. .. .. .. ..248
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 251
. .. .. .. .. .. .. .. .. .. .. .. ..257
. .. .. .. .. .. .. .. .. .. .. .. .. .. 259
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 261

10. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..263
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..263
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 267
. .. .. .. .. .. .. .. .. .. .. .. .. 268
Visual Studio . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 270
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..271
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..273
System.Tuple. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..276
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 279
. .. .. .. .. .. .. .. .. .. .. .. .. .. ..283
. .. .. .. .. .. .. .. .. .. .. 284
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..285
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..285

11. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 286
, . .. .. .. .. .. .. .. .. .. .. .. .. ..287

  

11

1.
, .
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 288
2. -. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 289
3. ,
. .. .. .. .. .. .. .. .. .. .. .. .. ..290
4. , .
. .. .. .. .. .. .. .. .. .. .. .. ..292
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 293
, . .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..295
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..298

12. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 302
FCL. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..307
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 308
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..309
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .311
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 313
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..314
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..315
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 316
-.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..317
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .319
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 320
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..322
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 322
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..325
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 327
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..328
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 329

13. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 333
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 333
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..334
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 335

12

. .. .. .. .. .. .. .. .. .. .. .. .. ..338
.
( ). .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..339
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..341
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 344

. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 345
.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 346
. .. .. .. .. .. .. .. .. 348
: ? . .. .. .. .. .. .. ..351

III.
14. , . .. .. .. .. .. .. .. .. .. 356
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 356
System.String. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..359
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 359
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 362
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 362
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 369
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..372
. .. .. .. .. .. .. 372
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..375
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..375
StringBuilder. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 376
StringBuilder . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 377
. .. .. .. .. ..
. .. .. .. .. .. .. .. .. ..
.
. ..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

379
380
384
386

. .. .. .. .. .. .. .. .. .. .. ..389
: . .. .. .. .. .. ..391
. .. .. .. ..397
Base-64 . .. .. .. .. 398
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..399

  

13

15. . .. .. .. .. .. .. .. .. .. 403
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..403
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..409
. .. .. .. .. .. .. .. .. .. .. .. .. .. 413

16. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..416
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 418
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 421
System.Array. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..423
IEnumerable, ICollection IList . .. .. .. .. .. .. .. 424
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..425
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 426
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 427
.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..432

17. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 434
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..434
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..437
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..438
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..439
( ). .. .. .. .. .. ..443
C#. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 448
. .. .. ..448
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 451
. .. .. .. .. .. .. .. .. .. .. .. .. ..452
1: . .. .. .. .. .. .. .. .. .. .. .. .. .. 452
2: . .. .. .. .. .. .. .. 453
3: .
. .. .. .. .. .. .. .. .. .. .. .. .. 457
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..460

18. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 464
. .. .. .. .. .. .. .. .. .. .. .. .. .. 464
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..468

14

. .. .. .. .. .. .. .. .. 471
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 473
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 477
,
Attribute. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..480
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 484

19. Null- . .. .. .. .. .. .. .. .. .. .. ..485


C# null- . .. .. .. .. .. .. .. .. .. ..487
null . .. .. .. .. .. .. .. .. .. 490
CLR null- . .. .. .. .. .. .. .. .. .. 491
null- . .. .. .. .. .. .. .. .. .. .. .. .. .. 491
null- . .. .. .. .. .. .. .. .. .. .. .. 492
GetType null- . .. .. .. 492
null-.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 493

IV.
20. . .. .. .. .. .. .. .. ..496
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..496
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..498
try. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..499
catch. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 499
finally. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 501
CLS- CLS- . .. .. .. .. .. .. ..503
System.Exception . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 505
, FCL . .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..509
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..511
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 513
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..515
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..524
finally . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 525
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..526
. .. .. .. .. .. .. .. .. .. .. .. 528

15

  

.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..529
. .. .. .. .. ..530
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..533
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..537
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..540
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..543
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..546

21.
(). .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 554
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
.
. .. .. .. .. .. .. .. .. .. ..
. .. .. .. .. .. .. .. .. .. ..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

..
..
..
..

554
555
557
560

. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 562
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..568
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 569
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..570
. .. .. .. .. .. .. .. .. .. .. .. 573
. .. .. .. .. .. .. .. .. ..574
. .. .. ..576
, . .. .. .. .. .. .. .. .. .. .. .. .. .. ..583
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 588
.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..590
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..594
. .. .. .. .. .. .. .. .. .. .. ..597

22. CLR . .. .. .. .. .. .. .. .. .. .. 606


CLR. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 606
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..609
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..612
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..624
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 626

16

. .. .. .. .. .. ..627
. .. .. .. .. .. .. .. .. .. .. .. .. .628
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 628
- Silverlight. .. .. .. .. .. ..629
Microsoft ASP.NET - XML. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..629
Microsoft SQL Server. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..630
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 630
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..631
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..631
-. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..631
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..633

23. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. 636
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 637
.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..641
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 642
, . .. .. .. .. .. .. .. .. .. .. .. .. ..644
Type . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 644
, Exception . .. .. .. .. .. .. .. 646
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..648
. .. 650
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..653
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 654
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..658
.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..663

24. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 666
/. .. .. .. .. .. .. .. ..667
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 672
. .. .. .. .. .. .. .. .. .. .. .. .. 673
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..677
. .. .. 679
, ISerializable,.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..684

17

  

- . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..

..
..
..
..

..
..
..
..

..
..
..
..

686
688
691
694

/ . ..695

25. WinRT . .. .. .. .. .. .. ..698


CLR .
WinRT. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 700
WinRT. .. .. .. .. .. .. .. .. .. .. .. .. ..700
.NET Framework. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..705
WinRT API .NET. .. .. .. .. .. .. .. .. .. .. .. .. 705
WinRT .NET . .. .. .. .. ..710
CLR WinRT. .. .. .. .. .. .. .. .. .. .. .. .. 712
WinRT C#. .. .. .. .. .. .. .. .. .. .. .. .. .. ..715

V.
26. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..724
Windows ? . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 724
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 725
!. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..729
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 732
CLR- Windows- . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 733
. .. .. .. .. .. .. .. .. .. 734
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..736
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 739
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..744
? . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 746

27. . .. .. .. .. .. .. .747
CLR . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 747
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 748
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..750
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..752

18

. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..757
. .. .. .. .. .. .. .. .. .. .. .. ..758
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..760
. .. .. 762
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..764
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 765
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 767
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..769
For, ForEach Invoke Parallel . .. .. .. .. .. .. .. .. .. .. .. .. .. ..771
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..775
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 779
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..782
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..783
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..783
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..784

28. - . .. .. .. .. .. .. .. .. 787
- Windows. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..787
C#. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..792
. .. .. .. .. ..795
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..799
. .. .. .. .. .. .. .. .. .. .. .. .. 803
FCL. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 804
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..806
. .. .. .. .. .. .. .. .. .. .. .. .. .. ..807
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 810
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 813
- . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 814
-.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..815
FileStream . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 816
-. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..817

  

19

29.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 820
. .. .. .. .. .. .. .. .. .. .. .. .. .. 822
.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 824
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..825
Volatile-. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..826
Interlocked-. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 832
. .. .. .. .. .. .. .. .. .. .. .. 837
Interlocked-. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 841
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..843
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 847
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..850
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 851

30. . .. 854
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..854
, . .. .. .. .. .. .. .. .. .. .. .. .. ..857
FCL. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..859
ManualResetEventSlim SemaphoreSlim. .. .. .. .. .. .. .. .. .. .. ..859
Monitor . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..860
ReaderWriterLockSlim. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..866
OneManyLock. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..868
CountdownEvent . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 871
Barrier. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..872
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 873
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..875
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 880
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 882
. .. .. .. .. .. .. .. .. .. .. .. .. 888


. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..893

. , .
.
.
(9 ) (5 ). , . , , .
. .

. ? ,
!
. ,
; , . ,
, , .
. ,
( -
). . ,
, .
, .
.
, - 3
( 5- ,
, , ). -

.
, - , .

.
; . , , - - .
, ;
Microsoft.
. ,
, .
, ,
(reflection). , .
, ,
,
, . , .
async/await. ,
AsyncEnumerator, - .
, ! ,
, .

23

M, async/await,
, .
.
, WinRT
. WinRT , -
:
! , ; Windows
. . , .
! , ,
- .
, . , : WinRT,
!
, ( )
, .
? ,
.

,
( )
2012 .

! !


1999 Microsoft .NET Framework, (Common Language
Runtime, CLR) #.
: , .
, . , .NET Framework Win32
API (Application Program Interface, )
COM (Component Object Model, ).
.NET Framework, ,
. .
, , , , ( ),
. ( )
,
.
2012 , 13 ,
.NET Framework C#.
13 Microsoft
.NET Framework.
Wintellect (http://Wintellect.com)
, ,
, , .NET Framework.
,
.NET Framework .
, .


, .NET Framework. , , , CLR
.
(Framework Class Library, FCL). FCL ,
. ,

25

. Windows Forms,
Windows Presentation Foundation
(WPF), Microsoft Silverlight, - XML, -, Microsoft ASP.NET
MVC, Windows Store Apps .., , ,
.
Microsoft Visual Studio 2012, .NET Framework4.5
# 5.0. Microsoft
, , ,
. #,
CLR ,
, .

, , Wintellect
(http://Wintellect.com/Books).

, ,
, , , .
.
( )
,
JeffreyR@Wintellect.com.

.
, .
, , ,
, ,
. - . , ,
.
. .NETFramework ( )
,
. (Christophe Nasarre),
,
.
. , -

26

Microsoft Press.
(Ben Ryan), (Devon Musgrave)
(Carol Dillingham). (Susie Carr)
(Candace Sinclair) .

,
.
Microsoft Press oreilly.com http://
go.microsoft.com/FWLink/?Linkid=266601.
, ,
.
, Microsoft Press Book Support mspinput@microsoft.com.
, , Microsoft .


. ,
, http://microsoft.com/learning/booksurvey.
,
. !


! : http://twitter.com/MicrosoftPress.


. ,
comp@piter.com ( ,
).
!
-
http://www.piter.com.

I
CLR

1. CLR. .. .. .. . 28
2. , ,

. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 58
3.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 94

1.
CLR

Microsoft .NET Framework , . .NET Framework,


,
. (),
(, ..), , .

, .NET Framework . ! .
, , ,
.
.
. , ,
C/C++ .
, .. , Microsoft Visual Basic6.0
COM-
.
(Common Language Runtime,
CLR) : ,
. CLR ( ,
, , , )
, . , , ,
, ,
. , ,
, ,
, , .

29

CLR ,
. ,
,
.
,
CLR.
?
. , ,
, ,
. , .
. ,
APL
Perl.
Microsoft , : C++/CLI, C# (
), Visual Basic, F# ( ), Iron Python, Iron Ruby
Intermediate Language (IL). Microsoft,
,
CLR. Ada, APL, Caml, COBOL, Eiffel, Forth, Fortran,
Haskell, Lexico, LISP, LOGO, Lua, Mercury, ML, Mondrian, Oberon, Pascal, Perl, Php,
Prolog, RPG, Scheme, Smalltalk Tcl/Tk.
1.1 .
, ,
CLR.
.
(managed module) (portable
executable, PE) 32- (PE32) 64- Windows (PE32+),
CLR. ,

(DEP, Data Execution Prevention) ASLR (Address Space
Layout Optimization),
.
,
, x86, 64 ARM. ,
CLR- IL-. ( IL- .) IL- (managed code),
CLR .

30

1. CLR

IL


(IL )
. 1.1.

. 1.1 .
1.1.

PE32
PE32+

PE- Windows, Common Object File Format (COFF). PE32 32- 64-
Windows, PE32+ 64. : GUI, CUI DLL,
, ,
. , IL-, PE32(+) .
, ,

CLR

( CLR ), . CLR, ,
MethodDef
( Main), /
, , , .

.
,
, , , ,

Intermediate
Language (IL)

, . CLR IL

31

, CLR, IL-,
(metadata)
. , , ,
, .
, , , .
, COM IDL (Interface Definition Language,
). , CLR
. , IDL-,
, IL-.
EXE- DLL-, , .
,
IL- .
. .

, /
IL-.
.
Microsoft Visual Studio . IntelliSense ,
, ,
.
CLR , ,
. ( .)
, ,
.
.
, .
2 .
C#, Visual Basic, F# IL-
, (IL) (, ).
CLR (
.NET Framework) , MFC Visual
Basic 6.0 Microsoft Foundation Class
(MFC) DLL- Visual Basic.

32

1. CLR

Microsoft C++ EXE- DLL-,


. CLR
. C++ /CLR , ( ,
CLR). C++
Microsoft
,
. Microsoft,
,
. Microsoft , C/
C++ , ,
.

CLR , . (assembly)
, .
-,
. -,
, .

. CLR ,
.
2,
,
.
1.2 . ( ),
. PE32(+),
. PE32(+) , (manifest).
. ,
, ,
, .
, C#
, , .
, ,

33

( ), , .
,
(, AL.exe)
. 2.

(:
, )

. 1.2.

, ,
.
. ,
.
. , ,
.
,
.
,
( ). (self-describing). , CLR
, .
,
AD DS (Active Directory Domain Services).
, .

34

1. CLR

CLR
,
DLL,
. , CLR .
, , ,
.NET Framework. Microsoft .NET Framework ,
.
Windows .NET
Framework.
, .NET Framework , MSCorEE.dll %SystemRoot%\system32.
, .NET Framework .
.NET Framework.
, ,
:
%SystemRoot%\Microsoft.NET\Framework
%SystemRoot%\Microsoft.NET\Framework64

Microsoft .NET Framework SDK


CLRVer.exe, CLR,
, , CLR . all
.
CLR, 32- 64- Windows.
,
.
. , EXE- DLL-
Windows x86 x64,
Windows Store Windows RT ( ARM). ,
.NET Framework.
, - Windows.
(unsafe code)
, . C# /platform.
,
: 86, 32- Windows, 64, 64-
Windows, ARM,

CLR

35

32- Windows RT. ,


anycpu, ,
Windows. Visual Studio Platform Target Build (.1.3).

. 1.3. Visual Studio

. 1.3 Prefer 32-Bit.


, Platform Target Any CPU,
. Prefer 32-Bit,
Visual Studio C# /platform:
anycpu32bitpreferred. ,
32- 64- . , 64- ,
, Visual Studio
(Edit-and-Continue) x64.
, 32- 32-
DLL COM, .
C#
PE32 PE32+,
( ). , , Microsoft
DumpBin.exe CorFlags.exe.

36

1. CLR

Windows EXE-
,
32- 64-. PE32
,
PE32+ 64- . Windows .
, 64- Windows
32- 64- , WoW64
(Windows on Windows64).
1.2 . -,
/platform
C#. -, Windows.
1.2. /platform .

/
platform

x86 Windows

x64 Windows

ARM Windows
RT

anycpu (
)

PE32/

32-

64-

32-

anycpu32bit
preferred

PE32/

32-

WoW64

32-

86

PE32/x86

32-

WoW64

64

PE32+/x64

64-

ARM

PE32+/Itanium

32-

EXE- , 32- 64-, Windows

37

MSCorEE.dll (x86,
x64 ARM). Windows x86 ARM 32-
MSCorEE.dll %SystemRoot%\System32. x64 x86
%SystemRoot%\SysWow64, 64-
MSCorEE.dll %SystemRoot%\System32 ( ).
MSCorEE.dll , CLR,
EXE, Main, .
1.

, 7.0 7.1 C# Microsoft, PE32 .


CLR x86.
64- ,
WoW64,
, 32
x86Windows.

Win32 LoadLibrary
, Windows CLR ( ) .
, , ,
. , , /platform:x86, 64-
, WoW64
64 Windows.


,
IL. ,
Microsoft
, .
IL .
Is64BitOperatingSystem
, , 64- Windows,
Is64BitProcess, ,
64- .
1

38

1. CLR

,
. . IL
- .
,
C#, Visual Basic F#. IL-.
, , Microsoft
IL (ILAsm.exe), IL (ILDasm.exe).
, , ,
, CLR. IL
CLR.
CLR, ,
IL ,
.
CLR, , .
CLR ,
C#. ,
CLR
, . , ,
.

, CLR. , ,
. , C# Visual Basic,
-. APL (A Programming
Language) .
CLR C# , -,
APL. CLR
,
.

- IL-
. JIT- (Just-In-Time) CLR.
.1.4 , .
Main CLR
, Main. CLR ,
, . . 1.4 Main Console, CLR .
,

39

Console. , . CLR
,
CLR. JITCompiler.

( )

. 1.4.

Main WriteLine ,
JITCompiler. IL-
. IL- (just in time), CLR
JIT-.

86 Windows WoW64, JIT x86. ,


64- x64 Windows, JIT- x64.
, ARM- Windows, JIT-
ARM.

40

1. CLR

JITCompiler , . JITCompiler IL-


. JITCompiler IL- , .
JITCompiler ,
CLR, ,
. JITCompiler
. WriteLine
( String). Main, .
Main WriteLine.
WriteLine ,
, JITCompiler. ,
WriteLine Main. .1.5 ,
WriteLine.

. 1.5.

41

.
,
.
JIT- . , .

( ) JIT
IL- .

,
.
, JIT-, .
.
.
, .
, JIT- CLR
C++. :
,
, .
C#, ,
/optimize /debug .
IL, C#, , JIT.

IL-


JIT

/optimize- /debug-

/optimize- /debug(+/full/
pdbonly)

/optimize+ /debug(-/+/full/
pbdonly)

( )

C /optimize- # IL, (no-operation, NOP). (edit-and-continue)


Visual Studio . ,
(breakpoints) ,
for, while, do, if, else, try, catch finally.
IL- # ,

42

1. CLR

, .
, , .
IL- , EXE DLL-; , IL- ,
IL-, , (, ).
, PDB (Program Database)
/debug(+/full/pdbonly) . PDB
IL .
/debug:full JIT- ,
; JIT- , IL.
JIT- Visual Studio
. /debug:full
IL ;
.
Visual Studio, JIT- IL ( /
debug), Suppress JIT Optimization On Module Load
(Managed Only) Visual Studio.
C# Visual Studio
/optimize /debug:full,
/optimize+ /debug:pdbonly.
C C++
, .
. .
,
IL-. IL-
,
, ,
.
CLR C/C++
. , ,
,
. Microsoft
, .
,
.
- , Microsoft . ,
.
, ( ) ,

43

. . , ,
JIT- IL- ,
, .

:
JIT- ,
Intel Pentium 4, ,
Pentium 4. ,
.
JIT- , ,
, . , :
if (numberOfCPUs > 1) {
...
}

, JIT-
. , ,
.
CLR IL
.
. CLR , , .
,
. ,

.
, JIT-
, ,
NGen.exe .NET Framework SDK.
IL-
. CLR ,
, , . ,
NGen.exe , , NGen.exe,
, JIT-.
System.
Runtime.ProfileOptimization. CLR ( ) -

44

1. CLR

, JIT- . , ,
, JIT-
. , , (
JIT-).

IL-
IL ; ,
. IL
, ,
CLR.
IL . , IL
, . (32- 64-).
,
, .
, , IL-
, . IL- .
IL CLR ,
IL
. , , ,
,
, return . .
, ,
.
Windows .
, .
(, ). Windows
; .
,
. , Windows.
Windows ,

45

.
, ,
.
.
, CLR
. (AppDomain).
EXE- ,
. , ()
CLR , IIS (Internet Information Services) Microsoft SQL Server,

. 22.


C# Microsoft .
, . Microsoft C# ,
. ,

, .
: ( )
. C# ,
, , unsafe,
/unsafe.
JIT- ,
, , ,
System.Security.Permissions.SecurityPermission SkipVerification System.Security.Permissions.
SecurityPermissionFlag. , JIT-
. CLR ,
. , JIT- System.
InvalidProgramException System.Security.VerificationException, . ,
, .
Microsoft PEVerify.exe,
, .
, PEVerify.exe , ;
.

46

1. CLR

, ,
; , ,
. , ,
. , .
,
.

, , . , PEVerify
, . PEVerify CLR ,
, . 2 3.

IL
, IL
. ,
, - IL, .
, IL- , , IL-
. , (-,
- ), . ,
IL
.
,
.
. . ,
, CLR IL- JIT-.
,
,
,
IL . CLR ( )
. , ,

.

FCL

47

NGen.exe
NGen.exe, .NET Framework,
IL-
. , JIT-
CLR ,
. NGen.exe .
. NGen.exe ,
,
.
. , ,
NGen.exe . , NGen.exe
IL .
, , .

FCL
.NET Framework FCL (Framework Class Library)
DLL, ,
.
Microsoft , Windows Azure
SDK DirectX SDK. ,
. , Microsoft
, Microsoft.
,
:
-. Microsoft ASP.NET XML Web Service Windows
Communication Foundation (WCF)
, .
Web Forms/ MVC HTML. ,
ASP.NET , ,

HTML.
Windows .
- ,

48

1. CLR

Windows Store, WPF (Windows Presentation


Foundation) Windows Forms.
, , , , ,
,
-.
Windows.

. , .
Windows. , (services),
Windows SCM (Service Control Manager)
.NET Framework.
. Microsoft SQL Server,
IBM DB2 Oracle .NET Framework.
. .NET Framework
() , .

Visual Studio Portable Class Librar


, ,
.NET Framework, Silverlight, Windows Phone,
Windows Store Xbox 360.

FCL , . , System (
) Object
. , System
, , ,
-, ,
, ,
.
System.
FCL, ,
, .
; FCL. -
, .NET Framework
. ,
, .
.
Win32 .

CTS

49

FCL , . .1.3
.
,
Microsoft, Microsoft SDK.
1.3. FCL

System

System.Data

System.IO

-,

System.Net

System.Runtime.
InteropServices

, ( COM, Win32 DLL-)

System.Security

System.Text

(, ANSI
)

System.Threading

System.Xml

XML

CLR , CLR. , ,
CLR.
-, Web Forms/MVC, WPF
.. ,
.
, ,
. ,
, .

CTS
, , CLR , .

50

1. CLR

, , ,
. CLR,
Microsoft CTS (Common Type
System), .

Microsoft CTS .NET Framework


( , , IL, P/Invoke . .) ECMA . CLI (Common Language
Infrastructure) ECMA-335. ,
Microsoft FCL, C# (ECMA334) C++/CLI. ECMA http://www.ecma-international.org.
Microsoft: http://msdn.microsoft.com/en-us/netframework/
aa569283.aspx.

CTS, . II ,
:
, . .
, ,
. , .
( ), , , ,
.
,
( ).

/ .
, ,
.

. , , .
CTS . ,
( public),
, . , ( internal C#)
. , CTS ,
, CLR .

CTS

51

, ,
. :
()
.

, . : (, C# C++)
protected.
,
, . (, C# Visual Basic) . ,
IL- .
, . internal.

, . C#
protected internal.
.
, CTS , ,
, . .
, . , CTS ,

. IL, CLR,
.
CLR, ,
. C++/
CLI, . ,
C#
Visual Basic. ,
, ,
CTS.
, . CTS
. C++ , CTS
.
, , Microsoft
C++/CLI .

52

1. CLR

CTS: (
) System.Object (
Object System). Object ,
, ,
. , System.Object :
;
- ;
;
() ;
.

CLS
COM , , . , CLR ,
, .
CLR, (
) .
, ,
. , ,
, .
,
, , .
Microsoft CLS
(Common Language Speciication); , ,
, CLS-
CLR.
CLR/CTS ,
CLS. , ,
. , CLS ,
,
CLS- .
: CLS , -

CLS

53

. .1.6 ,
.
CLR/CTS

Visual
Basic

C#
CLS

Fortran

. 1.6. CLR/CTS CLS


(, )

. 1.6, CLR/CTS . CLR/CTS.


, , IL,
CLR/CTS. (C#, Visual
Basic, Fortran . .)
CLR/CTS. CLS ,
.
,
, CLS, .
,
.
CLS- C#.
CLS- , -
C# .
usingSystem;
//
// CLS
[assembly:CLSCompliant(true)]
namespaceSomeLibrary{
// ,
publicsealedclassSomeLibraryType{
//: 'SomeLibrary.SomeLibraryType.Abc()'
// CLS-
publicUInt32Abc(){return0;}

54

1. CLR

//: 'SomeLibrary.SomeLibraryType.abc()',
// ,
// CLS-
publicvoidabc(){}
// :
privateUInt32ABC(){return0;}
}
}

[assembly:CLSCompliant(true)] .
,
,
. C#
. - , Abc
; . - ,
, : Abc abc. Visual Basic
.
public sealed class SomeLibraryType
, . ,
SomeLibraryType internal, ,
. CLS Cross-Language Interoperability .NET Framework
SDK (http://msdn.microsoft.com/en-us/library/730f1wy3.aspx).
CLS . CLR
(), ().
,
. . ,
, , , , , ,
, , ,
. . , , CLR
.
, , , , . ,
, ,
.
usingSystem;
internalsealedclassTest{

CLS

55

//
publicTest(){}
//
~Test(){}
//
publicstaticBooleanoperator==(Testt1,Testt2){
returntrue;
}
publicstaticBooleanoperator!=(Testt1,Testt2){
returnfalse;
}
//
publicstaticTestoperator+(Testt1,Testt2){returnnull;}
//
publicStringAProperty{
get{returnnull;}
set{}
}
//
publicStringthis[Int32x]{
get{returnnull;}
set{}
}
//
public eventEventHandlerAnEvent;
}

,
. ,
IL Disassembler (ILDasm.exe), .NET Framework
SDK (.1.7).
.1.4 / CLR.
Test, .1.4 .class, .custom,
AnEvent, AProperty Item, .
,
, CLR, . , , Test
AnEvent,
(add_AnEvent remove_AnEvent).

56

1. CLR

. 1.7. ILDasm Test.


( )

1.4. Test

AnEvent

; AnEvent, System.
EventHandler

.ctor

Finalize

add_AnEvent

get_AProperty

Get-

get_Item

Get-

op_Addition

op_Equality

==

op_Inequality

!=

remove_AnEvent

set_AProperty

Set-

set_Item

Set-

57


.NET Framework
. , . Microsoft
, CLR , , .
, CLR :
DLL P/Invoke ( Platform Invoke).
, , FCL,
, Kernel32.dll, User32.dll . . ,
DLL . , C#
CreateSemaphore, Kernel32.dll.
COM.

COM. COM.
, .
TlbImp.exe,
.NET Framework SDK.
.
COM.
, , . ,
C# ActiveX
.
TlbExp.exe RegAsm.exe, .NET Framework SDK.

, , Microsoft Type Library


Importer P/Invoke Interop Assistant. http://CLRInterop.CodePlex.com/.

Windows 8 Microsoft , Windows Runtime (WinRT).


COM, COM
API ECMA,
.NET Framework. , ,
.NET, ( ) WinRT API. CLR
COM ,
!
25.

2. ,
,

, Microsoft
.NET Framework, ,
. , . 3
, ,
, , . ,
.
, Microsoft. ,
, . , , (CLR),
;
.
, ,
. , .NET Framework.

.NET Framework
Windows . , ,
. -,
(Dynamic Link Library, DLL), Microsoft
. ,
, -
100% , ,
. ,

.NET Framework

59

,
.
,
. ,
, ? ,
,
, ,
.
, ,
( ) . , ,
DLL. ,
.
,
.
, Windows,
.
. , , ,
(Desktop), (Start)
. , . ,
, ,
. ,
, . ,
, -
- .
.
, . ,
- (, ActiveX) , , .
,
. -
, .
, ,
,
.
, .NET Framework DLL

60

2. , ,

,
. , COM . ,
.
.NET Framework
(code access security). Windows
,
, , .
(, Microsoft SQL Server)
,
( ). , .NET Framework
, , - Windows.


, ,
, , .
:
public sealed class Program {
public static void Main() {
System.Console.WriteLine("Hi");
}
}

Program
Main. Main System.Console.

Microsoft, IL,
, MSCorLib.dll. ,
, ,
.
, (, Program.cs, :
csc.exe /out:Program.exe /t:exe /r:MSCorLib.dll Program.cs

C# Program.
exe ( /out:Program.exe). -

Win32 ( /t[arget]:exe).
C# WriteLine System.Console.
, WriteLine.

61

, , ,
WriteLine.
C#, C# , .
/r[eference]:MSCorLib.dll
, MSCorLib.dll.
MSCorLib.dll , :
Byte, Char, String, Int32 .. ,
, C# (MSCorLib.dll) .
, ( /r)
, :
csc.exe /out:Program.exe /t:exe Program.cs

, ,

/out:Program.exe /t:exe, ,

:
csc.exe Program.cs

- , C#
MSCorLib.dll, /nostdlib. Microsoft
MSCorLib.dll. ,
Program.cs
, System.Console MSCorLib.dll:
csc.exe /out:Program.exe /t:exe /nostdlib Program.cs

Program.exe,
C#. ? PE
(portable executable). , , 32-
64- Windows, -
. Windows :
(Console User Interface, CUI)
(Graphical User Interface, GUI). /t:exe C#
.
/t:winexe, Windows
Store /t:appcontainerexe.



(response files) ,
. CSC.
exe ,
.

62

2. , ,

@.
, MyProject.rsp :
/out:MyProject.exe
/target:winexe

(CSC.exe) ,
:
csc.exe @MyProject.rsp CodeFile1.cs CodeFile2.cs

C# . , ,

.
C# . ,
CSC.rsp .
CSC.exe CSC.rsp,
, .
.

. ,
, .
.NET Framework
CSC.rsp %SystemRoot%\Microsoft.NET\Framework(64)\
vX.X.X ( X.X.X .NET Framework).
:
#
#
#
#

,
C# (CSC)
,
"/noconfig".

# Framework
/r:Accessibility.dll
/r:Microsoft.CSharp.dll
/r:System.Configuration.dll
/r:System.Configuration.Install.dll
/r:System.Core.dll
/r:System.Data.dll
/r:System.Data.DataSetExtensions.dll
/r:System.Data.Linq.dll
/r:System.Data.OracleClient.dll
/r:System.Deployment.dll
/r:System.Design.dll
/r:System.DirectoryServices.dll
/r:System.dll
/r:System.Drawing.Design.dll

63

/r:System.Drawing.dll
/r:System.EnterpriseServices.dll
/r:System.Management.dll
/r:System.Messaging.dll
/r:System.Runtime.Remoting.dll
/r:System.Runtime.Serialization.dll
/r:System.Runtime.Serialization.Formatters.Soap.dll
/r:System.Security.dll
/r:System.ServiceModel.dll
/r:System.ServiceModel.Web.dll
/r:System.ServiceProcess.dll
/r:System.Transactions.dll
/r:System.Web.dll
/r:System.Web.Extensions.Design.dll
/r:System.Web.Extensions.dll
/r:System.Web.Mobile.dll
/r:System.Web.RegularExpressions.dll
/r:System.Web.Services.dll
/r:System.Windows.Forms.Dll
/r:System.Workflow.Activities.dll
/r:System.Workflow.ComponentModel.dll
/r:System.Workflow.Runtime.dll
/r:System.Xml.dll
/r:System.Xml.Linq.dll

CSC.rsp , /reference.
,
, Microsoft ,
/reference.
,
,
,
.

/reference - . ,
( ).
.
, (CSC.exe). MSCorLib.
dll .
:
- %SystemRoot%\Microsoft.NET\Framework\v4.0.#####.
- , /lib .
- , LIB.

64

2. , ,

, CSC.
rsp,
CSC.rsp ,
.
, CSC.rsp, /noconfig.


Program.exe? PE-
4- : PE32(+), CLR, (intermediate language, IL). PE32(+)
, Windows. CLR , , CLR ( ).
CLR,
, MethodDef ( ),
, CUI, GUI Windows Store,
( 3).
, ,
. CLR,
IMAGE_COR20_HEADER, CorHdr.h.
, .
: , . .2.1
,
.
2.1.

ModuleDef

, .
( ) ( GUID). ,
.
, CLR

TypeDef

, .
, , (public,
private ..) MethodDef, PropertyDef
EventDef, ,

65

MethodDef

, . , (private, public, virtual,


abstract, static, final ..), , IL-.
ParamDef,

FieldDef

, . (, private, public ..)


ParamDef

,
. (in, out, retval ..),

PropertyDef

, . , ,
( )

EventDef

, .

, , , .2.1.
, , ,
, .
, . .2.2
, .
2.2. ,

AssemblyRef

, . ,
: ( ),
, (
-, ,
). -,
.
CLR - ,,

66

2. , ,

2.2 ()

ModuleRef

PE-,
, .
( ).
,

TypeRef

,
. ,
. , TypeRef.
, ModuleDef.
, ModuleRef.
,
AssemblyRef

MemberRef

(, ,
), .

TypeRef, ,

, . 2.1
2.2; , . ,
. .
PE-
. ILDasm.exe IL.
, :
ILDasm Program.exe

ILDasm.exe Program.exe.
,
View MetaInfo Show! ( Ctrl+M).
:

===========================================================
ScopeName : Program.exe
MVID
: {CA73FFE8
0D42
4610
A8D3
9276195C35AA}
===========================================================
Global functions

67

Global fields

Global MemberRefs

TypeDef #1 (02000002)

TypDefName: Program (02000002)


Flags
: [Public] [AutoLayout] [Class] [Sealed] [AnsiClass]
[BeforeFieldInit] (00100101)
Extends
: 01000001 [TypeRef] System.Object
Method #1 (06000001) [ENTRYPOINT]
MethodName: Main (06000001)
Flags
: [Public] [Static] [HideBySig] [ReuseSlot]
RVA
: 0x00002050
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
ReturnType: Void
No arguments.

(00000096)

Method #2 (06000002)
MethodName: .ctor (06000002)
Flags
: [Public] [HideBySig] [ReuseSlot] [SpecialName]
[RTSpecialName] [.ctor] (00001886)
RVA
: 0x0000205c
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments.

TypeRef #1 (01000001)

Token:
0x01000001
ResolutionScope:
0x23000001
TypeRefName:
System.Object
MemberRef #1 (0a000004)

Member: (0a000004) .ctor:


CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments.

TypeRef #2 (01000002)
Token:
ResolutionScope:

0x01000002
0x23000001

68

2. , ,

TypeRefName:
System.Runtime.CompilerServices.CompilationRelaxationsAttribute
MemberRef #1 (0a000001)

Member: (0a000001) .ctor:


CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
1 Arguments
Argument #1: I4
TypeRef #3 (01000003)

Token:
0x01000003
ResolutionScope:
0x23000001
TypeRefName:
System.Runtime.CompilerServices.RuntimeCompatibilityAttribute
MemberRef #1 (0a000002)

Member: (0a000002) .ctor:


CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments.
TypeRef #4 (01000004)

Token:
0x01000004
ResolutionScope:
0x23000001
TypeRefName:
System.Console
MemberRef #1 (0a000003)

Member: (0a000003) WriteLine:


CallCnvntn: [DEFAULT]
ReturnType: Void
1 Arguments
Argument #1: String
Assembly

Token: 0x20000001
Name : Program
Public Key
:
Hash Algorithm : 0x00008004
Version: 0.0.0.0
Major Version: 0x00000000
Minor Version: 0x00000000
Build Number: 0x00000000
Revision Number: 0x00000000
Locale: <null>
Flags : [none] (00000000)
CustomAttribute #1 (0c000001)
CustomAttribute Type: 0a000001
CustomAttributeName:

69


System.Runtime.CompilerServices.CompilationRelaxationsAttribute ::
instance void .ctor(int32)
Length: 8
Value : 01 00 08 00 00 00 00 00
>
ctor args: (8)

<

CustomAttribute #2 (0c000002)

CustomAttribute Type: 0a000002


CustomAttributeName:
System.Runtime.CompilerServices.RuntimeCompatibilityAttribute ::
instance void .ctor()
Length: 30
Value : 01 00 01 00 54 02 16 57 72 61 70 4e 6f 6e 45 78 >
T WrapNonEx<
: 63 65 70 74 69 6f 6e 54 68 72 6f 77 73 01
>ceptionThrows
<
ctor args: ()
AssemblyRef #1 (23000001)

Token: 0x23000001
Public Key or Token: b7 7a 5c 56 19 34 e0 89
Name: mscorlib
Version: 4.0.0.0
Major Version: 0x00000004
Minor Version: 0x00000000
Build Number: 0x00000000
Revision Number: 0x00000000
Locale: <null>
HashValue Blob:
Flags: [none] (00000000)
User Strings

70000001 : ( 2) L"Hi"
Coff symbol name overhead: 0
===========================================================
===========================================================
===========================================================

, ILDasm , . ,
, , TypeDef, ILDasm
TypeRef .
,
, Program.exe TypeDef Program.
(sealed) ,
System.Object ( ). Program
: Main .ctor ().

70

2. , ,

Main , IL ( , x86). Main


void . - ( .ctor) , IL.
void, ,
this, ,
.

ILDasm. , , CLR . ILDasm.
Program.exe.
ILDasm ViewStatistics, :
File size
PE header size
PE additional info
Num.of PE sections
CLR header size
CLR meta
data size
CLR additional info
CLR method headers
Managed code
Data
Unaccounted
Num.of PE sections
1024
.text
.rsrc
1536
.reloc
512

:
:
:
:
:
:
:
:
:
:
:

3584
512 (496 used)
1411
3
72
612
0
2
20
2048
1
093

(14.29%)
(39.37%)
( 2.01%)
(17.08%)
( 0.00%)
( 0.06%)
( 0.56%)
(57.14%)
(
30.50%)

: 3

CLR meta
data size : 612
Module

1 (10 bytes)
TypeDef 2 (28 bytes) 0 interfaces, 0 explicit layout
TypeRef

4 (24 bytes)
MethodDef 2 (28 bytes) 0 abstract, 0 native, 2 bodies
MemberRef

4 (24 bytes)
CustomAttribute 2 (12 bytes)
Assembly

1 (22 bytes)
AssemblyRef

1 (20 bytes)
Strings
184 bytes
Blobs

68 bytes
UserStrings

8 bytes
Guids

16 bytes
Uncategorized 168 bytes
CLR method headers : 2
Num.of method bodies
Num.of fat headers

2
0


Num.of tiny headers

71

Managed code : 20
Ave method size 10

( ),
( ).
Program.cs ,
PE . IL- 20. ,
, ,
.

ILDasm.exe ,
. , Unaccounted.

Program.exe PE- , (assembly),


. . (manifest) ,
, . ,
, , , .
CLR , CLR ,
. :
;
;
.
, ,
.
,
, , .
, Program.exe , : PE-

72

2. , ,

, GIF- JPG-. ,
EXE- DLL-.
, , Microsoft
. ,
. ,
. , ,
, . ,
, . ,
(independent software vendor, ISV), ,
Active Accessibility ( Microsoft).
, .
, , codeBase (. 3).
URL-, .
CLR URL codeBase
.
, , CLR
URL-. , CLR FileNotFoundException.
.
,
,
, .
. ,
.
.
(,
AL.exe, ).
: , Microsoft
Excel Microsoft Word, ,
.
, . C#, Visual Basic,
.
C# , Visual Basic .
.
. -

73

, . ,
ILDasm.exe IL. ILAsm.exe
, , .
IL-.

, , , .
, ,
. ,
CLR , ,
.
, , , ,
, .
,
,
, ,
. CLR Windows
: , .
, ,
. ,, nGen.exe ,
.

, PE-, . PE-,
, . .2.3
, .
2.3.

AssemblyDef

,
. ( ),
( ,
), , ,
(
null)

74

2. , ,

2.3 ()

FileDef

PE- , ( ,
).
( ), - . , FileDef

ManifestResourceDef

,
. , (public
private), FileDef, . (, JPEG- GIF-), PE-.
,
PE-

ExportedTypesDef

,
PE- .
, FileDef ( ,
),
TypeDef. :
, , ,
, TypeDef


. , , ,
, , ,
.

, , AssemblyRef.
,
. , ,
, ,
. AssemblyRef .

C# , /t[arget]:exe, /t[arget]:winexe, /t[arget]: appcontainerexe,

75

/t[arget]:library /t[arget]:winmdobj1. -

PE-
. , , Windows Store,
WINMD.
C# /t[arget]:module,
PE- .
DLL- PE.
,
. /t:module C# .netmodule.

, (Integrated Development Environment,


IDE) Microsoft Visual Studio .

. PE-
C#,
/addmodule. , ,
. , :
RUT.cs ;
FUT.cs .
, ,
:
csc /t:module RUT.cs

C# RUT.netmodule, PE- DLL, CLR


.

, .
, FUT.dll MultiFileLibrary.dll:
csc /out:MultiFileLibrary.dll /t:library /addmodule:RUT.netmodule FUT.cs

/t[arget]:winmdobj .winmdobj
WinMDExp.exe,
CLR Windows Runtime.
WinMDExp.exe IL.
1

76

2. , ,

C# FUT.cs
MultiFileLibrary.dll. /t:library,
PE- DLL MultiFileLibrary.dll.
/addmodule:RUT.netmodule , RUT.netmodule . , /addmodule
FileDef
, ExportedTypesDef
.
, (.2.1).
.
RUT.netmodule IL-, RUT.cs.
, , , ,
, , .., RUT.cs, , .,
RUT.cs. MultiFileLibrary.dll . RUT.
netmodule, IL-, FUT.cs,
. MultiFileLibrary.dll ,
. ,
( MultiFileLibrary.dll RUT.netmodule). ,
MultiFileLibrary.dll RUT.netmodule.

,
PE-, .
, PE-. ,
,
MultiFileLibrary.dll RUT.netmodule, .
.

MultiFileLibrary.dll, ILDasm.exe, ,
RUT.netmodule. FileDef
ExportedTypesDef :
File #1 (26000001)

Token: 0x26000001
Name : RUT.netmodule
HashValue Blob : e6 e6 df 62 2c a1 2c 59
Flags : [ContainsMetaData] (00000000)
ExportedType #1 (27000001)
Token: 0x27000001
Name: ARarelyUsedType

97 65 0f 21 44 10 15 96

f2 7e db c2

77

Implementation token: 0x26000001


TypeDef token: 0x02000002
Flags
: [Public] [AutoLayout] [Class] [Sealed] [AnsiClass]
[BeforeFieldInit](00100101)

, RUT.netmodule , 0x26000001. ExportedType


ARarelyUsedType.
(implementation token) 0x26000001, , IL-
RUT.netmodule.

. 2.1.

: 4 .
(0x01=TypeRef, 0x02=TypeDef, 0x26=FileRef, 0x27=ExportedType). . CorTokenType
CorHdr.h .NET Framework SDK. . ,
0x26000001 FileRef (
1, 0). , TypeDef
2.

, MultiFileLibrary.dll, /r[eference]:MultiFileLibrary.
dll, MultiFileLibrary.dll ,
FileDef. ,
. RUT.netmodule, C# :

78

2. , ,

fatal error CS0009: Metadata file 'C:\MultiFileLibrary.dll' could not be


opened'Error importing module 'rut.netmodule' of assembly
'C:\MultiFileLibrary.dll' The system cannot find the file specified

,
, .
.
CLR ,
, . CLR , , .
, ,
CLR, . , , CLR
, CLR . CLR
, . , ,
, .

Visual Studio
Visual Studio,
, . Solution Explorer,
, ,
Add Reference. Reference Manager (.2.2).

. 2.2. Reference Manager Visual Studio

79

, .
, ( ),
Browse. Solution
, . COM
Reference Manager
COM- -,
Visual Studio. Browse ,
.
.NET,
:
http://msdn.microsoft.com/en-us/library/wkze6zky(v=vs.110).aspx

Assembly Linker
C#
(assembly linker) AL.exe. , , ( , /addmodule
C#), ,
. AL.exe ,
( ),
.
AL.exe EXE DLL PE,
, , .
, AL.exe, MultiFileLibrary.dll -:
csc /t:module RUT.cs
csc /t:module FUT.cs
al /out: MultiFileLibrary.dll /t:library FUT.netmodule RUT.netmodule

, , .2.3.
, RUT.netmodule FUT.netmodule.
, . MultiFileLibrary.dll PE DLL (
/t[arget]:library), IL-,
, , RUT.netmodule FUT.
netmodule . :
MultiFileLibrary.dll, RUT.netmodule FUT.netmodule,
.
AL.exe PE-
, Windows Store
/t[arget]:exe, /t[arget]:winexe /t[arget]:appcontainerexe).
, ,
PE-, IL-,

80

2. , ,

. ,
,
/main. AL.exe :
csc /t:module /r:MultiFileLibrary.dll Program.cs
al /out:Program.exe /t:exe /main:Program.Main Program.netmodule

. 2.3.

Program.cs ,
PE- Program.exe .
, AL.exe
/main: Program.Main. , __EntryPoint, IL-:
.method privatescope static void __EntryPoint$PST06000001() cil managed
{
.entrypoint
// Code size
8 (0x8)
.maxstack 8
IL_0000: tail.
IL_0002: call void [.module 'Program.netmodule']Program::Main()
IL_0007: ret
} // end of method 'Global Functions'::__EntryPoint

81

, Main, Program,
Program.netmodule. /main,
AL.exe, , -
, PE- . ,
.
Ch02-3-BuildMultiFileLibrary.
bat, . Ch02-4-AppUsingMultiFileLibrary Visual Studio
.
, Visual Studio.


AL.exe, /embed[resource]
( , PE). PE-.
ManifestResourceDef , .
AL.exe /link[resource], .
ManifestResourceDef FileDef ,
. PE- ,

.

Win32.
# ,
/nowin32manifest. ,
C# , :
<?xml version="1.0" encoding="UTF
8" standalone="yes"?>
<assembly xmlns="urn:schemasmicrosoftcom:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
<trustInfo xmlns="urn:schemas
microsoft
com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas
microsoft
com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

AL.exe, CSC.exe , C#. /resource C# -

82

2. , ,

PE-
ManifestResourceDef. /linkresource
ManifestResourceDef FileDef .
: Win32. , AL.exe CSC.exe RES-
/win32res. , Win32
, AL.exe CSC.exe ICO- /win32icon. Visual Studio
Application . ,
Windows (Windows Explorer)
.


AL.exe CSC.exe PE-,
Win32. , .
GetVersionInfo System.Diagnostics.
FileVersionInfo. .2.4 Details
Ch02-3-MultiFileLibrary.dll.

. 2.4. Details Ch02-3-MultiFileLibrary.dll

83


,
. , , .2.4.
using System.Reflection;
// FileDescription:
[assembly: AssemblyTitle("MultiFileLibrary.dll")]
// Comments:
[assembly: AssemblyDescription("This assembly contains MultiFileLibrary's types")]
// CompanyName:
[assembly: AssemblyCompany("Wintellect")]
// ProductName:
[assembly: AssemblyProduct("Wintellect (R) MultiFileLibrary's Type Library")]
// LegalCopyright:
[assembly: AssemblyCopyright("Copyright (c) Wintellect 2013")]
// LegalTrademarks:
[assembly:AssemblyTrademark("MultiFileLibrary is a registered trademark
of Wintellect")]
// AssemblyVersion:
[assembly: AssemblyVersion("3.0.0.0")]
// FILEVERSION/FileVersion:
[assembly: AssemblyFileVersion("1.0.0.0")]
// PRODUCTVERSION/ProductVersion:
[assembly: AssemblyInformationalVersion("2.0.0.0")]
// Language (. " ")
[assembly:AssemblyCulture("")]

, Windows
. , ,
AssemblyVersion, CLR
( 3).

. 2.4
, .
AL.exe,
. . 2.4
.
C#;
, .

84

2. , ,

2.4. .
AL.exe

AL.exe

FILEVERSION

/fileversion

System.Reflection.
AssemblyFileVersionAttribute

PRODUCTVERSION

/productversion

System.Reflection.AssemblyInformationalVersionAttribute

FILEFLAGSMASK

VS_FFI_
FILEFLAGSMASK (
WinVer.h 0x0000003F)

FILEFLAGS

FILEOS

VOS__
WINDOWS32

FILETYPE

/target

VFT_APP,
/target:exe /target:winexe.
/target:library
VFT_DLL

FILESUBTYPE

VFT2_
UNKNOWN (
VFT_APP VFT_DLL)

AssemblyVersion

/version

System.Reflection.
AssemblyVersionAttribute

Comments

/description

System.Reflection.
AssemblyDescriptionAttribute

CompanyName

/company

System.Reflection.
AssemblyCompanyAttribute

FileDescription

/title

System.Reflection.AssemblyTitleAttribute

FileVersion

/version

System.Reflection.
AssemblyVersionAttribute

InternalName

/out

( )

LegalCopyright

/copyright

System.Reflection.
AssemblyCopyrightAttribute

LegalTrademarks

/trademark

System.Reflection.
AssemblyTrademarkAttribute

85

AL.exe

OriginalFilename

/out

( )

PrivateBuild

ProductName

/product

System.Reflection.
AssemblyProductAttribute

ProductVersion

/productversion

System.Reflection.AssemblyInformationalVersionAttribute

SpecialBuild

C# Visual Studio AssemblyInfo.cs


. , ,
3.
AssemblyInfo.cs . Visual Studio

, . 2.5.

. 2.5. Visual Studio

86

2. , ,


, .
: 4 , (.2.5).
2.5.

719

. 2.5 2.5.719.2. , :
2.5. , 719, .
, .
2 .
(, , ),
.
Microsoft, .
: .
. ,
.
AssemblyFileVersion Win32
, CLR .
,
.
. Microsoft (, CSC.exe
AL.exe)
( ), . Windows
.
AssemblyInformationalVersion
Win32 , , ; CLR
. ,
. , 2.0
. 1.0, ,
1.0.
.

.

87

AssemblyVersion , AssemblyDef. CLR , ( 3).


, .
, ,
; ,
, .
, ,
AssemblyRef. , , . CLR ,
, 3.


,
(culture). , ,
, .. ,
( RFC1766).
. 2.6.
2.6. ,

De

De

AT

De

CH

En

En

GB

En

US

,
. ,
,
(culture neutral).
, , Microsoft

88

2. , ,

.
, .
,
, , . ,
, (satellite assemblies). , ,
.
, .
AL.exe.

. AL.exe, /c[ulture]:text, text (, en-US,
).
,
, . ,
C:\MyApp, C:\MyApp\en-US.

System.Resources.ResourceManager.

, . /culture AL.exe
System.Reflection.AssemblyCulture,
, , :
// Swiss German
[assembly:AssemblyCulture("de-CH")]

,
. , AssemblyRef
.
, , (.23).


( )
, .
, .

( )

89

Windows Store
. Visual Studio ,
, .appx, Windows Store,
. .appx,
, CLR
, Windows .
.appx,
, . Windows Store,
.
, Windows .
,
Windows Store. , Windows ,
.
( Windows Store)
. , . , ,
. -
.
, , , CLR
, .
,
, !
, , CAB- (
).
MSI-, Windows (Windows Installer), MSIExec.exe. MSI
CLR .
MSI,
EXE- DLL-.

, ,
(Start) .
, ,
, .

, Visual Studio , , Publish

90

2. , ,

. , Visual Studio
MSI- -, FTP- .
MSI- , .NET
Framework Microsoft SQL Server Express Edition. ,
ClickOnce.
, , , (privately deployed assemblies),
(
). ,
,
, CLR
. ; .
.
// . ,
, ,
. , .
, ,
. CLR
, . CLR
COM, ,
, .
3 , .


( )

. ,
.
,
3.
,
.
, . ,

( )

91


. CLR .
XML-
. (
, ) ,
:
.
3 ,
. ,
MultiFileLibrary, .
:
AppDir ( )
Program.exe
Program.exe.config ( )
AuxFiles ( MultiFileLibrary)
MultiFileLibrary.dll
FUT.netmodule
RUT.netmodule

MultiFileLibrary , CLR ,
System.IO.FileNotFoundException. , XML
.
config, Program.exe.
config.
:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="AuxFiles" />
</assemblyBinding>
</runtime>
</configuration>

, CLR ,
, AuxFiles.
privatePath , ,
, . ,
. ,
,
.

92

2. , ,


CLR .
( ,
firstPrivatePath secondPrivatePath
privatePath ):
AppDir\AsmName.dll
AppDir\AsmName\AsmName.dll
AppDir\firstPrivatePath\AsmName.dll
AppDir\firstPrivatePath\AsmName\AsmName.dll
AppDir\secondPrivatePath\AsmName.dll
AppDir\secondPrivatePath\AsmName\AsmName.dll
...

MultiFileLibrary MultiFileLibrary, CLR -

, .
, CLR
, EXE DLL.
, FileNotFoundException.

: ,
, . , AsmName.dll en-US,
:
C:\AppDir\enUS\AsmName.dll
C:\AppDir\enUS\AsmName\AsmName.dll
C:\AppDir\firstPrivatePath\enUS\AsmName.dll
C:\AppDir\firstPrivatePath\enUS\AsmName\AsmName.dll
C:\AppDir\secondPrivatePath\enUS\AsmName.dll
C:\AppDir\secondPrivatePath\enUS\AsmName\AsmName.dll
C:\AppDir\enUS\AsmName.exe
C:\AppDir\enUS\AsmName\AsmName.exe
C:\AppDir\firstPrivatePath\enUS\AsmName.exe
C:\AppDir\firstPrivatePath\enUS\AsmName\AsmName.exe
C:\AppDir\secondPrivatePath\enUS\AsmName.exe
C:\AppDir\secondPrivatePath\enUS\AsmName\AsmName.exe
C:\AppDir\en\AsmName.dll
C:\AppDir\en\AsmName\AsmName.dll
C:\AppDir\firstPrivatePath\en\AsmName.dll
C:\AppDir\firstPrivatePath\en\AsmName\AsmName.dll
C:\AppDir\secondPrivatePath\en\AsmName.dll
C:\AppDir\secondPrivatePath\en\AsmName\AsmName.dll
C:\AppDir\en\AsmName.exe
C:\AppDir\en\AsmName\AsmName.exe

( )

93

C:\AppDir\firstPrivatePath\en\AsmName.exe
C:\AppDir\firstPrivatePath\en\AsmName\AsmName.exe
C:\AppDir\secondPrivatePath\en\AsmName.exe
C:\AppDir\secondPrivatePath\en\AsmName\AsmName.exe

, CLR EXE DLL.


( CLR
), XML- culture,
. Microsoft
FusLogVw.exe, , CLR
.
http://msdn.microsoft.com/en-us/library/e74a18c4(v=vs.110).aspx.
XML- .
(EXE) . ,
EXE-, config.
Microsoft ASP.NET Web Form
- Web.config. ,
Web.config .
, -, http://www.Wintellect.com/
Training, Web.config,
Training.
,
. .NET Framework
Machine.config. Machine.config CLR, . Machine.config
:
%SystemRoot%\Microsoft.NET\Framework\\CONFIG

, %SystemRoot% ,
Windows ( C:\Windows), ,
.NET Framework (, v4.0.#####).
Machine.config
.
Machine.config,
, ,
. , ,
,
.

3.

2 , .
(private deployment),
, ,
. ,
.
, . , Microsoft .NET Framework,
,
Microsoft .NET Framework Class Library (FCL).
2, Windows - ,
. , Windows, , ,
Microsoft. , ,
.
.NET Framework, , ,
.
, Microsoft, : ,
.. ,
.

, .
, , , Windows.
.
, , 0 1 , ,
, ,
, . ,

95

. - ,
.
, : ,
, , ? .
, , ,
,
. , , , , ,
.
.NET Framework, . :
. , , (CLR). ,
, .
, , ,
.


CLR : (weakly named
assemblies) (strongly named assemblies).


.NET Framework. ? , .
,
. ,
, .

,
PE (portable executable), PE32(+),
CLR-, , , IL-,
1 2. , C# AL.exe. ,
, .
, ,
,
.

96

3.

CLR
, .
,
CLR.
.
. .
2.
- ,
CLR . ,
. ,
. .3.1.
3.1. .


, , CLR , .
( ) . ,
,
, , ,
(
DLL Windows DLL
System32).
, , . CLR
,
. .
, : ( ),
, . ,
- ,

97

(public key token). ,


(assembly display name), :
"MyTypes,
"MyTypes,
"MyTypes,
"MyTypes,

Version=1.0.8123.0,
Version=1.0.8123.0,
Version=2.0.1234.0,
Version=1.0.8123.0,

Culture=neutral,
Culture="en-US",
Culture=neutral,
Culture=neutral,

PublicKeyToken=b77a5c561934e089"
PublicKeyToken=b77a5c561934e089"
PublicKeyToken=b77a5c561934e089"
PublicKeyToken=b03f5f7f11d50a3a"

MyTypes.exe MyTypes.dll (
, ).
- 1.0.8123.0,
, , Culture
neutral. MyTypes.dll ( MyTypes.exe) 1.0.8123.0
.
, ,
, .
Microsoft ( GUID, URL URN) , . ,

,
. . , ,
, ,
. , , ,
.

System.Reflection.AssemblyName , . : CultureInfo, FullName, KeyPair, Name


Version , GetPublicKey,
GetPublicKeyToken, SetPublicKey SetPublicKeyToken.

2 , ,
.
. CLR ,
.
,

98

3.

, privatePath XML, CLR ( DLL EXE).


, . ,
.

Strong Name (SN.exe), .NET Framework SDK Microsoft
Visual Studio. , , . : SN.exe .
, :
SN k MyCompany.snk

SN.exe MyCompany.snk,
.
, , .
SN.exe, .
SN.exe : p,
, (MyCompany.PublicKey)1:
SN p MyCompany.keys MyCompany.PublicKey

SN.exe tp ,
:
SN tp MyCompany.PublicKey

:
Microsoft (R) .NET Framework Strong Name Utility Version 4.0.30319.17929
Copyright (c) Microsoft Corporation. All rights reserved.
Public key (hash algorithm: sha256):
00240000048000009400000006020000002400005253413100040000010001003f9d621b702111
850be453b92bd6a58c020eb7b804f75d67ab302047fc786ffa3797b669215afb4d814a6f294010
b233bac0b8c8098ba809855da256d964c0d07f16463d918d651a4846a62317328cac893626a550
69f21a125bc03193261176dd629eace6c90d36858de3fcb781bfc8b817936a567cad608ae672b6
1fb80eb0
Public key token is 3db32f38c8b42c9a

SN.exe .
Enhanced Strong Naming, .NET
Framework 4.5. , .NET Framework,
(counter-signature)
AssemblySignatureKey. http://msdn.
microsoft.com/en-us/library/hh415055(v=vs.110).aspx.
1

99

.
( ), . 64- -
. SN.exe tp,
.
, ,
.
/keyfile:_:
csc /keyfile:MyCompany.snk Program.cs

, C# (MyCompany.snk),
. : ,
, .
Visual Studio .
Signing, Sign the assembly,
Choose a strong name key file <New>.
:
FileDef
, . ,
, - ,
FileDef.
, , AL.exe /algid
, ,
System.Reflection.AssemblyAlgorithmIdAttribute. - SHA-1.
PE- - ( Authenticode Signature,
PE), .3.1.
SHA-1,
. - , RSA
PE- ( PE- ),
CLR- PE- ,
.
PE- (
AssemblyDef ). ,
,
, .
, ,
Calculus, ( ).
.

100

3.

. 3.1.

2, , . , .
C# /reference.
AssemblyRef . AssemblyRef
, ,
( ), , .

, ,
,
. Microsoft 8 -. AssemblyRef

.
, .
, CLR , ,
.

AssemblyRef (

ILDasm.exe) MultiFileLibrary.dll, 2:

101

AssemblyRef #1 (23000001)

Token: 0x23000001
Public Key or Token: b7 7a 5c 56 19 34 e0 89
Name: mscorlib
Version: 4.0.0.0
Major Version: 0x00000004
Minor Version: 0x00000000
Build Number: 0x00000000
Revision Number: 0x00000000
Locale: <null>
HashValue Blob:
Flags: [none] (00000000)

, MultiFileLibrary.dll , :
"MSCorLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

, ILDasm.exe Locale,
Culture.
AssemblyDef MultiFileLibrary.
dll, :
Assembly
-----------------------------------Token: 0x20000001
Name : MultiFileLibrary
Public Key
:
Hash Algorithm : 0x00008004
Version: 3.0.0.0
Major Version: 0x00000003
Minor Version: 0x00000000
Build Number: 0x00000000
Revision Number: 0x00000000
Locale: <null>
Flags : [none] (00000000)

:
"MultiFileLibrary, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null"

, MultiFileLibrary.dll, 2, , ,
. SN.exe, /keyfile,
.
ILDasm.exe,
AssemblyDef Public Key, ,
. , AssemblyDef , .

102

3.

. ,
.


,
, CLR
.
, , CLR
. ,
,
(global assembly cache, GAC). GAC
, .NET Framework.
GAC
%SystemRoot%\Microsoft.NET\Assembly

GAC ,
.
GAC
, . GAC .

GAC GACUtil.exe.
, :
Microsoft (R) .NET Global Assembly Cache Utility. Version 4.0.30319.17929
Copyright (c) Microsoft Corporation. All rights reserved.
Usage: Gacutil <command> [ <options> ]
Commands:
/i <assembly_path> [ /r <...> ] [ /f ]
Installs an assembly to the global assembly cache.
/il <assembly_path_list_file> [ /r <...> ] [ /f ]
Installs one or more assemblies to the global assembly cache.
/u <assembly_display_name> [ /r <...> ]
Uninstalls an assembly from the global assembly cache.
/ul <assembly_display_name_list_file> [ /r <...> ]
Uninstalls one or more assemblies from the global assembly cache.
/l [ <assembly_name> ]
List the global assembly cache filtered by <assembly_name>

103

/lr [ <assembly_name> ]
List the global assembly cache with all traced references.
/cdl
Deletes the contents of the download cache
/ldl
Lists the contents of the download cache
/?

Displays a detailed help screen

Options:
/r <reference_scheme> <reference_id> <description>
Specifies a traced reference to install (/i, /il) or uninstall (/u, /ul).
/f

Forces reinstall of an assembly.

/nologo
Suppresses display of the logo banner
/silent
Suppresses display of all output

GACUtil.exe /i, GAC, /u GAC. ,


GAC. GACUtil.
exe ,
( :
):
Failure adding assembly to the cache: Attempt to install an assembly
without astrong name

GAC
Windows Administrators. GACUtil.exe ,
.

/i GACUtil.exe
. GACUtil.exe
/r /i
/u . /r
Windows.
,
, .

104

3.

CAB- ,
, GAC
GACUtil.exe, ,
.

GACUtil.exe .NET
Framework, .
, GAC, Windows Installer (MSI), ,
GAC
.

GAC
, Windows.
GAC , ,
, .

, .

GAC? , OurLibrary, :
OurLibrary.dll. , ,
, ,
- . GAC
, %SystemRoot%\Microsoft.NET\Assembly
.
GAC,
. ,
GAC CLR , GAC.

,

, , .
, System.Object MSCorLib.dll,
. ,
, Microsoft,

105

. 2 ,
CSC.exe /reference
, .
, CSC.exe
. 2,
, CSC.exe
( ).
1. .
2. , CSC.exe. DLL CLR.
3. , /lib .
4. , LIB.
, , System.
Drawing.dll Microsoft, CSC.exe

/reference:System.Drawing.dll . -

System.Drawing.dll CSC.
exe , DLL CLR,
. ,
,
.
, .NET Framework , Microsoft, .
CLR, GAC. CLR
, GAC
.
CSC.exe GAC,
, GAC . ,
:
System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken= b03f5f7f11d50a3a

,
.
, CLR . ,
. IL ,
x86, x64 ARM. GAC
IL, .
,
GAC ;
, .

106

3.




CLR ,
. GAC
RSA,
PE- ( ).
, .
, FileDef.
,
GAC .
, , CLR
GAC (, ,
). ,
, , .
,
, ,
.
, AssemblyRef
, AssemblyDef , . GAC, CLR
, ,
; , MSI, CLR
MSI .
, System.
IO.FileNotFoundException.

GAC, ,
, , . .
CLR ,
, .
, GAC, CLR
,
,
.

GAC,
( , codeBase

107

) CLR -. ,
.
, , .
-, CLR System.
IO.FileLoadException.



SN.exe. ,
Microsoft API-
Crypto. . , ( Microsoft)
,
.

. , , ,
.
,
. , ,
.NET Framework (delayed signing),
(partial signing).
,
. AssemblyRef
, ,
, GAC.
, , ,
. ,
,
.
, . ( , , , SN.exe
p.) ,
, , .
C# /delaysign. Visual Studio
Signing Delay sign only.
AL.exe /delay[sign].

108

3.

, ,

AL.exe AssemblyDef

. , GAC, , ,
AssembyRef
. PE-
RSA. ( , .) ,
.
. GA , -
, .
GAC, , SN.exe
Vr. SN.exe CLR
- .
Vr SN.exe
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification.

, , , 64-
64- . 32- x86
C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\
NETFX 4.0 Tools, 64 x64 C:\Program
Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\x64.

,
. ,
SN.exe, R, , . R SN.exe
,
RSA . .
, SN.exe
Vu Vx.
.
1. , ,
/keyfile /delaysign:
csc /keyfile:MyCompany.PublicKey /delaysign MyAssembly.cs

109

2. ,
, GAC
, .
, .
SN.exe -Vr MyAssembly.dll

3. ,
.
GAC,
4.
SN.exe -R MyAssembly.dll MyCompany.PrivateKey

4. :
SN -Vu MyAssembly.dll


, -.
, ,
. (Cryptographic Service Providers, CSP)
, . , Microsoft
CSP-,
.
CSP-,
CSC.exe, AL.exe SN.exe.
(CSC.exe) /keyfile /keycontainer,
(AL.exe) /keyname /keyfile, SN.exe
, ,
-Rc -R. SN.exe
CSP.

, -
. , , .
, - .
, .
SN.exe -R -Rc,
-.

110

3.



GAC . GAC
,
. , GAC

(.). GAC
. GAC
,
GAC . , GAC
.
GAC,
. GAC,
. , .

. , GAC
C:\Windows\System32
.
, .

codeBase URL,

Web. - CLR
(
C:\Documents and Settings\<UserName>\Local Settings\ApplicationData\Assembly,
<UserName> , ). CLR
URL-. , CLR (
).
codeBase .

GAC , , . , ,
.

.
XML-, codeBase .

111

CLR , , . ,
. ,
,
.



2 :
public sealed class Program {
public static void Main() {
System.Console.WriteLine("Hi");
}
}

Program.exe. CLR.

CLR CLR- MethodDefToken,


Main, .
CLR MethodDef , IL- ,
JIT-.
, . IL- Main. ,
ILDasm.exe, View Show Bytes
Main .
.method public hidebysig static void Main() cil managed
// SIG: 00 00 01
{
.entrypoint
// Method begins at RVA 0x2050
// Code size
11 (0xb)
.maxstack 8
IL_0000: /* 72 | (70)000001 */
ldstr
"Hi"
IL_0005: /* 28 | (0A)000003 */
call
void [mscorlib]System.Console::WriteLine(string)
IL_000a: /* 2A |
*/
ret
} // end of method Program::Main

JIT- CLR
, ( -

112

3.

). , System.Console.
Write-Line: Call 0A000003.
3 MemberRef ( 0A). , CLR ,
TypeRef ( System.Console). TypeRef
CLR AssemblyRef:
MSCorLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

CLR , ,
.
CLR
.
. , , ( ).
, .
. , ,
, FileRef .
, ,
. , -,
, CLR
, .
. , ,
, .
,
, CLR , .

ModuleDef, ModuleRef FileDef


. AssemblyRef
, . DLL EXE,
, 2.

(
, - ..), .

System.AppDomain.AssemblyResolve, System.AppDomain.
ReflectionOnlyAssemblyRessolve System.AppDomain. TypeResolve. ,
.

113

CLR , System.Console . CLR PE-,


.
PE-, .
, , , , CLR
.
CLR
JIT- Main.
Main.
3.2 .

. 3.2. - , CLR, ,
, IL-

- , .
: CLR , , . GAC ,
, , .
GAC CLR , -

114

3.

32- x86 (, WoW64),


64- x64 64- ARM.
GAC .
.

, .
, , .NET Framework,
. .NET Framework ( MSCorLib.dll)
CLR. , .NET
Framework, CLR. (unification), Microsoft ,
.NET Framework CLR.
.
WriteLine System.Console MSCorLib.dll, CLR, ,
MSCorLib.dll AssemblyRef .

, CLR , ,
.
. CLR
.

CLR (, , , ) . ,
.NET3.5 System.TimeZoneInfo System.Core.dll. .NET
4.0 Microsoft MsCorLib.dll.
.
CLR System.Runtime.CompilerServices.
TypeForwardedToAttribute, (, System.Core.dll). System.
Type. ( MSCorLib.dll), . ,
TypeForwardedToAttribute ,
, .
,
System.Runtime.CompilerServices.TypeForwardedToAttribute
, .
, . TypeForwardedToAttribute
, , , ,
.

( )

115


( )
( ) 2
, CLR. ,
, ,
CLR XML
.
2 privatePath probing,
XML-:
<?xml version="1.0"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas
microsoft
com:asm.v1">
<probing privatePath="AuxFiles;bin\subdir" />
<dependentAssembly>
<assemblyIdentity name="SomeClassLibrary"
publicKeyToken="32ab4ba45e0a69a1" culture="neutral"/>
<bindingRedirect
oldVersion="1.0.0.0" newVersion="2.0.0.0" />
<codeBase version="2.0.0.0"
href="http://www.Wintellect.com/SomeClassLibrary.dll" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="TypeLib"
publicKeyToken="1f2e74e897abbcfe" culture="neutral"/>
<bindingRedirect
oldVersion="3.0.0.0
3.5.0.0" newVersion="4.0.0.0" />
<publisherPolicy apply="no" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

XML- CLR .
probing. AuxFiles bin\subdir, ,

116

3.

. GAC URL-, codeBase. CLR


, codeBase .
dependentAssembly, assemblyIdentity bindingRedirect. SomeClassLibrary
1.0.0.0 , ,
32ab4ba45e0a69a1,
, 2.0.0.0.
codebase. SomeClassLibrary
2.0.0.0 , , 32ab4ba45e0a69a1,
, URL: http://wwwWintellect.
com/SomeClassLibrary.dll. 2, codeBase
.
codeBase.
URL, codeBase,
.
dependentAssembly, assemblyIdentity bindingRedirect. TypeLib 3.0.0.0
3.5.0.0 ,
, 1f2e74e897abbcfe,
4.0.0.0 .
publisherPolicy. , TypeLib,
( .
), CLR .
CLR , . , (
AssemblyRef ),
. CLR

, .
apply publisherPolicy yes , CLR GAC /
, (
); CLR /. CLR / Machine.config
.
CLR , , GAC. GAC
, codeBase , CLR ,

( )

117

2. ,
, codeBase, CLR URL-,
.

, CLR
. , , ,
. CLR ,
.
CLR ,
XML- .
, , ,
,
Machine.config , CLR
.
, ,
, , . ,
, . .


, ,
,
XML- .
, .
, - CLR
. ,
XML- ,
. ,

. , .
, , ,
.
, XML-. ,
. SomeClassLibrary.
config SomeClassLibrary.dll:
<configuration>
<runtime>

118

3.
<assemblyBinding xmlns="urn:schemas
microsoft
com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="SomeClassLibrary"
publicKeyToken="32ab4ba45e0a69a1" culture="neutral"/>
<bindingRedirect
oldVersion="1.0.0.0" newVersion="2.0.0.0" />
<codeBase version="2.0.0.0"
href="http://www.Wintellect.com/SomeClassLibrary.dll"/>

</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

, .
, , . ,
probing publisherPolicy.
CLR
1.0.0.0 SomeClassLibrary 2.0.0.0. ,
, ,
. AL.exe
:
AL.exe /out:Policy.1.0.SomeClassLibrary.dll
/version:1.0.0.0
/keyfile:MyCompany.snk
/linkresource:SomeClassLibrary.config

AL.exe.
/ o u t AL.exe PE-
Policy.1.0.SomeClassLibrary.dll, , .
. , Policy,
CLR, .
, 1.0, CLR,
SomeClassLibrary,
1.0. ;
. , SomeClassLibrary,
, . , dll, ,
.
/version ,
. ,

( )

119

, , . , CLR 1.0.0.0
SomeClassLibrary 2.0.0.0, ,
1.0.0.0 SomeClassLibrary 2.5.0.0.
CLR , ,
.
/keyfile AL.exe
, .
, SomeClassLibrary. , CLR
, SomeClassLibrary
.
/linkresource AL.exe
XML .
.
SomeClassLibrary.
, XML- , AL.exe /embedresource,
CLR ,
XML .
, ,
SomeClassLibrary.dll . GAC. SomeClassLibrary
GAC, .
, URL-
codeBase.


.
.

. ,
, - , . , CLR
.
, publisherPolicy:
<publisherPolicy apply="no"/>


<assemblyBinding> -

120

3.

. <dependantAssembly>, .
, CLR , GAC
, . , CLR ,
Machine.config.

.
, . , ,
. . ,
, ,
. ,
.

II

4. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..122
5. ,
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 142
6. . .. .. .. .. 186
7. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 210
8. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..215
9. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 245
10. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..263
11. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 286
12. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 302
13. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..333

4.
(Common Language Runtime, CLR). , , , ,
, ,
. , , , .

System.Object
CLR System.
Object. , :
// , Object
class Employee {
...
}
// , Object
class Employee : System.Object {
...
}

, , ,

System.Object,
. System.Object -

. 4.1.

4.1. System.Object

Equals

true, .

5

GetHashCode

- .
, -. , Object
,
-; .
- 5

System.Object

123

ToString

(this.GetType().
FullName). ,
String,
. , , Boolean Int32,
. , :
, . ,
ToString CultureInfo, . ToString
14

GetType

, Type,
, GetType.
Type , .
23. GetType , ,
;

, , System.Object, (.4.2).
4.2. System.Object

Memberwise
Clone


this.

Finalize

, , ,
. ,
, . .
21

CLR , new. ,

Employee :

Employee e = new Employee("ConstructorParam1");

new :

124

4.

1. , , System.Object (
). ,
,
- (type object pointer) (sync block
index); CLR . ,
.
2.
. (0).
3. - .
4. ,
new ( ConstructorParam1 ).

.
. , System.
Object, .
, new ( )
. e Employee.
, new delete,
, . CLR
(.21), ,
, .


CLR (type safety).
CLR .
GetType.
, .
, Employee GetType,
SuperHero.
.
CLR
. -. , C#
,

125

.
C# .
:
// System.Object
internal class Employee {
...
}
public sealed class Program {
public static void Main() {
// , . . new Employee,
// Object Employee.
Object o = new Employee();
// , . . Employee Object
// ( Visual Basic)
//
Employee e = (Employee) o;
}
}

, .
, . CLR
, , . , ,
InvalidCastException:
internal class Employee {
...
}
internal class Manager : Employee {
...
}
public sealed class Program {
public static void Main() {
// Manager PromoteEmployee
// Manager Employee,
// PromoteEmployee
Manager m = new Manager();
PromoteEmployee(m);
// DateTime PromoteEmployee
// DateTime Employee,
// PromoteEmployee
// System.InvalidCastException
DateTime newYears = new DateTime(2013, 1, 1);
PromoteEmployee(newYears);
}

126

4.

public static void PromoteEmployee(Object o) {


// ,
// o,
// CLR ,
// o ( ),
// , Employee
// , Employee
Employee e = (Employee) o;
...
}
}

Main Manager PromoteEmployee.


, Manager
Object, PromoteEmployee. PromoteEmployee CLR , o Employee ,
Employee. Manager Employee , CLR
, PromoteEmployee .
PromoteEmployee , Main
DateTime, PromoteEmployee. DateTime Object, , PromoteEmployee,
. PromoteEmployee CLR , o
DateTime, Employee, , Employee. CLR
System.InvalidCastException.
, . :
, , .
,
CLR .
PromoteEmployee
Object, Employee,
, , . Object , ,
C# CLR.

C# is as
C# . , is
,
Boolean (true false). is . :
Object o = new Object();
Boolean b1 = (o is Object); // b1 true
Boolean b2 = (o is Employee); // b2 false

127

null- is false, ,
, .
is :
if (o is Employee) {
Employee e = (Employee) o;
// e if
}

CLR :

is o Employee, if
, o Employee. CLR -

, ,
CLR , (o),
(Employee).
, C# ,
as:
Employee e = o as Employee;
if (e != null) {
// e if
}

CLR o Employee. o Employee


, as , as null. : as CLR
, if e null
, .
, as ,
. , null.
null , System.
NullReferenceException. :
System.Object o = new Object(); // Object
Employee e = o as Employee; // o Employee
// : , e null
e.ToString(); // e NullReferenceException

, . ,
:
internal class B { //
}
internal class D : B { //
}

.4.3 C#.
CLR.

128

4.

, OK,
CTE (compile-time error),
RTE (run-time error).
4.3.

OK

Object o1 = new Object();

Object o2 = new B();

Object o3 = new D();

Object o4 = o3;

B b1 = new B();

B b2 = new D();

D d1 = new D();

CTE

B b3 = new Object();

D d2 = new Object();

B b4 = d1;

RTE

D d3 = b2;

D d4 = (D) d1;

D d5 = (D) b2;

D d6 = (D) b1;

B b5 = (B) o1;

B b6 = (D) b2;

C# ,
8. , ,
is as C#.


,
. ,
System.Text , System.

129

IO -.
System.IO.FileStream System.Text.StringBuilder:
public sealed class Program {
public static void Main() {
System.IO.FileStream fs = new System.IO.FileStream(...);
System.Text.StringBuilder sb = new System.Text.StringBuilder();
}
}

FileStream
StringBuilder . ,
, . , C# using.
:
using System.IO; // "System.IO"
using System.Text; // "System.Text"
public sealed class Program {
public static void Main() {
FileStream fs = new FileStream(...);
StringBuilder sb = new StringBuilder();
}
}

,

, . , FileStream System.IO.FileStream, StringBuilder System.
Text.StringBuilder.
using C# ,
. using C#
, .

CLR . -
CLR (
) , ,
, .

, :
, , ,
, ..
, System.IO ,
. ,

130

4.

System.Text. using,
, FileStream StringBuilder
System.IO.FileStream System.
Collections.StringBuilder. , ,
, .
/reference (. 2
3), .
. ,

. ,
, . C# MSCorLib.dll,
. FCL-,
Object, Int32, String .
, , ( ) .
Microsoft
. . CLR
. , , Microsoft
Wintellect, , Widget.
Widget Microsoft , Wintellect .
,
, .
Widget Microsoft Microsoft.Widget,
Widget Wintellect Wintellect.Widget.
Widget , C# error CS0104: 'Widget'
is an ambiguous reference ( CS0104: 'Widget' ):
using Microsoft; // "Microsoft."
using Wintellect; // "Wintellect."
public sealed class Program {
public static void Main() {
Widget w = new Widget(); //
}
}

, ,
Widget :
using Microsoft; // "Microsoft."
using Wintellect; // "Wintellect."
public sealed class Program {
public static void Main() {
Wintellect.Widget w = new Wintellect.Widget(); //
}
}

131

C# using,
. , ,
.
:
using Microsoft; // "Microsoft."
using Wintellect; // "Wintellect."
// WintellectWidget Wintellect.Widget
using WintellectWidget = Wintellect.Widget;
public sealed class Program {
public static void Main() {
WintellectWidget w = new WintellectWidget(); //
}
}

, .
, Australian Boomerang Company (ABC) Alaskan Boat
Corporation (ABC) BuyProduct
. , ABC, BuyProduct.
, , ,
, .
, C# (extern aliases),
. ( ) .
. C#.
, , ,
, . ,
, . .NET
Framework SDK Microsoft Microsoft
(: Microsoft.CSharp, Microsoft.VisualBasic Microsoft.Win32).
, ( C#):
namespace CompanyName {
public sealed class A {
}

// TypeDef: CompanyName.A

namespace X {
public sealed class B { ... } // TypeDef: CompanyName.X.B
}
}

,

CLR .

132

4.

,
. C# namespace
.


(, )
. , , , . ,
System.IO.FileStream MSCorLib.dll, System.
IO.FileSystemWatcher System.dll. , System.IO.dll
.NET Framework .
. ,
System.Int32 System.Text.StringBuilder MSCorLib.dll.
.NET Framework SDK, ,
, , ,
. .4.1 , ResXFileRef System.Resources System.Windows.Forms.
dll. , ResXFileRef, using System.Resources
/r:System.Windows.forms.dll.

. 4.1. SDK

133



, , , . , ,
, . . , ,
, CLR, ,
, CLR.
.4.2 Microsoft Windows
CLR. .
1.

. .4.2 .
(
). - ,
- (
). , , M1.

. 4.2. M1

, , (prologue
code), . , (epilogue code), ,
, . M1
name (.4.3).
M1 M2, name. name (.4.4).
M2 - s. (,
,

134

4.

.)
( .4.4).

. 4.3. M1

. 4.4. M2 M1 .

M2
length tally (.4.5).
M2. , M2 , , M2
, .4.3.
M1, M2,
, M1.
, M1 ,
( , name), M1
, .4.2.
, , M1,
, .

135

. 4.5. M2

CLR. ,
:
internal
public
public
public
}

class Employee {
Int32 GetYearsEmployed () { ... }
virtual String GetProgressReport () { ... }
static Employee Lookup(String name) { ... }

internal sealed class Manager : Employee {


public override String GenProgressReport() { ... }
}

Windows , CLR,
, ( 1 ). - , M3 (.4.6). M3
, , CLR;
, , , .
IL- 3 JIT
, M3, Employee,
Int32, Manager String (- "Joe"). CLR ,
. , , CLR
, .
- Employee Manager .4.7.
M3 - , , - Int32 String ( ,
), .
-.
, : - . Employee
Manager .

136

4.

.
-. , -
, . 1. Employee
(GetYearsEmployed, GenProgressReport Lookup),
. Manager (
GenProgressReport), .

. 4.6. CLR , ,
, M3

. 4.7. M3 Employee Manager

137

CLR -
M3,
M3. M3 (.4.8). , CLR
null 0 ()
.
, , #
Use of unassigned local variable ( ).

. 4.8. M3

M3 Manager.
Manager, Manager (.4.9).
Manager -
. ,
, Manager,
,
Manager ( Employee Object). CLR
- , - (
- Manager). , CLR
null
0 () , , ,
. new
Manager, e ( ).

138

4.

. 4.9. Manager

M3 Lookup
Employee. CLR -,

, .
- CLR ,
JIT- ( )
. ,
Lookup Employee ,
Joe. , , Joe , Lookup Manager,
Joe . e. .4.10.
M3
GenProgressReport Employee.
CLR . -, CLR
, , . e Joe
Manager. -, CLR -.
CLR - ,
JIT- ( )
. GenProgressReport
Manager, e Manager.
.4.12.
, Lookup Employee , Joe
Employee, Manager, Lookup Employee,

139

- - Employee; ,
GenProgressReport Employee, Manager.

. 4.10. Lookup Employee .


Manager Joe

. 4.11. GetYarsEmployeed Employee


5

, , IL
JIT-, , ,
, .
, - (

140

4.

). , CLR
, . CLR , , .
, CLR.

. 4.12. GenProgressReport Employee


Manager

. 4.13. Manager Employee System.Type

, Employee Manager -. - .

141

-, CLR - .
: ? ,
CLR -
System.Type ( MSCorLib.dll). Employee Manager , -
- System.Type (.4.13).
, - System.Type -; , ,
. , - System.
Type -. , CLR. , GetType
System.Object , -
. , GetType
( -).

5. ,

,
Microsoft .NET Framework. ,
. .NET Framework, , ,
,
. ,
.

,
. ,
:
System.Int32 a = new System.Int32();

, . , ( C#)
, :
int a = 0;

, IL- System.Int32. , , (primitive types);


.NET Framework Class Library
(FCL). , int C# System.Int32, IL-:
int a = 0; //
System.Int32 a = 0; //
int a = new int(); //
System.Int32 a = new System.Int32(); //

143

. 5.1 FCL
C#. ,
(Common Language Specification, CLS),
. , CLS,
.
5.1. # FCL

FCL-

CLS

sbyte

System.Sbyte

8-

byte

System.Byte

8-

short

System.Int16

16-

ushort

System.Uint16

16-

int

System.Int32

32-

uint

System.Uint32

32-

long

System.Int64

64-

ulong

System.Uint64

64-

char

System.Char

16- Unicode (char 8- , ++)

float

System.Single

32- IEEE

double

System.Double

64- IEEE

bool

System.Boolean

(true false)

decimal

System.Decimal

128-
,
,
. ,
96
, 8
10,
96- ( 0 28).

144

5. ,

5.1 ()

FCL-

CLS

string

System.String

object

System.Object

dynamic

System.Object

CLR dynamic
object. #
dynamic
.

dynamic

, , C# ,
using ( 4):
using
using
using
using
using
using
...

sbyte = System.SByte;
byte = System.Byte;
short = System.Int16;
ushort = System.UInt16;
int = System.Int32;
uint = System.UInt32;


C#:
, ,
FCL- . , , ,
FCL-. .
, , : string String. C# ,
string FCL- System.String. ,
, 32-
int 32- , 64 64 . : C# int
System.Int32, 32-
.
Int32 .
C# long System.Int64,
Int16 Int32. , ++/CLI long Int32.

145

- , ,
.
long, , .
FCL- , . , BinaryReader ReadBoolean, ReadInt32, ReadSingle
.., System.Convert ToBoolean, ToInt32, ToSingle ..
, , float,
; , :
BinaryReader br = new BinaryReader(...);
float val = br.ReadSingle(); // ,
Single val = br.ReadSingle(); //

, #, ,
CLR . ,
FCL #, FCL
, GetLongLength Array, Int64, long #,
(, C++/CLI). LongCount
System.Linq.Enumerable.
FCL.
:
Int32 i = 5; // 32-
Int64 l = i; // 64-

, 4,
, . - System.Int32 System.Int64,
. : , . , C#
.
, IL-,
, . , ,
, .
,
, :
Int32 i = 5; //
Int64 l = i; //
Single s = i; //
Byte b = (Byte) i; //
Int16 v = (Int16) s; //

Int32 Int32
Int32 Int64
Int32 Single
Int32 Byte
Single Int16

C# , ,
; Int32 Int64.

146

5. ,

C#
. . , Int32 Byte
, Int32
; Single Int16,
Single , Int16.

. , 6,8 Single Int32 , Int32 6,
7. , C# .

C#, (Conversions).
, : .
, ,
, :
Console.WriteLine(123.ToString() + 456.ToString()); // "123456"

, , , , , .
Boolean found = false; // found 0
Int32 x = 100 + 20 + 3; // x 123
String s = "a " + "bc"; // s "a bc"

, ,
( +, -, *, /, %, &, ^, |, ==, !=, >, <, >=, <=,
<<, >>, ~, !, ++, -- ..):
Int32 x = 100; //
Int32 y = x + 23; //
Boolean lessThanFifty = (y < 50); // " "



, :
Byte b = 100;
b = (Byte) (b + 200);// b 44 (2C )

, , . ,
(, - ),
, .

147

CLR
32 ( 64 ,
32 ). b 200 ( 32
) 32- , . 32- (300 , 12C
), b,
Byte. C# ,
Byte.

. C C++
, . Visual Basic
, .
CLR IL-, -
. , add,
, add.ovf, System.OverflowException. , CLR
IL- (sub/sub.ovf), (mul/mul.ovf)
(conv/conv.ovf).
C# , ; . ,
, , IL . , ,
.
,
/checked+. , , ,
IL-
. , CLR
, . , CLR OverflowException.
.
. ,
. C#
checked unchecked. (, ):
UInt32 invalid = unchecked((UInt32) -1); // OK

checked:
Byte b = 100; //
b = checked((Byte) (b + 200)); // OverflowException

148

5. ,

b 200 32- ; 300. 300 Byte


OverflowException. Byte checked,
:
b = (Byte) checked(b + 200); // b 44; OverflowException

checked unchecked C# ,
:
checked { //
Byte b = 100;
b = (Byte) (b + 200); //
} //

, += Byte,
:
checked { //
Byte b = 100;
b += 200; //
} //

,
checked, ( ) checked IL- , ,
. :
checked {
// , SomeMethod 400 Byte
SomeMethod(400);
// OverflowException SomeMethod
//
}

, .
-
- . , checked
unchecked.
(Int32 Int64)
(UInt32 UInt64) , . . ,
(, Length Array String) ,
( ,

149

). ,
CLS.
checked , , ,
, .
, OverflowException,
.
unchecked ,
(, ).
, checked unchecked, ,
. ,
,
.
/checked+. ,
, checked unchecked.
, .
/checked-, ; .
checked Microsoft Visual Studio,
, Build, Advanced
Check for arithmetic overflow/underflow, .5.1.

. 5.1. .
Visual Studio Advanced Build Settings

, /checked .

150

5. ,


. ,
, OverflowException,
- .

System.Decimal .
( C# Visual Basic), CLR Decimal .
CLR IL- Decimal. .NET
Framework , Decimal - Add,
Subtract, Multiply, Divide , +, -, *, / ..
Decimal
Decimal, . Decimal
CLR-. , IL-
Decimal,
checked unchecked, , Decimal
OverflowException.
, System.Numerics.BigInteger UInt32
,
. , BigInteger
OverflowException.
OutOfMemoryException, .


CLR : (reference types) (value types). FCL ,
.
, C# new ,
.
, :
;
, , , ;
(
);
.
,
. , ,

151

Int32 ! , , CLR
.
( ).
;
. , (dereference) .
,
,
,
.
.NET Framework , , . (class),
. , System.Object, System.Exception,
System.IO.FileStream System.Random . ,
(structure) (enumeration). , System.Int32, System.Boolean,
System.Decimal, System.TimeSpan System.DayOfWeek, System.
IO.FileAttributes System.Drawing.FontStyle .
System.
ValueType , , , System.
Object. System.
ValueType. System.Enum, System.ValueType . CLR -
. . 15.

, . , CLR ,
-
. , ,
Boolean, Char, Int32, Uint64, Single, Double, Decimal ..

( , , C/C++)
. C/C++ , ,
: . : ,
, , ,
, , .

( .5.2) :

152

5. ,

// ( 'class')
class SomeRef { public Int32 x; }
// ( 'struct')
struct SomeVal { public Int32 x; }
static void ValueTypeDemo() {
SomeRef r1 = new SomeRef(); //
SomeVal v1 = new SomeVal(); //
r1.x = 5; //
v1.x = 5; //
Console.WriteLine(r1.x); // "5"
Console.WriteLine(v1.x); // "5"
// . 5.2
//
SomeRef r2 = r1; // ()
SomeVal v2 = v1; //
r1.x = 8; // r1.x r2.x
v1.x = 9; // v1.x, v2.x
Console.WriteLine(r1.x); // "8"
Console.WriteLine(r2.x); // "8"
Console.WriteLine(v1.x); // "9"
Console.WriteLine(v2.x); // "5"
// . 5.2
//
}

. 5.2.

SomeVal struct,
class. C# , struct,
, class, .

153

.
, : ,
.
:
SomeVal v1 = new SomeVal(); //

, SomeVal .
C# , SomeVal ,
SomeVal . C#
.
:
SomeVal v1; //

IL-, SomeVal . , , new, C# .


:
// , C# ,
// v1
SomeVal v1 = new SomeVal();
Int32 a = v1.x;
// , C# ,
// v1
SomeVal v1;
Int32 a = v1.x;
// error CS0170: Use of possibly unassigned field 'x'
// ( CS0170: 'x', )

, ,
. .
, .
. , ,
,
, , (immutable).
, readonly
(.7).
.
.
, ;
, . :
, , ,

154

5. ,

, .
, :
( 16 ).
( 16 ),
.
, . ,
. :
(. ):
(unboxed) (boxed).
.
System.ValueType.
, System.Object. System.ValueType
Equals, true,
. , System.ValueType GetHashCode,
- , . - , ,
Equals GetHashCode. Equals
GetHashCode .
,
.
( ).
. , null,
.
NullReferenceException.
,
0.
,
NullReferenceException . CLR
, null (nullable types).
19.

, . -

155

,
.

, ,
, , .

,
.
,
, ( ).

CLR
CLR
. , CLR ,
, . ,
, ,
CLR .
CLR ,
System.Runtime.InteropServices.StructLayout
Attribute. CLR, LayoutKind.Auto, LayoutKind.Sequential, LayoutKind.
Explicit , . StructLayoutAttribute,
.
() C# LayoutKind.
Auto, () LayoutKind.Sequential. , , , , ,
. ,
, , , , , :
using System;
using System.Runtime.InteropServices;
// CLR
//
[StructLayout(LayoutKind.Auto)]
internal struct SomeValType {
private readonly Byte m_b;

156

5. ,

private readonly Int16 m_x;


...

StructLayoutAttribute
, LayoutKind.Explicit.
System.Runtime.InteropServices.FieldOffsetAttribute
Int32,
( ) .
, C/C++
(union),
, :
using System;
using System.Runtime.InteropServices;
//
[StructLayout(LayoutKind.Explicit)]
internal struct SomeValType {
[FieldOffset(0)]
private readonly Byte m_b; // m_b m_x
[FieldOffset(0)]
private readonly Int16 m_x; //
}

, . ,
,
, .


: , ,
. ,
Point ArrayList
( System.Collections). :
//
struct Point {
public Int32 x, y;
}
public sealed class Program {
public static void Main() {

157

ArrayList a = new ArrayList();


Point p; // Point ( )
for (Int32 i = 0; i < 10; i++) {
p.x = p.y = i; //
a.Add(p); //
// ArrayList
}
...
}
}

Point,
Point ArrayList. , ArrayList:
Point, Point - ?
Add ArrayList .
Add :
public virtual Int32 Add(Object value);

, Add Object,
( ) .
p, Point. , Point .
(boxing).
.
1. .
.
.
2. , .
3. . ,
.
C# IL-, , , ,
.
C# , ,
, ,
. p Point
Point. Point ( )
Add. Point . p Point , ArrayList
. :
.

158

5. ,

FCL , -
. , System.
Collections.ArrayList System.Collections.Generic.List<T>.
. , API- , ,
.
, /.
, , ,
, .
,
(. 12).

, . ,
ArrayList:
Point p = (Point) a[0];

( ), 0

ArrayList, p Point. ,
Point, p

, . CLR
. Point Point.
(unboxing).
, .
.
, ,
( ), . ,
,
( ) .
.
, / ( ,
), ,
, .
.
1. , ,
null, NullReferenceException.
2. ,
, InvalidCastException1.
CLR , null (. 19).
1

159

, ,
:
public static void Main() {
Int32 x = 5;
Object o = x; // x; o
Int16 y = (Int16) o; // InvalidCastException
}

, Int32, o, Int16. ( Int32).


:
public static void Main() {
Int32 x = 5;
Object o = x; // x; o
Int16 y = (Int16)(Int32) o; // ,
}

, .
C# ,
:
public static void Main() {
Point p;
p.x = p.y = 1;
Object o = p; // p; o
p = (Point) o; // o
}

C# IL- o( ) IL
p, .
:
public static void Main() {
Point p;
p.x = p.y = 1;
Object o = p; // p; o
// x Point ( 2).
p = (Point) o; // o
//
p.x = 2; //
o = p; // p; o
}

x Point 1 2.
, , () ( ). , ,
.

160

5. ,

, C++/CLI, , .
(
). ,
, (
). ,
C++/CLI ,
x Point Point. ,
!


, , ,
. , ,
. , ,
ILDasm.exe, IL- ,
.

, :
public static void
Int32 v = 5; //
Object o = v; //
v = 123; //

Main() {
o
Int32, 5
123

Console.WriteLine(v + ", " + (Int32) o); // "123, 5"


}

?
! , , IL- Main.
, .
.method public hidebysig static void
{
.entrypoint
// 45 (0x2d)
.maxstack 3
.locals init ([0]int32 v,
[1] object o)
// 5 v.
IL_0000: ldc.i4.5
IL_0001: stloc.0

Main() cil managed

// v o.
IL_0002: ldloc.0


IL_0003:
IL_0008:

box
stloc.1

161

[mscorlib]System.Int32

// 123 v.
IL_0009: ldc.i4.s
123
IL_000b: stloc.0
// v Concat
IL_000c: ldloc.0
IL_000d: box
[mscorlib]System.Int32
// Concat
IL_0012: ldstr ", "
// o: Int32
IL_0017: ldloc.1
IL_0018: unbox.any [mscorlib]System.Int32
// Int32 Concat
IL_001d: box
[mscorlib]System.Int32
// Concat
IL_0022: call string [mscorlib]System.String::Concat(object,
object,
object)
// , Concat, WriteLine
IL_0027: call
void [mscorlib]System.Console::WriteLine(string)
// Main ,
IL_002c: ret
} // App::Main

v Int32,
5. o Object, v.
, C# IL-
v v o. 123
v,
Int32, 5.
WriteLine, String,
. Int32 (v), String ( )
Int32 (o), Int32. - ,
String.
String, C# ,
Concat String.
, .

162

5. ,

, Concat:
public static String Concat(Object arg0, Object arg1, Object arg2);

, arg0, v. v
, arg0 Object, v ,
arg0. arg1 ","
String. , arg2, o(
Object) Int32. ( ), Int32
Int32. Int32
, arg2 Concat.
Concat ToString .
Concat String WriteLine,
.
IL- , WriteLine :
Console.WriteLine(v + ", " + o); // "123, 5"

o (Int32). ,
o Object
Concat. , :
. ,
IL-:
.method public hidebysig static void
{
.entrypoint
// 35 (0x23)
.maxstack 3
.locals init ([0] int32 v,
[1] object o)

Main() cil managed

// 5 v
IL_0000: ldc.i4.5
IL_0001: stloc.0
// v o
IL_0002: ldloc.0
IL_0003: box
[mscorlib]System.Int32
IL_0008: stloc.1
// 123 v
IL_0009: ldc.i4.s
123
IL_000b: stloc.0

163

// v Concat
IL_000c: ldloc.0
IL_000d: box
[mscorlib]System.Int32
// Concat
IL_0012: ldstr ", "
// Int32 Concat
IL_0017: ldloc.1
// Concat
IL_0018: call string [mscorlib]System.String::Concat(object,
object,
object)
// , Concat, WriteLine
IL_001d: call
void [mscorlib]System.Console::WriteLine(string)
// Main ,
IL_0022: ret
} // App::Main

IL- Main ,
Int32 10 , . /, ,
. , ,
, . ,
, ,
(, ),
.
, WriteLine:
Console.WriteLine(v.ToString() + ", " + o); // "123, 5"

v ToString, String.
Concat .
, :
public static void Main() {
Int32 v = 5; //
Object o = v; // o v
v = 123; // 123
Console.WriteLine(v); // "123"
v = (Int32) o; // o v
Console.WriteLine(v); // "5"
}

164

5. ,

? .
, System.Console WriteLine,
Int32:
public static void WriteLine(Int32 value);

WriteLine v,
Int32, . , - WriteLine
Int32, .
, : .
FCL, , . , System.Console
WriteLine:
public
public
public
public
public
public
public
public
public
public
public
public

static
static
static
static
static
static
static
static
static
static
static
static

void
void
void
void
void
void
void
void
void
void
void
void

WriteLine(Boolean);
WriteLine(Char);
WriteLine(Char[]);
WriteLine(Int32);
WriteLine(UInt32);
WriteLine(Int64);
WriteLine(UInt64);
WriteLine(Single);
WriteLine(Double);
WriteLine(Decimal);
WriteLine(Object);
WriteLine(String);

Write System.
Console, Write System.IO.BinaryWriter, Write WriteLine System.IO.TextWriter, AddValue System.Runtime.Serialization.SerializationInfo, Append Insert System.Text.
StringBuilder ..

,
.
, FCL-
. ,
, FCL, . ,
,
, Object.
Object , .
, (,
, ).
, ,
(.12).
, : , - , -

165

,
. .
using System;
public sealed class Program {
public static void Main() {
Int32 v = 5; //
#if INEFFICIENT
// v
// , ,
Console.WriteLine("{0}, {1}, {2}", v, v, v);
#else
// ,
//
Object o = v; // v ( )
//
Console.WriteLine("{0}, {1}, {2}", o, o, o);
#endif
}
}

INEFFICIENT, , v -

! ,
5.
INEFFICIENT, v
. Console.WriteLine
.
.
,
. : ,
. ,
, .
, .
, , ,
:
;
, :
.
, ,
System.Threading.Monitor ( lock
C#).

166

5. ,

,
(, Equals, GetHashCode
ToString), . , CLR
,
. , , , .

,
, this
.
(, GetType
MemberwiseClone) ,
System.Object, , this .
,
, , . (
. 13.) :
using System;
internal struct Point : IComparable {
private Int32 m_x, m_y;
// ,
public Point(Int32 x, Int32 y) {
m_x = x;
m_y = y;
}
// ToString, System.ValueType
public override String ToString() {
// Point ( ToString )
return String.Format("({0}, {1})", m_x.ToString(), m_y.ToString());
}
// CompareTo
public Int32 CompareTo(Point other) {
// ,
// (0, 0)
return Math.Sign(Math.Sqrt(m_x * m_x + m_y * m_y)
- Math.Sqrt(other.m_x * other.m_x + other.m_y * other.m_y));
}
// CompareTo IComparable
public Int32 CompareTo(Object o) {
if (GetType() != o.GetType()) {

167

throw new ArgumentException("o is not a Point");


}
// CompareTo
return CompareTo((Point) o);
}
}
public static class Program {
public static void Main() {
// Point
Point p1 = new Point(10, 10);
Point p2 = new Point(20, 20);
// p1 ToString ( )
Console.WriteLine(p1.ToString()); // "(10, 10)"
// p1 GetType ( )
Console.WriteLine(p1.GetType()); // "Point"
// p1 CompareTo
// p2 , CompareTo(Point)
Console.WriteLine(p1.CompareTo(p2)); // "-1"
// p1 , c
IComparable c = p1;
Console.WriteLine(c.GetType()); // "Point"
// p1 CompareTo
// CompareTo Point,
// CompareTo(Object),
// Point
// c , Point
Console.WriteLine(p1.CompareTo(c)); // "0"
// c , Point
// p2 , CompareTo(Object)
Console.WriteLine(c.CompareTo(p2));// "-1"
// c , p2
p2 = (Point) c;
// , p2
Console.WriteLine(p2.ToString());// "(10, 10)"
}
}

,
/.
ToString. ToString p1 . ,
p1 , ToString , , System.ValueType.

168

5. ,

, p1
, Point. JIT- ,
ToString Point, ,
() ToString. ,
, Point ,
- . ToString Point
base.ToString(),
ToString System.ValueType.
GetType. GetType p1 , Point GetType, System.
Object. GetType Point,
p1.
CompareTo. CompareTo p1 ,
Point CompareTo,
. : CompareTo p2 Point,
CompareTo,
Point. , p2 CompareTo ,
.
IComparable. p1 (), p1 ,
. p1,
c.
GetType , c
Point .
CompareTo. CompareTo p1 , Point CompareTo,
. , CompareTo
IComparable,
CompareTo, Object. , , .
, Point,
c CompareTo
.
CompareTo. CompareTo c
Point . c
IComparable,
CompareTo , Object. , , .
p2
CompareTo.

169

Point. c Point, , c, ,
p2, Point, .
, ,
. , .NET Framework,

.


(
)
, , . : ,
.
using System;
// Point - .
internal struct Point {
private Int32 m_x, m_y;
public Point(Int32 x, Int32 y) {
m_x = x;
m_y = y;
}
public void Change(Int32 x, Int32 y) {
m_x = x; m_y = y;
}
public override String ToString() {
return String.Format("({0}, {1})", m_x.ToString(), m_y.ToString());
}
}
public sealed class Program {
public static void Main() {
Point p = new Point(1, 1);
Console.WriteLine(p);
p.Change(2, 2);
Console.WriteLine(p);
Object o = p;

170

5. ,
Console.WriteLine(o);

((Point) o).Change(3, 3);


Console.WriteLine(o);

: Main p Point
m_x m_y 1. p WriteLine,
ToString Point, ,
, (1, 1). p Change,
m_x m_y p 2.
WriteLine, , (2, 2).
p o
Point. WriteLine (2, 2),
. , Change
Point. Object ( o)
Change, o Point.
o , Point
Point . m_x m_y
3, Change
Point. WriteLine
(2, 2). .

, C++/CLI,
, C#. C# , . :
using System;
// , Change
internal interface IChangeBoxedPoint {
void Change(Int32 x, Int32 y);
}
// Point -
internal struct Point : IChangeBoxedPoint {
private Int32 m_x, m_y;
public Point(Int32 x, Int32 y) {
m_x = x;
m_y = y;
}
public void Change(Int32 x, Int32 y) {
m_x = x; m_y = y;
}
public override String ToString() {
return String.Format("({0}, {1})", m_x.To_String(), m_y.ToString());

171

public sealed class Program {


public static void Main() {
Point p = new Point(1, 1);
Console.WriteLine(p);
p.Change(2, 2);
Console.WriteLine(p);
Object o = p;
Console.WriteLine(o);
((Point) o).Change(3, 3);
Console.WriteLine(o);
// p ,
((IChangeBoxedPoint) p).Change(4, 4);
Console.WriteLine(p);
//
((IChangeBoxedPoint) o).Change(5, 5);
Console.WriteLine(o);
}
}

.
, Change IChangeBoxedPoint
Point . Main WriteLine
( ).
Main .
p Point
IChangeBoxedPoint. p. Change
, m_x m_y 4,
Change
. WriteLine
(2, 2), .
Point, o, IChangeBoxedPoint. ,
o . Change, m_x
m_y Point. Change Point! WriteLine
(5, 5). , ,
. C#
.

172

5. ,

, ,
, -
. , readonly, ,
, .
.
,
. , ,
. ,
,
.
.
(, ), , . ,
, .
, , .
. ,
- ,
. Point class, struct
, . , ,
, FCL Byte, Int32, UInt32, Int64, UInt64,
Single, Double, Decimal, BigInteger, Complex ,
.


. ,
,
, .
, ,
, .
System.Object Equals,
true . Equals
Object:
public class Object {
public virtual Boolean Equals(Object obj) {
// ,
// ,
if (this == obj) return true;
// ,
return false;
}
}

173

:
, this obj, ,
true, false. ,
Equals , .
, Equals ,
, false. , ,
Equals Object
, .
, .
,
Equals.
Equals:
1. obj null, false, , ,
this, null Equals.
2. obj this , true.

.
3. obj this , false.
, String FileStream false.
4. obj this.
, false.
5. Equals ,
. Equals false, false,
true.
, Microsoft Equals
Object :
public class Object {
public virtual Boolean Equals(Object obj) {
// null
if (obj == null) return false;
//
if (this.GetType() != obj.GetType()) return false;
// , true ,
// .
// System.Object ,
// ,
return true;
}
}

, Microsoft Equals , Equals , . -

174

5. ,

Equals,
Equals ,
Object. ,
Equals Object,
. Object
ReferenceEquals :
public class Object {
public static Boolean ReferenceEquals(Object objA, Object objB) {
return (objA == objB);
}
}

ReferenceEquals (
, ).
== C# (
Object),
,
.
, .NET Framework
. , System.ValueType ( ) Equals Object
( ). :
1. obj null, false.
2. obj this ,
false.
3. , ,
obj this Equals .
, false.
4. true. Equals ValueType
Object.
3 Equals ValueType
(.23). CLR , Equals ,

. , ,
Equals .
Equals, , :
: x.Equals(x) true.
: x.Equals(y) y.Equals(x)
.

175

: x.Equals(y) true y.Equals(z)


true, x.Equals(z) true.
: ,
.
Equals
.
Equals
.
Equals System.IEquatable<T>.

Equals. Equals , ,
Object, Equals.
== !=. Equals.
, CompareTo System.Icomparable
CompareTo System.IComparable<T>.
, Equals ,
CompareTo System.IComparable<T> true, CompareTo 0. CompareTo
(<, <=, >, >=)
, CompareTo.

-
FCL , - .
System.Object GetHashCode, (Int32) -.
Equals, GetHashCode.
, C# . ,
: warning
CS0659: 'Program' overrides Object.Equals(Object o) but does not override
Object.GetHashCode() ('Program' Object.Equals(Object o),
Object.GetHashCode()).
public sealed class Program {
public override Boolean Equals(Object obj) { ... }
}

176

5. ,

, Equals
GetHashCode , , System.Collections.
Hashtable, System.Collections.Generic.Dictionary
, -. , Equals, GetHashCode
, , ,
- .
, - ,
- . ,
-. , -. -
, .
,
, .
-,
-, , -
-.
GetHashCode .

, .
, Point:
internal sealed class Point {
private readonly Int32 m_x, m_y;
public override Int32 GetHashCode() {
return m_x ^ m_y; // m_x m_y
}
...
}

- , :
, ,
-.
GetHashCode
,
GetHashCode Object ValueType, .
.
, , ,
.
.

dynamic

177

. , String, ,
-.
GetHashCode System.Object
. ,
; ,
.

- ,
GetHashCode, -.
. ,
-
.
, .
- , .
(String) GetHashCode, . -
, GetHashCode ,
- .
. , CLR
GetHashCode String -.
-!

dynamic
C# . , ,
, .
, , ,
,
.
,
IL
.
, - ,
, .
,
(, C#) ,
, , , -

178

5. ,

.
C#,
, ,
(. 23). #
, #.
, Python Ruby,
COM-, IDispatch (,
C++), DOM (Document Object
Model), .
DOM- Silverlight-.
, #
(dynamic). .
() ,
, /, , , /
. (), IL-,
. (payload).

, ().
, :
internal static class DynamicDemo {
public static void Main() {
dynamic value;
for (Int32 demo = 0; demo < 2; demo++) {
value = (demo == 0) ? (dynamic) 5 : (dynamic) "A";
value = value + value;
M(value);
}
}

private static void M(Int32 n) { Console.WriteLine("M(Int32): " + n); }


private static void M(String s) { Console.WriteLine("M(String): " + s); }

Main :
M(Int32): 10
M(String): AA

, , +.
dynamic. # ,
value ,
+.

dynamic

179

+ 5 ( Int32),
10 ( Int32).
value. M, value. M
,
, M.
value Int32, M,
Int32.
+ A ( String), AA ( ).
M, value.
, , M, ,
M .
, ,
dynamic,
System.Object System.Runtime.CompilerServices.
DynamicAttribute , .
,
Object, DynamicAttribute - , . - ,
dynamic Object , ,
dynamic Object.
dynamic ( ), ( ), , . , dynamic
Object DynamicAttribute ,
. , , ,
Object,
,
.
dynamic, , Object1.
Object , .
dynamic .
Object o1 = 123; // OK: Int32 Object ()
Int32 n1 = o1; // : Object Int32
Int32 n2 = (Int32) o1; // OK: Object Int32 ()
dynamic d1 = 123; // OK: Int32 dynamic ()
Int32 n3 = d; // OK: dynamic Int32 ()

, .

180

5. ,


, CLR . , CLR InvalidCastException.
:
dynamic d = 123;
var result = M(d); // 'var result' - , 'dynamic result'

, , M . ,
, M. , result . ,
var Visual Studio
IntelliSense- .
dynamic: Represents an object whose operations will be resolved at runtime.

M, , void, Microsoft.CSharp.RuntimeBinder.RuntimeBinderException.

dynamic var. var


. var
, dynamic
, .
var, dynamic.
, var, ,
dynamic, . var
9.

dynamic ,
, . dynamic
, :
dynamic d = 123;
var x = (Int32) d; // : 'var x' 'Int32 x'
var dt = new DateTime(d); // : 'var dt' 'DateTime dt'

dynamic foreach
using, , System.IEnumerable
System.IDisposable . , , .
Microsoft.CSharp.RuntimeBinder.
RuntimeBinderException.

dynamic

181

dynamic , System.Object. ,
. ,
. Visual
Studio - IntelliSense-
.
dynamic ( 8), Object.
- ( 17) ,
.

C# COM- IDispatch
Microsoft Office Excel A1.
using Microsoft.Office.Interop.Excel;
...
public static void Main() {
Application excel = new Application();
excel.Visible = true;
excel.Workbooks.Add(Type.Missing);
((Range)excel.Cells[1, 1]).Value = "Text in cell A1";
// A1.
}

dynamic , excel.Cells[1, 1], Object,


Range
Value. COM-
VARIANT COM dynamic.
, excel.Cells[1,1] dynamic,
Range
Value. dynamic ,
COM-. :
using Microsoft.Office.Interop.Excel;
...
public static void Main() {
Application excel = new Application();
excel.Visible = true;
excel.Workbooks.Add(Type.Missing);
excel.Cells[1, 1].Value = "Text in cell A1";
// A1
}

, (Contains) String ("ff") ("Jeffrey Richter")


Int32 result.
Object target = "Jeffrey Richter";
Object arg = "ff";

182

5. ,

// ,
Type[] argTypes = newType[] { arg.GetType() };
MethodInfo method = target.GetType().GetMethod("Contains", argTypes);
//
Object[] arguments = newObject[] { arg };
Boolean result = Convert.ToBoolean(method.Invoke(target, arguments));

C# dynamic,
.
dynamic target = "Jeffrey Richter";
dynamic arg = "ff";
Boolean result = target.Contains(arg);

, C# ,
. ,
(runtime binder). , .
C# Microsoft.CSharp.dll,
,
dynamic. , CSC.rsp.
, + Int32 ,
String .
Microsoft.CSharp.dll ,
. , Microsoft.SCharp.dll System.dll
System.Core.dll. dynamic COM-,
System.Dynamic.dll.
, ,
, (Anonymously Hosted
Dynamic Methods Assembly).
,
(call site) , .
- , C#, ,
:
.
, : ( ), ( COM-).
#
. ,

dynamic

183

IDynamicMetObjectProvider. , GetMetaObject, ,
DynamicMetaObject. ,
, . IDynamicMetaObjectProvider
DynamicMetaObject System.
Dynamic System.Core.dll.
, Python Ruby, ,
DynamicMetaObject, (, C#). C# COM DynamicMetaObject,
COM-. DynamicMetaObject
System.Dynamic.dll.
, ,
IDynamicMetaObjectProvider, C#
C#
.
,
, .
,
. StaticMemberDynamicWrapper,
System.Dynamic.DynamicObject,
IDynamicMetaObjectProvider.
(. 23). StaticMemberDynamicWrapper.
internal sealed class StaticMemberDynamicWrapper : DynamicObject {
private readonly TypeInfo m_type;
public StaticMemberDynamicWrapper(Type type) { m_type = type.GetTypeInfo(); }
public override IEnumerable<String> GetDynamicMemberNames() {
return m_type.DeclaredMembers.Select(mi => mi.Name);
}
public override Boolean TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
var field = FindField(binder.Name);
if (field != null) { result = field.GetValue(null); return true; }
var prop = FindProperty(binder.Name, true);
if (prop != null) { result = prop.GetValue(null, null); return true; }
return false;
}
public override Boolean TrySetMember(SetMemberBinder binder, object value) {
var field = FindField(binder.Name);

184

5. ,
if (field != null) { field.SetValue(null, value); return true; }

var prop = FindProperty(binder.Name, false);


if (prop != null) { prop.SetValue(null, value, null); return true; }
return false;
}
public override Boolean TryInvokeMember(InvokeMemberBinder binder, Object[]
args,
out Object result) {
MethodInfo method = FindMethod(binder.Name);
if (method == null) { result = null; return false; }
result = method.Invoke(null, args);
return true;
}
private MethodInfo FindMethod(String name, Type[] paramTypes) {
return m_type.DeclaredMethods.FirstOrDefault(mi => mi.IsPublic &&
mi.IsStatic
&& mi.Name == name
&& ParametersMatch(mi.GetParameters(), paramTypes));
}
private Boolean ParametersMatch(ParameterInfo[] parameters, Type[]
paramTypes) {
if (parameters.Length != paramTypes.Length) return false;
for (Int32 i = 0; i < parameters.Length; i++)
if (parameters[i].ParameterType != paramTypes[i]) return false;
return true;
}
private FieldInfo FindField(String name) {
return m_type.DeclaredFields.FirstOrDefault(fi => fi.IsPublic && fi.IsStatic
&& fi.Name == name);
}
private PropertyInfo FindProperty(String name, Boolean get) {
if (get)
return m_type.DeclaredProperties.FirstOrDefault(
pi => pi.Name == name && pi.GetMethod != null &&
pi.GetMethod.IsPublic && pi.GetMethod.IsStatic);

return m_type.DeclaredProperties.FirstOrDefault(
pi => pi.Name == name && pi.SetMethod != null &&
pi.SetMethod.IsPublic && pi.SetMethod.IsStatic);

,
Type .
-

dynamic

185

. Concat(String,

String) String:

dynamic stringType = new StaticMemberDynamicWrapper(typeof(String));


var r = stringType.Concat("A", "B"); //
// Concat String
Console.WriteLine(r); // "AB"

6.

4 5 , . , ,
. ,
,
. 7 11 .


.
, .
, ,
. ,
,
. .7.
,
/.
. ()
.
,
. .7.
, . .8.
,
. .8.
, , ( )
( ).
. .8.
,
.

187

CLS,
. .8.
,
.
CLS , . .8.
,
( )
. (
) ( , ).
.10.
.
() .
, . ,
() .
, -
. .11.
. ,
.
,
, .
, IL- .

CLR .
, ,
.
CLR , , , ,
. ,
Microsoft .NET Framework;
, .
C#
. ( ),

188

6.

,
. , .
using System;
public sealed class SomeType {

// 1

//
private class SomeNestedType { }

// 2

// ,
//Constant,read
only,andstaticread/writefield
privateconst
Int32 c_SomeConstant =1
;
privatereadonlyStringm_SomeReadOnlyField ="2";
privatestatic
Int32 s_SomeReadWriteField=3;

// 3
// 4
// 5

//
static SomeType() { }

// 6

//
public SomeType(Int32 x) { }
public SomeType() { }

// 7
// 8

//
private String InstanceMethod() { return null; }
public static void Main() {}

// 9
// 10

//
public Int32 SomeProp {
get { return 0; }
set { }
}

// 11
// 12
// 13

//
public Int32 this[String s] {
get { return 0; }
set { }
}

// 14
// 15
// 16

//
public event EventHandler SomeEvent;
}

// 17

ILDasm.exe (.6.1).

, .
, , (17), ( ) .
, ,
,
, .

189

. 6.1. , ILDasm.exe.


,
(public) (internal).
. ,
. C# ( ). .
using System;
//
public class ThisIsAPublicType { ... }
//
internal class ThisIsAnInternalType { ... }
// ,
class ThisIsAlsoAnInternalType { ... }


: ,
, , .
, ,
, , ;
.

190

6.

,
. ,
.
, ,
. , , ,
. ,
,
. CLR C#
(friend assemblies). , , ,
.
,
, InternalsVisibleTo, System.Runtime.CompilerServices.
,
( , ). ,
,
. ,
Wintellect Microsoft:
using System;
using System.Runtime.CompilerServices; // InternalsVisibleTo
//
// ( )
[assembly:InternalsVisibleTo("Wintellect, PublicKey=12345678...90abcdef")]
[assembly:InternalsVisibleTo("Microsoft, PublicKey=b77a5c56...1934e089")]
internal sealed class SomeInternalType { ... }
internal sealed class AnotherInternalType { ... }


. , Wintellect 1234567890abcdef SomeInternalType
:
using System;
internal sealed class Foo {
private static Object SomeMethod() {
// Wintellect
// ,
SomeInternalType sit = new SomeInternalType();
return sit;
}
}

191

, , ,
. , (
InternalsVisibleTo) C# /out:. , , .
, C#
, ;
.

.
, ( )
/t:module, ,
/moduleassemblyname: C#.
, ,
.


( )
. ,
. CLR ,
. , Assembly CLR , ,
C# internal.
. 6.1 ,
(Private) (Public).
6.1.
CLR

C#

Private ()

private

Family ()

protected


( )

Family and
Assembly (
)

( )


( )

192

6.

6.1 ()
CLR

C#

Assembly ()

internal

Assembly or Family
(
)

protected
internal

, ( )

Public ()

public

,
. , ,
, B ,
B.
. -
, . , JIT-
IL- . , , , JIT-
FieldAccessException MethodAccessException .
IL- ,
. , , ( );
,
(protected) (private), .
, C# ( ) . CLR ,
. C#

, .

C# ,
, C#
, Declared Accessibility C#.

193

, . 6.1, CLR
. C#
C#.
, C#
, . ,
. C#,
CLR. CLR , . ,
, .
,
. CLR
,
.


, ,
Console, Math, Environment ThreadPool.
. , . , Math ,
. C#
static. , (
), CLR ,
.
.
System.Object
,
, .
, .
(, ,
). .
,
, , , .
, .
, ;
.

194

6.

using System;
public static class AStaticClass {
public static void AStaticMethodQ { }
public static String AStaticProperty {
get { return s_AStaticField; }
set { s_AStaticField = value; }
}
private static String s_AStaticField;
}

public static event EventHandler AStaticEvent;

.6.2

ILDasm.exe (DLL) , -

. , static
C# (abstract) (sealed). ,
(.ctor).

. 6.2. ILDasm.exe

partial C#, ,
.

195

; CLR . ,
.
. ,
.
, -
, . partial ,
.
.
.
.
, , , .. ,
.

(
).
. Microsoft Visual Studio
Windows Forms Web Forms
. . Visual Studio
.
. ,
.
. Visual Studio 2005, Visual Studio
: , , .
.
partial
. , exe dll (
netmodule). ,
C#;
.

196

6.

,
- ()
. 70- 80- -
,
. , ,
,
.
, , , - (, ,
), ..

. ,
. ,
.
.
(Component Software Programming,
CSP) . .
( .NET) .
, ,
.
(
.NET
).
( ).
. C#
XML-
/doc .
. CLR
(Code Access Security, CAS).
( )
. (servicing)
, .
,

197

.
.
,
. ,
.
,
, .
.NET : (major) (minor) , (build)
(revision). , 1.2.3.4 1, 2, 3 4.
,
.
, 2.7.0.0. , ,
, 2.7.1.34.

(2.7.0.0).
, , , ,
/ (,3.0.0.0).

, . , CLR
. 1.2.3.4
, CLR 1.2.3.4 (
).


CLR (
C#), , .
, ,
(),
(). ,
. ,
.
C# / , , CLR. . 6.2 C#,
, .

198

6.

6.2. C# .

C#

//

abstract

()

virtual

()

()

override

()

()

sealed


.
,

()

new

, , , ,
, ,


,
CLR.

, CLR
, , , ,
.
, ( ) ().
, , (void).
,
.
,
. (
IL) , ,

199

. , C#
(.8).
Employee .
internal class Employee {
//
public Int32 GetYearsEmployed { ... }
// ( - , )
public virtual String GetProgressReport { ... }
//
public static Employee Lookup(String name) { ... }
}

. , ,
, .
, ,
, , IL-
. CLR :
call , .
, , .
,
, call ,
null . , ,
. ,
. call
.
callvirt ( ) . , .
, ,
. callvirt
CLR ,
, .
JIT-
null, CLR NullReferenceException.
- callvirt , call. null
.
, C#.

200

6.

using System;
public sealed class Program {
public static void Main() {
Console.WriteLine(); //
Object o = new Object();
o.GetHashCode(); //
o.GetType(); //
}
}

IL- .
.method public hidebysig static void Main() cil managed {
.entrypoint
// Code size 26 (0x1a)
.maxstack 1
.locals init (object o)
IL_0000: call void System.Console::WriteLine()
IL_0005: newobj instance void System.Object::.ctor()
IL_000a: stloc.0
IL_000b: ldloc.0
IL_000c: callvirt instance int32 System.Object::GetHashCode()
IL_0011: pop
IL_0012: ldloc.0
IL_0013: callvirt instance class System.Type System.Object::GetType()
IL_0018: pop
IL_0019: ret
} // end of method Program::Main

WriteLine , C#
call. GetHashCode
callvirt. , GetType
callvirt. , GetType
. , JIT
CLR , GetType , .
, : C#
call? C# , JIT- ,
, null . ,
, C# NullReferenceException,
.
using System;
public sealed class Program {
public Int32 GetFive() { return 5; }
public static void Main() {
Program p = null;
Int32 x = p.GetFive(); // C# NullReferenceException
}
}

201

. p null,
GetFive CLR p,
Program. GetFive this null, GetFive
, . C# call callvirt,
NullReferenceException.

,
. ,
call callvirt.
,
, .
, , C#, , C#
callvirt.
, .

callvirt
call. ,
, .
internal class SomeClass {
// ToString - Object
public override String ToString() {
// call
// ToString Object
// call callvirt,
//
return base.ToString();
}
}

base.ToString C#
call, ToString .
, ToString ,
, , .
call , , .
, .
, ,
null, NullReferenceException . ,
CLR
,
, .
, .

202

6.


call callvirt
this, , .

. -, . -, JIT- (inline)
, . -, ,
. -,
.
,
, . ,
,
. :
public class Set {
private Int32 m_length = 0;
//
public Int32 Find(Object value) {
return Find(value, 0, m_length);
}
//
public Int32 Find(Object value, Int32 startIndex) {
returnFind(value,startIndex,m_length startIndex);
}
//
//
public virtual Int32 Find(Object value, Int32 startIndex, Int32 endIndex) {
// , ...
}
//
}



.NET Framework ,
, .
.
( ,
), . , -
.
, ,

203

. ,
.
, .
, ,
.

. ( C#) , ,
sealed.
, , , ,
, .
.
. ,
, . , .
,
,
, .
. ,
, CLR
, , . , , JIT-
, .
,
. , JIT- ToString :
using System;
public sealed class Point {
private Int32 m_x, m_y;
public Point(Int32 x, Int32 y) { m_x = x; m_y = y; }
public override String ToStringO {
return String.Format("({0}, {1})", m_x, m_y);
}
public static void Main() {
Point p = new Point(3, 4);
// C# callvirt,
// JIT-
// ToString,
// p Point,
Console.WriteLine(p.ToString());
}
}

204

6.

.
. ,
,
, . , . ,
,
, .
,
.
,
. . CLR
,

C# (. 8),
ConditionalWeakTable (. 21).
, :
,
. , C#
.
, . ,
C#. ,
, ,
, .
,
. , C# . ,
, C# ,
protected, internal, public .. .

. (internal)
,
, .
, . , C# . ,
, ,
, , . ,

205

- ,
.
: .
, ,
. , .
.
, FxCopCmd.
exe Visual Studio
( ),

. , .



, . 3 (
, , ).
. ,
.
.
Company Phone:
namespace CompanyA {
public class Phone {
public void Dial() {
Console.WriteLine("Phone.Dial");
//
}
}
}

, CompanyB ,
BetterPhone, Phone :
namespace CompanyB {
public class BetterPhone : CompanyA.Phone {
public void Dial() {
Console.WriteLine("BetterPhone.Dial");
EstablishConnection();

206

6.

base.Dial();

protected virtual void EstablishConnection() {


Console.WriteLine("BetterPhone.EstablishConnection");
//
}
}
}

CompanyB C# :
warning CS0108: 'CompanyB.BetterPhone.Dial()' hides inherited member
'CompanyA.Phone.Dial()'. Use the new keyword if hiding
was intended.

, Dial, BetterPhone, Phone. Dial


, , Company .

. ,
: new
Dial BetterPhone.
BetterPhone:
namespace CompanyB {
public class BetterPhone : CompanyA.Phone {
// Dial Phone
public new void Dial() {
Console.WriteLine("BetterPhone.Dial");
EstablishConnection();
base.Dial();
}
protected virtual void EstablishConnection() {
Console.WriteLine("BetterPhone.EstablishConnection");
//
}
}
}

CompanyB
BetterPhone :
public sealed class Program {
public static void Main() {
CompanyB.BetterPhone phone = new CompanyB.BetterPhone();
phone.Dial();
}
}

207

:
BetterPhone.Dial
BetterPhone.EstablishConnection
Phone.Dial

, , CompanyB. Dial
, BetterPhone.
EstablishConnection, Dial
Phone.
, Phone,
Company. ,
Dial.
Company Phone:
namespace CompanyA {
public class Phone {
public void Dial() {
Console.WriteLine("Phone.Dial");
EstablishConnection();
//
}
protected virtual void EstablishConnection() {
Console.WriteLine("Phone.EstablishConnection");
//
}
}
}

CompanyB
BetterPhone ( Phone)
:
warning CS0114: 'BetterPhone.EstablishConnection()' hides inherited member
'Phone.EstablishConnection()'. To make the current member override
that implementation, add the override keyword. Otherwise,
add the new keyword

, 'BetterPhone. EstablishConnection()'
'Phone.EstablishConnection()',
, override;
new.
, Phone, BetterPhone EstablishConnection,
. BetterPhone
, , , Phone.

208

6.

CompanyB , EstablishConnection
, ,
Dial EstablishConnection, BetterPhone,
Phone.
CompanyB new
EstablishConnection:
namespace CompanyB {
public class BetterPhone : CompanyA.Phone {
// 'new' , ,
// Dial
public new void Dial() {
Console.WriteLine("BetterPhone.Dial");
EstablishConnection();
base.Dial();
}
// 'new' ,
// EstablishConnection
protected new virtual void EstablishConnection() {
Console.WriteLine("BetterPhone.EstablishConnection");
//
}
}
}

new , CLR, BetterPhone Dial


EstablishConnection ,
. CLR , Phone
BetterPhone .
( Main) :
BetterPhone.Dial
BetterPhone.EstablishConnection
Phone.Dial
Phone.EstablishConnection

, , Main Dial , , BetterPhone . Dial EstablishConnection , BetterPhone .


EstablishConnection BetterPhone ,
Dial Phone, EstablishConnection .
EstablishConnection BetterPhone
new ,
EstablishConnection, Phone.
Dial Phone EstablishConnection,
Phone, .

209

( ++),
BetterPhone Dial
EstablishConnection. , ,
.
, .
,
, Dial EstablishConnection,
, .

: CompanyB, Company
Phone, , Dial EstablishConnection
Phone , . CompanyB
Dial BetterPhone. CompanyB
, EstablishConnection BetterPhone
Phone,
new. ,
EstablishConnection BetterPhone.
, CompanyB BetterPhone EstablishConnection virtual override.
BetterPhone :
namespace CompanyB {
public class BetterPhone : CompanyA.Phone {
// Dial ( )
// new , virtual
// override, ,
// EstablishConnection
protected override void EstablishConnection() {
Console.WriteLine("BetterPhone.EstablishConnection");
//
}
}
}

( Main) :
Phone.Dial
BetterPhone.EstablishConnection

, Main Dial, ,
Phone BetterPhone. ,
Dial , Phone ,
EstablishConnection , BetterPhone,
EstablishConnection,
Phone.

7.

, , . ,
.

(constant) , . , ,
.
. , ,
. C#
: Boolean, Char,
Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal
String. C# , , null:
using System;
public sealed class SomeType {
// , #
// null
public const SomeType Empty = null;
}

,
. , , .
.
, , ,
IL-.
, . ,
. , ,
, ,
( MaxInt16
32767). , .
DLL-:

211

using System;
public sealed class SomeLibraryType {
// : C#
// static, ,
//
public const Int32 MaxEntriesInList = 50;
}

:
using System;
public sealed class Program {
public static void Main() {
Console.WriteLine("Max entries supported in list: "
+ SomeLibraryType.MaxEntriesInList);
}
}

MaxEntriesInList . , ,
MaxEntriesInList 50, 50
Int32 IL- . -

DLL- ,
.
.method public hidebysig static void Main() cil managed
{
.entrypoint
// Code size 25 (0x19)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "Max entries supported in list: "
IL_0006: ldc.i4.s 50
IL_0008: box [mscorlib]System.Int32
IL_000d: call string [mscorlib]System.String::Concat(object, object)
IL_0012: call void [mscorlib]System.Console::WriteLine(string)
IL_0017: nop
IL_0018: ret
} // Program::Main


. MaxEntriesInList
1000 DLL-, . ,
.
( ),
, .
,
.

212

7.

(field) ,
. .7.1 ,
.
7.1.
CLR

C#

Static

static

Instance

( )

InitOnly

readonly

Volatile

volatile

, ,
, CLR . (volatile)
: , Single, Boolean, Byte, SByte, Int16, UInt16,
Int32, UInt32, Char, ,
Byte, SByte, Int16, UInt16, Int32
UInt32. 2

, (CLR)
(), ().
,
(.22),
JIT- , .

.
,
. ,
. ,
,
(
).
CLR , (),
, ().
. ,
.
( ). ,

213

, , ,
. ,
.

, .
DLL-:
using System;
public sealed class SomeLibraryType {
// static ,
// ,
public static readonly Int32 MaxEntriesInList = 50;
}

, ,
, ,
. Main CLR DLL- ( )
MaxEntriesInList ,
. , 50.
, 50 1000 .
1000.
, , (
). ,
, CLR
.
, ,
:
public sealed class SomeType {
// .
//
public static readonly Random s_random = new Random();
//
private static Int32 s_numberOfWrites = 0;
//
public readonly String Pathname = "Untitled";
//
private System.IO.FileStream m_fs;
public SomeType(String pathname) {
//
// ,
//

214

7.
this.Pathname = pathname;

public String DoSomething() {


//
s_numberOfWrites = s_numberOfWrites + 1;
//
return Pathname;
}
}

(inline). C# ,
. 8, C# ,
.
, C# ,
,
. 8.

,
, , , :
public sealed class {
// InvalidChars
public static readonly Char[] InvalidChars = new Char[] { '', '', 'C'};
}
public sealed class AnotherType {
public static void M() {
// ,
// InvalidChars
.InvalidChars[0] = 'X';
.InvalidChars[1] = 'Y';
.InvalidChars[2] = 'Z';
// ,
// InvalidChars
.InvalidChars = new Char[] { 'X', 'Y', 'Z' };
}
}

8.

,
, , . , ,
- ( ),
( ). ,
, ,
.


( )
, . , ,
- .ctor ( constructor).
( -
), ,
.

. , , 0 null.
.
, ,
. , virtual, new, override, sealed abstract.
, (
C#) ( ), .
, :
public class SomeType { }

:
public class SomeType {
public SomeType() : base() { }
}

216

8.

protected,
(public). ,
,
. ( )
.
,
.

- .
, C#,
, , , .
System.Object
.
, System.Object
, .
. , MemberwiseClone Object
, , , . ,
. ,
GetUninitializedObject GetSafeUninitializedObject System.Runtime.
Serialization.FormatterServices (.24).

- ,
. :
, , ,
.
.

C# ,
:
internal sealed class SomeType {
private Int32 m_x = 5;
}

SomeType m_x 5.
: ? IL- -
( .ctor), :

( )

217

.method public hidebysig specialname rtspecialname


instance void .ctor() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld int32 SomeType::m_x
IL_0007: ldarg.0
IL_0008: call instance void [mscorlib]System.Object::.ctor()
IL_000d: ret
} // end of method SomeType::.ctor

, SomeType ,
m_x 5 . , -

C# ,
. , . ,
, :
internal sealed class SomeType {
private Int32 m_x = 5;
private String m_s = "Hi there";
private Double m_d = 3.14159;
private Byte m_b;
//
public
public
public
}

SomeType()
{ ... }
SomeType(Int32 x) { ... }
SomeType(String s) { ...; m_d = 10; }

IL- - ,
, m_x, m_s m_d.
, , -. ,
IL-, String,
, m_x, m_s m_d, , m_d
10. : m_b 0,
, .



, , . ,
, ,
.
.

218

8.

, , m_x, m_s m_d:


.
-,
, ;
, , , .
.
C#
this:
internal sealed class SomeType {
// ,
private Int32 m_x;
private String m_s;
private Double m_d;
private Byte m_b;
//
//
public SomeType() {
m_x = 5;
m_s = "Hi there";
m_d = 3.14159;
m_b = 0xff;
}
// ,
// m_x
public SomeType(Int32 x) : this() {
m_x = x;
}
// ,
// m_s
public SomeType(String s) : this() {
m_s = s;
}
// ,
// m_x m_s
public SomeType(Int32 x, String s) : this() {
m_x = x;
m_s = s;
}
}

( )

219


( )
(struct) , (class).
CLR
. , ,
. ( C#) , .
:
internal
public
}
internal
public
}

struct Point {
Int32 m_x, m_y;
sealed class Rectangle {
Point m_topLeft, m_bottomRight;

Rectangle , new
. ,
C#. , Rectangle,
Point. CLR
, . ,
, /null.
, CLR
, ,
, , Rectangle:
internal struct Point {
public Int32 m_x, m_y;
public Point(Int32 x, Int32 y) {
m_x = x;
m_y = y;
}
}
internal sealed class Rectangle {
public Point m_topLeft, m_bottomRight;
public Rectangle() {
// C# new,
// ,
m_topLeft = new Point(1, 2);
m_bottomRight = new Point(100, 200);
}
}

220

8.

. Rectangle
m_topLeft m_bottomRight new Point,
m_x m_y Point 0.
Point , ,
. :
internal struct Point {
public Int32 m_x, m_y;

public Point() {
m_x = m_y = 5;
}

internal sealed class Rectangle {


public Point m_topLeft, m_bottomRight;

public Rectangle() {
}

, 0 5
m_x m_y, Point (m_topLeft m_bottomRight)?
, .
( ++) ,
C# Rectangle ,
Point , ,
Rectangle. ,
, C# .


.
, .
, m_x m_y Point
Rectangle , Point.
, . ,
C# .
. C# ( CS0568:
):
error CS0568: Structs cannot contain explicit parameterless constructors

C# , ,
. ,

( )

221

, .
/null.

0 null,
. , ,
, 0 null, .
, ,
, .
, - , . C# ,
, , , ,
.
.
, , .

C#
, CLR.
, (, IL)
.
C# ,
: ( CS0573: 'SomeValType.m_x':
):
error CS0573: 'SomeValType.m_x': cannot have instance field initializers in structs

, :
internal struct SomeValType {
//
private Int32 m_x = 5;
}

, - , ,
, .
, :
internal struct SomeValType {
private Int32 m_x, m_y;
// C#
public SomeValType(Int32 x) {
m_x = x;

222

8.

// : m_y
}
}

C# :
( CS0171: 'SomeValType.m_y'
):
error CS0171: Field 'SomeValType.m_y' must be fully assigned before control leaves
the constructor

, y -
(0).
, :
// C#
public SomeValType(Int32 x) {
// , ,
// 0 null
this = new SomeValType();
m_x = x; // m_x x
// , m_y
}

this
,
.
this .


, CLR ( , ). ( C#
), . ,
,
. .
; ,
.
C#:
internal sealed class SomeRefType {
static SomeRefType() {
// SomeRefType
}

223

}
internal struct SomeValType {
// C#
//
static SomeValType() {
// SomeValType
}
}

, , ,
. , (C#
).
( - ), C#
: ( CS0515: 'SomeValType.Some-ValType()':
):
error CS0515: 'SomeValType.SomeValType()': access modifiers are not allowed on
static constructors

,
, , CLR
.

,
, CLR .
:
internal struct SomeValType {
static SomeValTypeQ {
Console.WriteLine("This never gets displayed");
}
public Int32 m_x;
}
public sealed class Program {
public static void Main() {
SomeValType[] a = new SomeValType[10];
a[0].m_x = 123;
Console.WriteLine(a[0].m_x); // 123
}
}

.
JIT- , .
- , JIT- ,
. , JIT-

224

8.

IL- . , JIT- , ,
.
, JIT- , , .
, . CLR
,
.
. ,
, , .
.
,
. ,
. , -
CLR , ,
.

CLR ,
, ,
- (singleton), .

,
, . , ClassA , ClassB,
, ClassA. CLR ,
,
ClassA
ClassB. . ,
CLR, ,
.
, , CLR
.
System.TypeInitializationException.
;
, .
, C# :
internal sealed class SomeType {
private static Int32 s_x = 5;
}

225

C#
, . ,
class struct, , .


SomeType. , ,
:
internal sealed class SomeType {
private static Int32 s_x;
static SomeType() { s_x = 5; }
}

ILDasm.exe ,
. IL- .
, , - .cctor ( class constructor).
IL- , .cctor
. ,
s_x 5.
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldc.i4.5
IL_0001: stsfld int32 SomeType::s_x
IL_0006: ret
} // end of method SomeType::.cctor

.
,
.

, Java, ,
, . , , , .
CLR ,
RunClassConstructor,
System.Runtime.CompilerServices.RuntimeHelpers. , ,
, .
RunClassConstructor CLR ,
, , .

226

8.

:
internal sealed class SomeType {
private static Int32 s_x = 5;

static SomeTypeQ {
s_x = 10;
}

C# - ,
s_x 5, 10.
, IL- C#
, ,
, - .

:
? -, ,
. , , ,
, .
,
Finalize, . , CLR
Finalize. : ,
DomainUnload System.AppDomain.


,
. , (, System.String, System.
Decimal System.DateTime) (==)
(!=). CLR
, . ,
, , .
, C# +, , .
+ , C# ,
. C# !=, Visual Basic <>. , ^ C#
(XOR), Visual Basic .
CLR , , ,

227

.
, , ,
. CLR
.

, ,
. CLR , .
C# ( ) , ,
, , . ,
C#
.
, C#:
public sealed class Complex {
public static Complex operator+(Complex c1, Complex c2) { ... }
}

op_Addition specialname, ,
. ( C#)
+, . , op_Addition
specialname, .
, , ,
.
. 8.1 8.2 , C#
,
, . .
8.1. # CLS- .

C#

CLS-

op_UnaryPlus

Plus

op_UnaryNegation

Negate

op_LogicalNot

Not

op_OnesComplement

OnesComplement

228

8.

8.1 ()
C#

CLS-

++

op_Increment

Increment

--

op_Decrement

Decrement

op_True

IsTrue { get; }

op_False

IsFalse { get; }

8.2. CLS-
C#

CLS-

op_Addition

Add

op_Subtraction

Subtract

op_Multiply

Multiply

op_Division

Divide

op_Modulus

Mod

&

op_BitwiseAnd

BitwiseAnd

op_BitwiseOr

BitwiseOr

op_ExclusiveOr

Xor

<<

op_LeftShift

LeftShift

>>

op_RightShift

RightShift

==

op_Equality

Equals

!=

op_Inequality

Equals

<

op_LessThan

Compare

>

op_GreaterThan

Compare

<=

op_LessThanOrEqual

Compare

>=

op_GreaterThanOrEqual

Compare

CLR , , C# . ,
. ECMA (www.ecma-international.org/
publications/standards/Ecma-335.htm) CLI,
10.3.1 ( ) 10.3.2 ( ).

229

.NET Framework (FCL)


Int32, Int64, UInt32 . ., , . , IL-,
. ,
,
. ,
,
IL. : , ,
- FCL,
.


,
. ; , , , , +
( ),
. , , op_
(, op_Addition) .
, +
, op_Addition.
, C# op_Addition, +,
. +, C# op_Addition
specialname, , op_Addition
. op_Addition
, , specialname ,
C# . ,
op_Addition, +
.

Microsoft,

, , , , . ,
,
specialname, ,
,
. , ,
,

230

8.

op_. , Microsoft
, ,
Microsoft .
Microsoft
, . , op_Addition op_AdditionAssignment
Add.

.8.1 8.2. , Complex
:
public sealed class Complex {
public static Complex operator+(Complex c1, Complex c2) { ... }
public static Complex Add(Complex c1, Complex c2) { return(c1 + c2); }
}

, , , , Add. Microsoft,
,
. , ,
, JIT-
. JIT-

.

,
Microsoft, System.
Decimal FCL.



. , Byte
Int32. ,
, .
, ,
CLR ( ). CLR ,
( ).

231

. , System.Xml.Linq.
XElement XML Boolean, (U)Int32, (U)Int64,
Single, Double, Decimal, String, DateTime, DateTimeOffset, TimeSpan, Guid
, null ( String).
, FCL Rational,
Int32 Single. ,
Rational Int32
Single.
Rational
, . ,
ToXxx, ( ToString).
, ,
Xxx. Rational:
public sealed class Rational {
// Rational Int32
public Rational(Int32 num) { ... }
// Rational Single
public Rational(Single num) { ... }
// Rational Int32
public Int32 ToInt32() { ... }
// Rational Single
public Single ToSingle() { ... }
}

, , ,
Int32 Single Rational . , ,
.
.
(, C#)
,
.
. CLR , . , C# (
) , , ,
,
. , C#
. Rational
:

232

8.

public sealed class Rational {


// Rational Int32
public Rational(Int32 num) { ... }
// Rational Single
public Rational(Single num) { ... }
// Rational Int32
public Int32 ToInt32() { ... }
// Rational Single
public Single ToSingle() { ... }
// Rational Int32
public static implicit operator Rational(Int32 num) {
return new Rational(num); }
// Rational Single
public static implicit operator Rational(Single num) {
return new Rational(num); }
// Int32, Rational
public static explicit operator Int32(Rational r) {
return r.ToInt32(); }
// Single, Rational
public static explicit operator Single(Rational r) {
return r.ToSingle();
}
}

,
. implicit
C#,
, .
explicit ,
.
implicit explicit ,
(
operator). operator ,
, .
Rational ,
( C#):
public sealed class Program {
public static void Main() {
Rational r1 = 5; // Int32 Rational
Rational r2 = 2.5F; // Single Rational
Int32 x = (Int32) r1; // Rational Int32
Single s = (Single) r2; // Rational Single
}
}

233

.
C# ( )
IL-,
, Rational.
? , Rational
. ,
. , Rational, :
public
public
public
public

static
static
static
static

Rational op_Implicit(Int32 num)


Rational op_Implicit(Single num)
Int32 op_Explicit(Rational r)
Single op_Explicit(Rational r)

, , , op_Implicit op_Explicit.
,
,
Int32 Rational. (, Rational Int32),
. , , OverflowException InvalidOperationException.

op_Explicit
Rational. : Int32 Single . ,
. CLR
, . . , , ,
C++, C#, Visual Basic Java ,
. (, IL)
, . , IL-
,
, . C# ,
,
.

C# . ,
, , , , .
,
IL- .

234

8.

,
. , .
,
, .

# ,
. , as is.

- , System.
Decimal . Decimal , Decimal . ToXxx Decimal
. ,
.


.
14 , StringBuilder
, String, ,
StringBuilder ,
. ,
StringBuilder . ,
IndexOf:
public static class StringBuilderExtensions {
public static Int32 IndexOf(StringBuilder sb, Char value) {
for (Int32 index = 0; index < sb.Length; index++)
if (sb[index] == value) return index;
return -1;
}
}

, :
//
StringBuilder sb = new StringBuilder("Hello. My name is Jeff.");
//
// (5)
Int32 index = StringBuilderExtensions.IndexOf(sb.Replace('.', '!'), '!');

235

, . -, , StringBuilder,
StringBuilderExtensions. -,
,
StringBuilder, , .
Replace,
IndexOf, ,
IndexOf, Replace.
, :
//
sb.Replace('.', '!');
// (5)
Int32 index = StringBuilderExtensions.IndexOf(sb, '!');

,
. StringBuilderExtensions
: IndexOf. StringBuilder
IndexOf,
:
//
// (5)
Int32 index = sb.Replace('.', '!').IndexOf('!');

!
StringBuilder ,
.
, .
,
. , IndexOf , , .
IndexOf ,
this :
public static class StringBuilderExtensions {
public static Int32 IndexOf(this StringBuilder sb, Char value) {
for (Int32 index = 0; index < sb.Length; index++)
if (sb[index] == value) return index;
return -1;
}
}

:
Int32 index = sb.IndexOf('X');

StringBuilder , IndexOf

236

8.

Char. ,
IndexOf,

, .
this. sb
StringBuilder. IndexOf : StringBuilder ( this) Char.
IndexOf IL- .
, , . ,
, ,
IndexOf StringBuilder?
Microsoft Visual Studio IntelliSense. ,
, IntelliSense- .
, IntelliSense- , , . IntelliSense-
.8.1. , ,
,
. ,

,
.

. 8.1. IntelliSense Visual Studio

237


, .
# ,
, , ..
( this )
.
, . ,
, , ,
this.
C# ,
, . ,
, ,
C# ( CS1109:
, StringBuilderExtensions
):
error CS1109: Extension method must be defined in a top-level static
class; StringBuilderExtensions is a nested class

,
# - , ; ,
, .
,
, C# .
, - StringBuilderExtensions Wintellect, ,
,
using Wintellect.

. ,
,
( CS0121:
'StringBuilderExtensions.IndexOf(string, char)' 'AnotherStringBuild
erExtensions.IndexOf(string, char)):
error CS0121: The call is ambiguous between the following methods
or properties: 'StringBuilderExtensions.IndexOf(string, char)'
and 'AnotherStringBuilderExtensions.IndexOf(string, char)'.

, .

238

8.

,
, , .
,
. , ,
. , ,
System.Object, ,
IntelliSense.
.
Microsoft IndexOf StringBuilder
, , , IndexOf
Microsoft IndexOf. -
-. ,
.


,
StringBuilder. ,
, CLR
, ( null).
// sb null
StringBuilder sb = null;
// : NullReferenceException
// IndexOf
// NullReferenceException IndexOf
sb.IndexOf('X');
// : NullReferenceException
// Replace
sb.Replace('.', '!');

,
, :
public static void ShowItems<T>(this IEnumerable<T> collection) {
foreach (var item in collection)
Console.WriteLine(item);
}


, , IEnumerable<T>:

239

public static void Main() {


//
"Grant".ShowItems();
//
new[] { "Jeff", "Kristin" }.ShowItems();
// Int32 .
new List<Int32>() { 1, 2, 3 }.ShowItems();
}

Microsoft Language Integrated Query (LINQ).


System.Linq.Enumerable
Microsoft .NET Framework SDK.
IEnumerable, IEnumerable<T>.

-, :
public static void InvokeAndCatch<TException>(this Action<Object> d, Object o)
where TException : Exception {
try { d(o); }
catch (TException) { }
}

:
Action<Object> action = o => Console.WriteLine(o.GetType());
// NullReferenceException
action.InvokeAndCatch<NullReferenceException>(null);
// NullReferenceException

, ( .15).
, # ,
(.17):
public static void Main () {
// C Action,
// ShowItems; "Jeff"
Action a = "Jeff".ShowItems;
.
.
.
// , ShowItems
// "Jeff"
a();
}

240

8.

# IL- ,
Action.
, ,
. ,
, , null, .
C# , ,
ShowItems,
"Jeff". , , CLR
"Jeff". - , , ,
.


, ,
#. ,
, , .
,
.
, .
#,
this, ,
.
System.Core.dll :
// System.Runtime.CompilerServices
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class
| AttributeTargets.
Assembly)]
public sealed class ExtensionAttribute : Attribute {
}

,
, , . , ,
, ,
.
, ,
, .

241

ExtensionAttribute System.Core.dll. , , , System.Core.dll, -


System.Core.dll
. , ExtensionAttribute , System.
Core.dll , - .


, , C# . ,
, .
, .
, , . ,
, ,
, . :
// :
internal class Base {
private String m_name;
// m_name
protected virtual void OnNameChanging(String value) {
}
public String Name {
get { return m_name; }
set {
//
OnNameChanging(value.ToUpper());
m_name = value; //
}
}
}
//
internal class Derived : Base {
protected override void OnNameChanging(string value) {
if (String.IsNullOrEmpty(value))
throw new ArgumentNullException("value");
}
}

242

8.

, .
(sealed) .
( ).
, .
. , , . OnNameChanging,
- ,
. ToUpper , OnNameChanging , ,
.
C#. ,
, :
//
internal sealed partial class Base {
private String m_name;
//
// m_name
partial void OnNameChanging(String value);
public String Name {
get { return m_name; }
set {
//
OnNameChanging(value.ToUpper());
m_name = value; //
}
}
}
// ,
internal sealed partial class Base {
// ,
// m_name
partial void OnNameChanging(String value) {
if (String.IsNullOrEmpty(value))
throw new ArgumentNullException("value");
}
}

, .
( ). ,
.

243

, , , ,
, ( .6).
, ,
. partial .
, , .
partial .
, , . ,
,
- .
, ,
.

Visual Studio, partial , IntelliSense


,
.
IntelliSense-, Visual Studio
. , .

. ,
, , . , IL- ,
:
// ,
//
internal sealed class Base {
private String m_name;
public String Name {
get { return m_name; }
set {
m_name = value; //
}
}
}


, . IL- ,
, , .

244

8.

ToUpper.
IL-
!

System.Diagnostics.
ConditionalAttribute. ,
ConditionalAttribute ,
.


, .

.
void
, out.
, ,
, ,
. ,
out, , . ,
ref, , , , unsafe.
,
. , ,
. , ,
.
,
, .
, .
( CS0762:
'Base.OnNameChanging(string)',
):
"error CS0762: Cannot create delegate from method
'Base.OnNameChanging(string)' because it is a partial method
without an implementing declaration

, C#
private .

9.
.
, ,
. ,
.

1
( )
.
, . ,
,
. , :
public static class Program {
private static Int32 s_n = 0;
private static void M(Int32 x = 9, String s = "A",
DateTime dt = default(DateTime), Guidguid = new Guid()) {
Console.WriteLine("x={0}, s={1}, dt={2}, guid={3}", x, s, dt, guid);
}
public static void Main() {
// 1. : M(9, "A", default(DateTime), new Guid());
M();
// 2. : M(8, "X", default(DateTime), new Guid());
M(8, "X");
// 3. : M(5, "A", DateTime.Now, Guid.NewGuid());
M(5, guid: Guid.NewGuid(), dt: DateTime.Now);
// 4. : M(0, "1", default(DateTime), new Guid());
M(s_n++, s_n++.ToString());
// 5. : String t1 = "2"; Int32 t2 = 3;
// M(t2, t1, default(DateTime), new Guid());
M(s: (s_n++).ToString(), x: s_n++);
}
}

:
x=9, s=A, dt=1/1/0001 12:00:00 AM, guid=00000000-0000-0000-0000-000000000000
x=8, s=X, dt=1/1/0001 12:00:00 AM, guid=00000000-0000-0000-0000-000000000000

msdn.microsoft.com , .
. . .
1

246

9.

x=5, s=A, dt=8/16/2012 10:14:25 PM, guid=d24a59da-6009-4aae-9295-839155811309


x=0, s=1, dt=1/1/0001 12:00:00 AM, guid=00000000-0000-0000-0000-000000000000
x=3, s=2, dt=1/1/0001 12:00:00 AM, guid=00000000-0000-0000-0000-000000000000

, ,
, .
M (named parameter). x , guid dt.
.
M s_n (0) x,
s_n s_n (1)
s. s_n 2.
.
M s_n (2) (t1). s_n 3,
(t2). s_n 4. ,
M, t2, t1, DateTime
Guid.


, ,
:
,
(C#). , . ,
.

. , ,
,
. , M
("A") s, .
,
params ( ). ,
. .
.

, .5.1 5. , null.

, .
default, new, -

247

IL-.
M dt
guid .
,
,
. , M dt dateTime, ( CS1739:
'M' 'dt'):
"error CS1739: The best overload for 'M' does not have a parameter
named 'dt'


.
.
, , .

0 null.
. :
// :
private static String MakePath(String filename = "Untitled") {
return String.Format(@"C:\{0}.txt", filename);
}
// :
private static String MakePath(String filename = null) {
// ,
// null (??); . 19
return String.Format(@"C:\{0}.txt", filename ?? "Untitled");
}

, ref out,
.

:
; .
,
, ,
(c ).
C# . ,
M(1,,DateTime.Now) , . ,
.
,
ref/out:

248

9.

// :
private static void M(ref Int32 x) { ... }
// :
Int32 a = 5;
M(x: ref a);

C#
, COM Microsoft Office.
COM- C# ref/out
. .
COM- ,
ref/out .

DefaultParameterValue

, C#. ,
, ,
,
. ,
,
.
C#
System.Runtime.InteropServices.OptionalAttribute,
. ,
System.Runtime.InteropServices.DefaultParameterValueAttribute,
.
DefaultParameterValueAttribute ,
.
, , ,
, ,
.

C# :

249

private static void ImplicitlyTypedLocalVariables() {


var name = "Jeff";
ShowVariableType(name); // : System.String
// var n = null; //
var x = (String)null; // ,
ShowVariableType(x); // : System.String
var numbers = new Int32[] { 1, 2, 3, 4 };
ShowVariableType(numbers); // : System.Int32[]
//
var collection = new Dictionary<String, Single>() { { "Grant", 4.0f } };
// : System.Collections.Generic.Dictionary`2[System.String,System.Single]
ShowVariableType(collection);
foreach (var item in collection) {
// : System.Collections.Generic.KeyValuePair`2
[System.String,System.Single]
ShowVariableType(item);
}
}
private static void ShowVariableType<T>(T t) {
Console.WriteLine(typeof(T));
}

ImplicitlyTypedLocalVariables var. ,

(=). "Jeff" , name
String. , , ShowVariableType.
. ShowVariableType ImplicitlyTypedLocalVariables.
() ImplicitlyType
dLocalVariables ( CS0815:
null
):
error CS0815: Cannot assign <null> to an implicitly-typed local variable

, null
, null. ,
. ,
null - ,
( String). , ,
, String x = null;, .

250

9.


. Dictionary<String, Single>.
,
,
.
foreach var ,
.
var foreach, using
for. , . ,
,
. .
, ,
! , , ,
,
.
Microsoft Visual Studio
var , . C#
, . 10.
var .
, ,
. , ,
. ,
. C# .
. C#
, ( ) .
, ( 10)
.

dynamic var. var ,


.
, dynamic , .
var,
dynamic. , var, , dynamic.
5.

251


CLR ,
. (
) . ,
.
, .
, .

, ,
.

CLR , . C#
out ref.
, .
,
.
CLR, out ref ,
IL-, ,
, .
C# , , .
out,
, .
,
. ref,
,
, .
out
ref . :
public sealed class Program {
public static void Main() {
Int32 x; // x
GetVal(out x); // x
Console.WriteLine(x); // 10
}
private static void GetVal(out Int32 v) {
v = 10; // V
}
}

252

9.

x Main, GetVal.
v Int32.
GetVal Int32, v,
10. , GetVal
. out
,
.
ref:
public sealed class Program {
public static void Main() {
Int32 x = 5; // x
AddVal(ref x); // x
Console.WriteLine(x); // 15
}
private static void AddVal(ref Int32 v) {
v += 10; // v
}
}

Main x 5. AddVal, v
Int32 Main. AddVal
Int32, v. , AddVal v
. ,
. AddVal
10. , , x
Main 15, .
, IL CLR out
ref : . ,
. , ref, ( CS0165:
x, ):
error CS0165: Use of unassigned local variable 'x'

, :
public sealed class Program {
public static void Main() {
Int32 x; // x
// , :
// error CS0165: Use of unassigned local variable 'x'
AddVal(ref x);
Console.WriteLine(x);
}
private static void AddVal(ref Int32 v) {

253

v += 10; // v
}
}

, C#
out ref. ,
, , ,
. C# ,
, ,
.
, CLR -
out ref. , C#
:
public sealed class Point {
static void Add(Point p) { ... }
static void Add(ref Point p) { ... }
}

, (out
ref), JIT- , . Point
:
static void Add(out Point p) { ... }

Point C# (
CS0663: 'Add' , ref out):
error CS0663: 'Add' cannot define overloaded methods that differ only
on ref and out

out ref ,
.
.
, .

, .
out ref , .
:
using System;
using System.IO;
public sealed class Program {
public static void Main() {
FileStream fs; // fs
//

254

9.
StartProcessingFiles(out fs);

// ,
for (; fs != null; ContinueProcessingFiles(ref fs)) {
//
fs.Read(...);
}
}
private static void StartProcessingFiles(out FileStream fs) {
fs = new FileStream(...); // fs
//
}
private static void ContinueProcessingFiles(ref FileStream fs) {
fs.Close(); //
// null,
if (noMoreFilesToProcess) fs = null;
else fs = new FileStream (...);
}
}

, ,
, out ref,
. ,
ContinueProcessingFiles ,
. ,
ref. :
using System;
using System.IO;
public sealed class Program {
public static void Main() {
FileStream fs = null; //
// null
//
ProcessFiles(ref fs);
// ,
for (; fs != null; ProcessFiles(ref fs)) {
//
fs.Read(...);
}
}
private static void ProcessFiles(ref FileStream fs) {
// ,

255

if (fs != null) fs.Close(); //


// null,
if (noMoreFilesToProcess) fs = null;
else fs = new FileStream (...);
}
}

, ref
, :
public static void Swap(ref Object a, ref Object b) {
Object t = b;
b = a;
a = t;
}

, , String, :
public static void SomeMethod() {
String s1 = "Jeffrey";
String s2 = "Richter";
Swap(ref s1, ref s2);
Console.WriteLine(s1); // "Richter"
Console.WriteLine(s2); // "Jeffrey"
}

: ,
, , .
, Swap Object,
String. :
public static void SomeMethod() {
String s1 = "Jeffrey";
String s2 = "Richter";
//
//
Object o1 = s1, o2 = s2;
Swap(ref o1, ref o2);
//
s1 = (String) o1;
s2 = (String) o2;
Console.WriteLine(s1); // "Richter"
Console.WriteLine(s2); // "Jeffrey"
}

SomeMethod
. , ,

256

9.

. ,
( , ):
internal sealed class SomeType {
public Int32 m_val;
}
public sealed class Program {
public static void Main() {
SomeType st;
// CS1503: Argument '1':
// cannot convert from 'ref SomeType' to 'ref object'.
GetAnObject(out st);
}

Console.WriteLine(st.m_val);

private static void GetAnObject(out Object o) {


o = new String('X', 100);
}
}

, Main GetAnObject
SomeType. GetAnObject Object,
GetAnObject o
. st , GetAnObject
Main, String, SomeType. , Console.WriteLine
. , C# , st
SomeType, GetAnObject
Object.
, , . Swap:
public static void Swap<T>(ref T a, ref T b) {
T t = b;
b = a;
a = t;
}

( )
:
public static void SomeMethod() {
String s1 = "Jeffrey";
String s2 = "Richter";
Swap(ref s1, ref s2);
Console.WriteLine(s1); // "Richter"
Console.WriteLine(s2); // "Jeffrey"
}

257

, ,
System.Threading.Interlocked CompareExchange Exchange.

,
. , System.String , , ,
.
, , :
static Int32 Add(params Int32[] values) {
// :
//

Int32 sum = 0;
if (values != null) {
for (Int32 x = 0; x < values.Length; x++)
sum += values[x];
}
return sum;

params,
. ,
, Int32,
.
, :
public static void Main() {
// "15"
Console.WriteLine(Add(new Int32[] { 1, 2, 3, 4, 5 } ));
}

,
Add. , .
, , Add :
public static void Main() {
// "15"
Console.WriteLine(Add(1, 2, 3, 4, 5));
}

params.

System.ParamArrayAttribute.

258

9.

, C# , ParamArray.
, , .
ParamArray ,
. ,
, , .
Add, Int32 .
Add, Int32, Add,
Int32 ParamArray.
, Int32 Add. ,
, Add , , Add,
.
params
(ParamArrayAttribute). .
null , . Add , ,
0 ( ):
public static void Main() {
// "0"
Console.WriteLine(Add()); //
Console.WriteLine(Add(null)); //
//
}
//

Int32[0] Add
Add null,
(
)

,
Int32. , ? :
, Int32[] Object[].
Type :
public sealed class Program {
public static void Main() {
DisplayTypes(new Object(), new Random(), "Jeff", 5);
}

private static void DisplayTypes(params Object[] objects) {


if (objects != null) {
foreach (Object o in objects)
Console.WriteLine(o.GetType());
}
}

259

:
System.Object
System.Random
System.String
System.Int32

, , , , , null.

,
. , ,
params. Concat
System.String, :
public sealed class String : Object,
public static string Concat(object
public static string Concat(object
public static string Concat(object
public static string Concat(params
public
public
public
str3);
public
}

... {
arg0);
arg0, object arg1);
arg0, object arg1, object arg2);
object[] args);

static string Concat(string str0, string str1);


static string Concat(string str0, string str1, string str2);
static string Concat(string str0, string str1, string str2, string
static string Concat(params string[] values);

, Concat , params . , , ,
.
params ,
. ,
.

,
, . , ,
, , IEnumerable<T> , List<T>,
ICollection<T> IList<T>:

260

9.

//
public void ManipulateItems<T>(IEnumerable<T> collection) { ... }
//
public void ManipulateItems<T>(List<T> collection) { ... }

, , , ,
, List<T>, String .., ,
IEnumerable<T>.
List<T>, String . ,
,
.
, , (
), IList<T>,
List<T> .
, IList<T>.
, , .
, . , ,
, , :
//
public void ProcessBytes(Stream someStream) { ... }
//
public void ProcessBytes(FileStream fileStream) { ... }

: FileStream,
NetworkStream, MemoryStream .. FileStream,

.
, ,
(
). , ,
FileStream, Stream:
//
//
public FileStream OpenFile() { ... }
//
//
public Stream OpenFile() { ... }

,
FileStream Stream.
,
Stream, .

, .
OpenFile , -

261

- FileStream ( ,
FileStream). , List<String>, , String[].
.
:
// :
//
public IList<String> GetStringCollection() { ... }
// :
//
public List<String> GetStringCollection() { ... }

GetStringCollection List<String>,
IList<String>.
String[], ,
. , . ,
IEnumerable<String> ICollection<String>.

, C++, .
, . CLR
, .
, ,
( C#).
, C++
const .
,

. C++
, ,
.
, ,
. , ,
String .
, Microsoft CLR . CLR
,

262

9.

, .
, . , .
,
. , , ,
, .
, CLR
/.

10.

. . CLR : , ,
. , C#
, Visual Basic .
,
,
System.Tuple.


,
. . ,
, :
public sealed class Employee {
public String Name; //
public Int32 Age; //
}

,
:
Employee e = new Employee();
e.Name = "Jeffrey Richter"; //
e.Age = 48; //
Console.WriteLine(e.Name); // "Jeffrey Richter"

. , .
-
. ,
,
,
. ,
Employee:
e.Age = -5; // , 5 ?

264

10.

. , , - , - ,
, .
, ,
, .
, -,
(private), -,
, . ,
, (accessor).
, ,
.
:
public sealed class Employee {
private String m_Name; //
private Int32 m_Age; //
public String GetName() {
return(m_Name);
}
public void SetName(String value) {
m_Name = value;
}
public Int32 GetAge() {
return(m_Age);
}
public void SetAge(Int32 value) {
if (value < 0)
throw new ArgumentOutOfRangeException("value", value.ToString(),
"The value must be greater than or equal to 0");
m_Age = value;
}
}

,
. , ,

.
SetXxx
(protected).
, : -, - , -,

:


e.SetName("Jeffrey Richter"); //
String EmployeeName = e.GetName(); //
e.SetAge(41); //
e.SetAge(-5); //
//
Int32 EmployeeAge = e.GetAge(); //

265





ArgumentOutOfRangeException

. CLR ,
.
, :
public sealed class Employee {
private String m_Name;
private Int32 m_Age;
public String Name {
get { return(m_Name); }
set { m_Name = value; } // value
} //
public Int32 Age {
get { return(m_Age); }
set {
if (value < 0) // value
//
throw new ArgumentOutOfRangeException("value", value.ToString(),
"The value must be greater than or equal to 0");
m_Age = value;
}
}
}

, , ,
:
e.Name = "Jeffrey Richter"; // ""
String EmployeeName = e.Name; // ""
e.Age = 41; // ""
e.Age = -5; //
// ArgumentOutOfRangeException
Int32 EmployeeAge = e.Age; // ""

,
. CLR , , . ,
(.6) (.13).
( void).
( , ).

266

10.

, : get set.
set, , ,
get, , .
get set ,
. (backing field).
get set . ,
System.Threading.Thread Priority,
, Thread ,
. , ,
, : , ,
, ..
:
get ,
get;
set ,
set;
.
Employee.
Name Age. get set,
Employee .
, :
public sealed class Employee {
private String m_Name;
private Int32 m_Age;
public String get_Name(){
return m_Name;
}
public void set_Name(String value) {
m_Name = value; // value
}
public Int32 get_Age() {
return m_Age;
}
public void set_Age(Int32 value) {
if (value < 0) { // value
throw new ArgumentOutOfRangeException("value", value.ToString(),
"The value must be greater than or equal to 0");
}
m_Age = value;
}
}

267

, get_ set_ , .
C#. ,
, .
,
. ,
.
, ,
,
. ,
get set.
, .
System.Reflection.PropertyInfo. CLR ,
.


, #
,
(Automatically Implemented Properties, AIP). Name:
public sealed class Employee {
//
public String Name { get; set; }
private Int32 m_Age;
public Int32 Age {
get { return(m_Age); }
set {
if (value < 0) // value
throw new ArgumentOutOfRangeException("value", value.ToString(),
"The value must be greater than or equal to 0");
m_Age = value;
}
}
}

set get,
C# .
String . get_Name set_Name
.
, ,
Name? . AIP , . ,
, get set.
, ,

268

10.

, , ,
. Name
, , , , .
,
.
, ,
. AIP .
, .
. AIP ,
, , ,
. ,
.
AIP- set get,
, .
, .
, AIP
, set get.
,
, , ,
. - ,
,
. ,
AIP. AIP .


, Microsoft
.NET Framework .
, , .
. , , ,
, .
,
, . ,
(get set).

269

, , , .

out ref, , :
using System;
public sealed class SomeType {
private static String Name {
get { return null; }
set {}
}
static void MethodWithOutParam(out String n) { n = null; }
public static void Main() {
//
// :
// error CS0206: A property or indexer may not
// be passed as an out or ref parameter.
MethodWithOutParam(out Name);
}
}

- ,
. ,
, . ,
(, System.MarshalByRefObject),
- , . , , MarshalByRefObject,
.
-
, . System.DateTime
Now, .
. ,
Microsoft , Now .
Environment.TickCount.
- ,
. ,
, .
-
, , -

270

10.

;
,
. , ,
, .
, ,
. , : ,
, . , ,
.
.NET Framework ,
,
GetXxx SetXxx.
,
, ,
!

Visual Studio
Microsoft Visual Studio
. get .
, .
, FileStream , ,
FileStream.Length .
get,

!
, get - ,
. , get
, .
- Visual Studio
, . ToolsOptions, Options
DebuggingGeneral Enable Property Evaluation And Other Implicit
Function Calls (.10.1). ,
, ,
Value Visual Studio.

271

. 10.1. Visual Studio


( ) . C# , :
Employee e = new Employee() { Name = "Jeff", Age = 45 };

Employee, , Name Jeff,


Age 45. (
, IL- ):
Employee e = new Employee();
e.Name = "Jeff";
e.Age = 45;

,
, ,
. , :
String s = new Employee() { Name = "Jeff", Age = 45 }.ToString().ToUpper();

Employee, ,
, ToString,

272

10.

ToUpper. # -

, .
, :
String s = new Employee { Name = "Jeff", Age = 45 }.ToString().ToUpper();

IEnumerable IEnumerable<T>,
, ( ). ,
:
public sealed class Classroom {
private List<String> m_students = new List<String>();
public List<String> Students { get { return m_students; } }
}

public Classroom() {}

Classroom Stu-

dents:

public static void M() {


Classroom classroom = new Classroom {
Students = { "Jeff", "Kristin", "Aidan", "Grant" }
};
// 4 ,
foreach (var student in classroom.Students)
Console.WriteLine(student);
}

, Students
List<String> IEnumerable<String>.
, List<String>
Add ( Add
). Add .
:
public static void M() {
Classroom classroom = new Classroom();
classroom.Students.Add("Jeff");
classroom.Students.Add("Kristin");
classroom.Students.Add("Aidan");
classroom.Students.Add("Grant");
// 4 ,
foreach (var student in classroom.Students)
Console.WriteLine(student);
}

273

IEnumerable IEnumerable<T>,
Add,
,
( CS0117: System.Collections.
Generic.IEnumerable<string> Add):
error CS0117: 'System.Collections.Generic.IEnumerable<string>' does not
contain adefinition for 'Add'

Add . ,
Add Dictionary:
public void Add(TKey key, TValue value);

Add , :
var table = new Dictionary<String, Int32> {
{ "Jeffrey", 1 }, { "Kristin", 2 }, { "Aidan", 3 }, { "Grant", 4 }
};

:
var table = new Dictionary<String, Int32>();
table.Add("Jeffrey", 1);
table.Add("Kristin", 2);
table.Add("Aidan", 3);
table.Add("Grant", 4);


#
. (tuple type)1 ,
, - .
(Name String Year Int32),
Name Jeff, Year 1964.
// ,
var o1 = new { Name = "Jeff", Year = 1964 };
//
Console.WriteLine("Name={0}, Year={1}", o1.Name, o1.Year); // :
// Name=Jeff, Year=1964

,
new, , , tuple : single, double, triple,
quadruple, quintuple, n-tuple.
1

274

10.

( ).
. , , , ,
o1.
, 9,
(=).
, , .
:
var o = new { property1 = expression1, ..., propertyN = expressionN };

, ,
, .
. ,
Equals, GetHashCode ToString
. , , :
[CompilerGenerated]
internal sealed class <>f__AnonymousType0<...>: Object {
private readonly t1 f1;
public t1 p1 { get { return f1; } }
...
private readonly tn fn;
public tn pn { get { return fn; } }
public <>f__AnonymousType0<...>(t1 a1, ..., tn an) {
f1 = a1; ...; fn = an; //
}
public override Boolean Equals(Object value) {
// false, - ;
// true
}
public override Int32 GetHashCode() {
// -, -
}
public override String ToString() {
// "name = value",
}
}

Equals GetHashCode, -. ,

275

, - .
- , -, . ToString
. Visual Studio
, , Visual Studio
ToString . ,
IntelliSense- Visual Studio .
,
:
String Name = "Grant";
DateTime dt = DateTime.Now;
//
// 1. Name Grant
// 2. Year Int32 Year dt
var o2 = new { Name, dt.Year };

, Name. Name ,
,
String. /:
Year. Year DateTime Int32, ,
Year Int32.
, Name , Name, Name
Grant. Year ,
dt Year.
. ,
,

. ,

. o1
o2 ,
Name/String Year/Int32, Name Year.
, , , ,
:
//
Console.WriteLine("Objects are equal: " + o1.Equals(o2));
o1 = o2; //

276

10.

,
( .16):
// ,
var people = new[] {
o1, // .
new { Name = "Kristin", Year = 1970 },
new { Name = "Aidan", Year = 2003 },
new { Name = "Grant", Year = 2008 }
};
//
// ( var ).
foreach (var person in people)
Console.WriteLine("Person={0}, Year={1}", person.Name, person.Year);


(Language Integrated Query, LINQ), , ,
.
. ,
:
String myDocuments =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var query =
from pathname in Directory.GetFiles(myDocuments)
let LastWriteTime = File.GetLastWriteTime(pathname)
where LastWriteTime > (DateTime.Now - TimeSpan.FromDays(7))
orderby LastWriteTime
select new { Path = pathname, LastWriteTime };
foreach (var file in query)
Console.WriteLine("LastWriteTime={0}, Path={1}",
file.LastWriteTime, file.Path);

. ,
.
. Object ( Object),
Object ,
.
System.Tuple,
.

System.Tuple
System
( Object), . .

277

// :
[Serializable]
public class Tuple<T1> {
private T1 m_Item1;
public Tuple(T1 item1) { m_Item1 = item1; }
public T1 Item1 { get { return m_Item1; } }
}
// :
[Serializable]
public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> {
private T1 m_Item1; private T2 m_Item2;
private T3 m_Item3; private T4 m_Item4;
private T5 m_Item5; private T6 m_Item6;
private T7 m_Item7; private TRestm_Rest;
public Tuple(T1 item1, T2 item2, T3 item3,
T4 item4, T5 item5, T6 item6, T7 item7, TRest t) {
m_Item1 = item1; m_Item2 = item2; m_Item3 = item3; m_Item4 = item4;
m_Item5 = item5; m_Item6 = item6; m_Item7 = item7; m_Rest = rest;
}

public
public
public
public
public
public
public
public

T1 Item1 {
T2 Item2 {
T3 Item3 {
T4 Item4 {
T5 Item5 {
T6 Item6 {
T7 Item7 {
TRest Rest

get {
get {
get {
get {
get {
get {
get {
{ get

return m_Item1; } }
return m_Item2; } }
return m_Item3; } }
return m_Item4; } }
return m_Item5; } }
return m_Item6; } }
return m_Item7; } }
{ return m_Rest; } }

, Tuple
( ). , Tuple
CompareTo, Equals, GetHashCode ToString, Size.
Tuple IStructuralEquatable, IStructuralComparable
IComparable, Tuple , .
SDK.
, Tuple
.
// Item1 Item2
private static Tuple<Int32, Int32>MinMax(Int32 a, Int32 b) {
return new Tuple<Int32, Int32>(Math.Min(a, b), Math.Max(a, b));
}
// Tuple
private static void TupleTypes() {
varminmax = MinMax(6, 2);

278

10.

Console.WriteLine("Min={0}, Max={1}",
minmax.Item1, minmax.Item2); // Min=2, Max=6
}

, , , Tuple
, Item#.
, . Tuple
, . , , .
,
, , / .

, , . System Tuple
Create,
.
Tuple .
Tuple MinMax:
// Item1 Item2
private static Tuple<Int32, Int32>MinMax(Int32 a, Int32 b) {
return Tuple.Create(Math.Min(a, b), Math.Max(a, b)); //
//
}

Tuple , ,
Tuple Rest:
var t = Tuple.Create(0, 1, 2, 3, 4, 5, 6, Tuple.Create(7, 8));
Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}",
t.Item1, t.Item2, t.Item3, t.Item4, t.Item5, t.Item6, t.Item7,
t.Rest.Item1.Item1, t.Rest.Item1.Item2);

, System.Dynamic.
ExpandoObject ( System.Core.dll assembly). C# ( 5)
( -) . ,
( IntelliSense),
ExpandoObject C# ,
Python. ExpandoObject:
dynamic e = new System.Dynamic.ExpandoObject();
e.x = 6; // 'x' Int32
// 6

279

e.y = "Jeff"; // 'y'


// "Jeff"
e.z = null; // 'z'
// null
//
foreach (var v in (IDictionary<String, Object>)e)
Console.WriteLine("Key={0}, V={1}", v.Key, v.Value);
// 'x'
var d = (IDictionary<String, Object>)e;
d.Remove("x");


, , get . (parameterless
properties). , .
,
, (parameterful properties).
get .
-. ,
-: C# , Visual
Basic .
C# .
C# ()
. , , C# [].
BitArray ,
, :
using System;
public sealed class BitArray {
// ,
private Byte[] m_byteArray;
private Int32 m_numBits;
// ,
// 0
public BitArray(Int32 numBits) {
//
if (numBits <= 0)
throw new ArgumentOutOfRangeException("numBits must be > 0");
//
m_numBits = numBits;
//

280

10.
m_byteArray = new Byte[(numBits + 7) / 8];

// ( )
public Boolean this[Int32 bitPos] {
// get
get {
//
if ((bitPos < 0) || (bitPos >= m_numBits))
throw new ArgumentOutOfRangeException("bitPos");
//
return (m_byteArray[bitPos / 8] & (1 << (bitPos % 8))) != 0;
}
// set
set {
if ((bitPos < 0) || (bitPos >= m_numBits))
throw new ArgumentOutOfRangeException(
"bitPos", bitPos.ToString());
if (value) {
//
m_byteArray[bitPos / 8] = (Byte)
(m_byteArray[bitPos / 8] | (1 << (bitPos % 8)));
} else {
//
m_byteArray[bitPos / 8] = (Byte)
(m_byteArray[bitPos / 8] & ~(1 << (bitPos % 8)));
}
}
}
}

BitArray :
// BitArray, 14
BitArray ba = new BitArray(14);
// set
for (Int32 x = 0; x < 14; x++) {
ba[x] = (x % 2 == 0);
}
// get
for (Int32 x = 0; x < 14; x++) {
Console.WriteLine("Bit " + x + " is " + (ba[x] ? "On" : "Off"));
}

BitArray bitPos Int32.


,
. ( )
.
System.Drawing.Imaging.ColorMatrix System.Drawing.dll.

281


. System.Collections.Generic.Dictionary ,
.
,
, .
set , set ( C# value),
.
CLR .
, . , . C# this[...]
, , , C#
. C# , - ,
CLR .
CLR ,

:
get ,
get;
set ,
set;
;
: CLR .
BitArray ,
:
public sealed class BitArray {
// get
public Boolean get_Item(Int32 bitPos) { /* ... */ }
// set
public void set_Item(Int32 bitPos, Boolean value) { /* ... */ }
}

,
get_ set_. C#
, C#
, Item.
get_Item set_Item.

282

10.

.NET Framework , Item, , . , System.


Collections.Generic.List Item,
List.
C#, Item ,
. , ,
, , (get set). C# ,
System.Runtime.CompilerServices.
IndexerNameAttribute. :
using System;
using System.Runtime.CompilerServices;
public sealed class BitArray {
[IndexerName("Bit")]
public Boolean this[Int32 bitPos] {
//
}
}

get_Item set_Item
get_Bit set_Bit. C#
IndexerName , ,
; 1.
Visual Basic,
, C#:
' BitArray
Dim ba as New BitArray(10)
' Visual Basic (),
' [].
Console.WriteLine(ba(2)) " True False
' Visual Basic
Console.WriteLine(ba.Bit(2)) ' ,

C# ,
. IndexerName
, . C# ,
C# ,
IndexerNameAttribute ECMA
CLI C#.
1

283

, , .
C#
( CS0111: SomeType this
):
error CS0111: Class 'SomeType' already defines a member called 'this' with the same
parameter types

, :
using System;
using System.Runtime.CompilerServices;
public sealed class SomeType {
// get_Item
public Int32 this[Boolean b] {
get { return 0; }
}
// get_Jeff
[IndexerName("Jeff")]
public String this[Boolean b] {
get { return null; }
}
}

, C# [],
.
, System.String, String Chars, Item.
. ,
, []
, Chars .
, C#
.
.
,
. CLR ,

System.Reflection.PropertyInfo.


, C# ,
:

284

10.

, ,
?
C#?
: ,
System.Reflection.DefaultMemberAttribute. , DefaultMemberAttribute
, . #
, , DefaultMember
IndexerName.
, ,
.
, C# , ,
IndexerName, DefaultMember, ,
Item.
IndexerName, DefaultMember
, IndexerName. : C#
, .
, ,
DefaultMember.
, C#.

get set JIT- (inlines)


, ,
, .
(, , ) . ,
, . ,
,
, .
, JIT- , . ,
, .
, .

285


get set
. get set:
public class SomeType {
private String m_name;
public String Name {
get { return m_name; }
protected set {m_name = value; }
}
}

, Name public, , get .


, set protected,
SomeType , SomeType.

C# ,
,
. ,
set ( public).


, C# CLR ,
- ( ). C# .
, .
, , . ,
/ ,
. -
( ) , .

11.

,
, . , ( ), ,
. , Button ()
Click (), ,
Button, . ,
. ,
:
;
;
.
,
.
, .
CLR (delegate). , .
(callback methods) , .
, 17.
CLR, , . ,
. ,
. ,
MailManager, . MailManager NewMail.
(, Fax Pager)
. MailManager ,
, . ,
.

MailManager Fax Pager. .11.1 , .

287

. 11.1. ,

MailManager,
NewMail. Fax Pager NewMail (
) MailManager, MailManager ,
.
MailManager , NewMail,
.

, ,
. .
MailManager ( Books http://wintellect.com) MailManager, Fax Pager. ,
Fax Pager .

288

11.

1.
,

, , - .
,
( ) . , ,
, ,
System.EventArgs, EventArgs.
NewMailEventArgs , (m_from), (m_to) (m_subject).
// 1. ,
//
internal class NewMailEventArgs : EventArgs {
private readonly String m_from, m_to, m_subject;
public NewMailEventArgs(String from, String to, String subject) {
m_from = from; m_to = to; m_subject = subject;
}

public String From { get { return m_from; } }


public String To { get { return m_to; } }
public String Subject { get { return m_subject; } }

EventArgs .NET Framework Class Library (FCL)


:
[ComVisible(true), Serializable]
public class EventArgs {
public static readonly EventArgs Empty = new EventArgs();
public EventArgs() { }
}

, . ,
.
. , Button
, . , ,
Event-Args,
EventArgs.Empty.

289

2. -
C# event. -
( ,
), , (
), ( ). NewMail:
internal class MailManager {

// 2. -
public event EventHandler<NewMailEventArgs> NewMail;
...
}

NewMail , EventHandler <NewMailEventArgs>. ,


, EventHandler<NewMailEventArgs>. System.
EventHandler :
public delegate void EventHandler<TEventArgs>
(Object sender, TEventArgs e) where TEventArgs: EventArgs;

:
void MethodName(Object sender, NewMailEventArgs e);

, , sender
Object. -, MailManager ,
NewMailEventArgs,
:
void MethodName(MailManager sender, NewMailEventArgs e);

, sender Object, .
, MailManager
SmtpMailManager? sender SmtpMailManager, MailManager,
, SmtpMailManager NewMail.
, SmtpMailManager ,
sender SmtpMailManager. ,
, sender
Object.
sender Object ,
, ,
NewMailEventArgs. , PopMailManager
, MailManager.

290

11.

: ,
, EventArgs, e. : , .
(, Microsoft Visual Studio) ,
e.
: , void.
,
. void
. , FCL ,
ResolveEventHandler, Microsoft Assembly.

3. ,


, .
, MailMsgEventArgs, .
, ,
,
.
MailManager:
internal class MailManager {
...
// 3. ,
//
// ,
//
protected virtual void OnNewMail(NewMailEventArgs e) {
//
//
EventHandler<NewMailEventArgs> temp = Volatile.Read (ref NewMail);
// ,
// ,
if (temp != null) temp(this, e);
}
...
}

291

,
.NET Framework :
// 1
protected virtual void OnNewMail(NewMailEventArgs e) {
if (NewMail != null) NewMail(this, e);
}

OnNewMail . , NewMail null, NewMail


, NewMail null.
NullReferenceException. :
// 2
protected void OnNewMail(NewMailEventArgs e) {
EventHandler<NewMailEventArgs> temp = NewMail;
if (temp != null) temp(this, e);
}

, NewMail
temp , . temp null temp,
, NewMail temp. ,
, .
,
, temp.
, -
NullReferenceException.
OnNewMail :
// 3
protected void OnNewMail(NewMailEventArgs e) {
EventHandler<NewMailEventArgs> temp = Thread.VolatileRead(ref NewMail);
if (temp != null) temp(this, e);
}

VolatileRead NewMail
temp. temp , null.
Volatile.Read 28.
, 2 JIT-,
, .
JIT- Microsoft
, ,
, .
,

292

11.

. Microsoft JIT-
, 1. , ( Windows
Presentation Foundation Windows Store),
.
(.8), , .
:
public static class EventArgExtensions {
public static void Raise<TEventArgs>(this TEventArgs e,
Object sender, ref EventHandler<TEventArgs> eventDelegate) {
//
//
EventHandler<TEventArgs> temp = Volatile.Read(ref eventDelegate);
// ,
if (temp != null) temp(sender, e);
}
}

OnNewMail :
protected virtual void OnNewMail(NewMailEventArgs e) {
e.Raise(this, ref m_NewMail);
}

, MailManager ,
OnNewMail, -

. ,
. OnNewMail ,
.
.

4. ,

, . MailManager SimulateNewMail
MailManager:
internal class MailManager {
// 4. ,

JIT-.

293

//
public void SimulateNewMail(String from, String to, String subject) {
// ,
//
NewMailEventArgs e = new NewMailEventArgs(from, to, subject);
// ,
// ,
//
OnNewMail(e);
}
}

SimulateNewMail
NewMailEventArgs, .
OnNewMail MailManager,
MailManager .
, . ( , , MailManager,
.)


, , , . MailManager
, -:
public event EventHandler<NewMailEventArgs> NewMail;


:
// 1. , null
private EventHandler<NewMailEventArgs> NewMail = null;
// 2. add_Xxx ( Xxx )
//
public void add_NewMail(EventHandler<NewMailEventArgs> value) {
// CompareExchange
// ,
EventHandler<NewMailEventArgs>prevHandler;
EventHandler<NewMailEventArgs> newMail = this.NewMail;
do {
prevHandler = newMail;
EventHandler<NewMailEventArgs> newHandler =
(EventHandler<NewMailEventArgs>) Delegate.Combine(prevHandler, value);
newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>(
ref this.NewMail, newHandler, prevHandler);

294

11.

} while (newMail != prevHandler);

// 3. remove_Xxx ( Xxx )
//
// c
public void remove_NewMail(EventHandler<NewMailEventArgs> value) {
// CompareExchange
// ,
EventHandler<NewMailEventArgs> prevHandler;
EventHandler<NewMailEventArgs> newMail = this.NewMail;
do {
prevHandler = newMail;
EventHandler<NewMailEventArgs> newHandler =
(EventHandler<NewMailEventArgs>) Delegate.Remove(prevHandler, value);
newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>(
ref this.NewMail, newHandler, prevHandler);
} while (newMail != prevHandler);
}

. , . null; ,
, .
,
EventHandler<NewMailEventArgs>, , , EventHandler<NewMailEventArgs>. ,
. ,
.
: (NewMail ) ,
.
,
. , , , .
, C#, ,
. C# ,
add_ (NewMail). C#
, Combine
System.Delegate. Combine
, .
, C#, ,
. C# , remove_
(NewMail). Remove System.Delegate.

295

,
.

, , Delegate.Remove
. , ,
.

add remove
, .
28.

add remove ,
. , add remove,
, .
, ,

, . ;
add remove
.
,
.
-, add remove. ,
.
, , ,
System.Reflection.EventInfo.
CLR
.

,
. , , , .
Fax:
internal sealed class Fax {
// MailManager

296

11.

public Fax(MailManager mm) {


// EventHandler<NewMailEventArgs>,
// FaxMsg
// NewMail MailManager
mm.NewMail += FaxMsg;
}
// MailManager
// Fax
private void FaxMsg(Object sender, NewMailEventArgs e) {
// 'sender' MailManager,
// -
// 'e' ,
// MailManager
//
//
Console.WriteLine("Faxing mail message:");
Console.WriteLine(" From={0}, To={1}, Subject={2}",
e.From, e.To, e.Subject);
}
// Fax
// NewMail
public void Unregister(MailManager mm) {
// NewMail
MailManager. mm.NewMail -= FaxMsg;
}
}

MailManager
. Fax,
MailManager . Fax Fax
NewMail MailManager +=
C#:
mm.NewMail += FaxMsg;

, C# += , :
mm.add_NewMail(new EventHandler<NewMailEventArgs>(this.FaxMsg));

, C# ,

EventHandler<NewMailEventArgs>, FaxMsg
Fax. C# add_NewMail MailManager, -

. , ,
IL- , ILDasm.exe.

297

, , , add.
, .
add ,
.
MailManager, FaxMsg Fax. sender
MailManager. , , Fax
MailManager.
NewMailEventArgs. , , NewMailEventArgs, .
NewMailEventArgs FaxMsg
,
. Fax , .
,
. , Fax
NewMail,
. ,
. Dispose IDisposable,
( IDisposable
. 21).
, ,
Unregister Fax.
Fax. , +=
=. , =,
C# remove :
mm.remove_NewMail(new EventHandler<NewMailEventArgs>(FaxMsg));

+=, , ,
remove,
- , .
, . ,
, .
, C# , += =.
add remove, C#
(CS0571: ):
CS0571: cannot explicitly call operator or accessor

298

11.


System.Windows.Forms.Control 70 .
Control ,
add remove -, Control
70- !
, ,
Control ,
. , System.Web.UI.Control ( ASP.NET) System.Windows.
UIElement ( Windows Presentation Foundation, WPF)
, .
, C#
, , add remove
. , .
,
.
,
, ( ),
, . .
. ,
.
, .
.
, ,
. ,
, . ,
, . , ,
.
.
EventSet, :
using System;
using System.Collections.Generic;
using System.Threading;
//
// EventSet
public sealed class EventKey : Object { }
public sealed class EventSet {
// EventKey -> Delegate


private readonly Dictionary<EventKey, Delegate> m_events =
newDictionary<EventKey, Delegate>();
// EventKey -> Delegate,
// EventKey
public void Add(EventKey eventKey, Delegate handler) {
Monitor.Enter(m_events);
Delegate d;
m_events.TryGetValue(eventKey, out d);
m_events[eventKey] = Delegate.Combine(d, handler);
Monitor.Exit(m_events);
}
// EventKey ( )
// EventKey -> Delegate
//
public void Remove(EventKey eventKey, Delegate handler) {
Monitor.Enter(m_events);
// TryGetValue
// EventKey.
Delegate d;
if (m_events.TryGetValue(eventKey, out d)) {
d = Delegate.Remove(d, handler);
// , EventKey,
// EventKey
if (d != null) m_events[eventKey] = d;
else m_events.Remove(eventKey);
}
Monitor.Exit(m_events);
}
// EventKey
public void Raise(EventKey eventKey, Object sender, EventArgs e) {
// EventKey
Delegate d;
Monitor.Enter(m_events);
m_events.TryGetValue(eventKey, out d);
Monitor.Exit(m_events);
if (d != null) {
// -
// , ,
// , .
// DynamicInvoke System.Delegate,
// . DynamicInvoke
//
// . ,
// .
d.DynamicInvoke(newObject[] { sender, e });
}
}

299

300

11.

, EventSet.
, EventSet,
, add EventSet, remove
( ).
using System;
// , EventArgs
public class FooEventArgs : EventArgs { }
public class TypeWithLotsOfEvents {
// , .
// "Event/Delegate"
// : EventSet FCL,
//
private readonly EventSet m_eventSet = newEventSet();
//
protected EventSet EventSet { get { return m_eventSet; } }
#region Code to support the Foo event (repeat this pattern for additional events)
// , Foo.
// 2a. ,
// .
// -
// .
protected static readonly EventKey s_fooEventKey = newEventKey();
// 2b.
// .
public event EventHandler<FooEventArgs> Foo {
add { m_eventSet.Add(s_fooEventKey, value); }
remove { m_eventSet.Remove(s_fooEventKey, value); }
}
// 2c. On .
protected virtual void OnFoo(FooEventArgs e) {
m_eventSet.Raise(s_fooEventKey, this, e);
}
// 2d. ,
public void SimulateFoo() {OnFoo(newFooEventArgs());}
#endregion
}

, TypeWithLotsOfEvents, ,
.
.
:


public sealed class Program {
public static void Main() {
TypeWithLotsOfEvents twle = new TypeWithLotsOfEvents();
//
twle.Foo += HandleFooEvent;
//
twle.SimulateFoo();
}
private static void HandleFooEvent(object sender, FooEventArgs e) {
Console.WriteLine("Handling Foo Event here...");
}
}

301

12.

- .
, .
,
. (generics)
, CLR
.
, , , , , , , ,
, .
, ,
Int32, String .., DateTime, Version ..
. CLR
, , . , CLR
.
, CLR , , .
, FCL
, . . , ,
.
FCL-, , List<T> System.Collections.Generic.
( ):
[Serializable]
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>,
IList, ICollection, IEnumerable {
public
public
public
public

List();
void Add(T item);
Int32 BinarySearch(T item);
void Clear();


public
public
public
public
public
public
public

303

Boolean Contains(T item);


Int32 IndexOf(T item);
Boolean Remove(T item);
void Sort();
void Sort(IComparer<T> comparer);
void Sort(Comparison<T> comparison);
T[] ToArray();

public Int32 Count { get; }


public T this[Int32 index] { get; set; }

<T> List ,
.
, (, T),
(type parameters). T ,
, .
, List T (
Add T) ( ToArray T) . -
( C# this). get,
T, set, T. T
, ,
.

Microsoft , T , , T (, , TKey TValue). T (type), I (,


IComparable).

, List<T> ;
, . -
(type arguments). , List,
DateTime -:
private static void SomeMethod() {
// (List), DateTime
List<DateTime> dtList = new List<DateTime>();
// DateTime
dtList.Add(DateTime.Now); //
// DateTime

304

12.

dtList.Add(DateTime.MinValue); //
// String
dtList.Add("1/1/2004"); //
// DateTime
DateTime dt = dtList[0]; //
}

.
. , ,
( C++
, , ).
.
, CLR ,
, .
.
String Add .
. , ,
. SomeMethod (DateTime), dt ( 0).
.

, Object.
,
CLR . 5,
,
, , ,
.
,
CLR .
(. ), CLR
, .
, ,
ArrayList FCL List. ,
:


using
using
using
using

305

System;
System.Collections;
System.Collections.Generic;
System.Diagnostics;

public static class Program {


public static void Main() {
ValueTypePerfTest();
ReferenceTypePerfTest();
}
private static void ValueTypePerfTest() {
const Int32 count = 10000000;
using (new OperationTimer("List<Int32>")) {
List<Int32> l = new List<Int32>();
for (Int32 n = 0; n < count; n++) {
l.Add(n); //
Int32 x = l[n]; //
}
l = null; //
}
using (new OperationTimer("ArrayList of Int32")) {
ArrayList a = new ArrayList();
for (Int32 n = 0; n < count; n++) {
a.Add(n); //
Int32 x = (Int32) a[n]; //
}
a = null; //
}
}
private static void ReferenceTypePerfTest() {
const Int32 count = 10000000;
using (new OperationTimer("List<String>")) {
List<String> l = new List<String>();
for (Int32 n = 0; n < count; n++) {
l.Add("X"); //
String x = l[n]; //
}
l = null; //
}
using (new OperationTimer("ArrayList of String")) {
ArrayList a = new ArrayList();
for (Int32 n = 0; n < count; n++) {
a.Add("X"); //
String x = (String) a[n]; //
} //
a = null; //

306

12.
}

//
internal sealed class OperationTimer : IDisposable {
private Int64 m_startTime;
private String m_text;
private Int32 m_collectionCount;
public OperationTimer(String text) {
PrepareForOperation();
m_text = text;
m_collectionCount = GC.CollectionCount(0);
//
//
m_startTime = Stopwatch.StartNew();
}
public void Dispose() {
Console.WriteLine("{0} (GCs={1,3}) {2}", (m_stopwatch.Elapsed),
GC.CollectionCount(0) m_collectionCount, m_text);
}

private static void PrepareForOperation() {


GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}

( ) , :
00:00:01.6246959
00:00:10.8555008
00:00:02.5427847
00:00:02.7944831

(GCs= 6)
(GCs=390)
(GCs= 4)
(GCs= 7)

List<Int32>
ArrayList of Int32
List<String>
ArrayList of String

, Int32 List ,
ArrayList. , : 1,6
11 , 7 ! ,
(Int32) ArrayList , ,
, 390 , List 6.
: .
List
. ,
. ,

FCL

307

,
.

, CLR
.
.
.

FCL
, , FCL . System.Collections.Generic System.Collections.ObjectModel.

System.Collections.Concurrent. Microsoft
. -, ,
, ,
. -,
, . , , , ,
, .
, ,
, ,
, . FCL
,
.
System.Collections.Generic.
: .
. , List<T> IList<T>,
List< DateTime> IList.
, System.Array , , ,
AsReadOnly, BinarySearch, ConvertAll, Exists, Find, FindAll, FindIndex, FindLast,
FindLastIndex, ForEach, IndexOf, LastIndexOf, Resize, Sort TrueForAll.
:
public abstract class Array : ICloneable, IList, ICollection, IEnumerable,
IStructuralComparable, IStructuralEquatable {

308

12.

public static void Sort<T>(T[] array);


public static void Sort<T>(T[] array, IComparer<T> comparer);
public static Int32 BinarySearch<T>(T[] array, T value);
public static Int32 BinarySearch<T>(T[] array, T value,
IComparer<T> comparer);
...
}

:
public static void Main() {
//
Byte[] byteArray = new Byte[] { 5, 1, 4, 2, 3 };
// Byte[]
Array.Sort<Byte>(byteArray);
// Byte[]
Int32 i = Array.BinarySearch<Byte>(byteArray, 1);
Console.WriteLine(i); // "0"
}


2.0 CLR,
. Microsoft
:
IL-, .

.
( C#, Microsoft Visual
Basic .NET .),
.
IL-
.
JIT-, IL-, , .
, , .
, ,

.

309

, , ,
.
IntelliSense Microsoft Visual Studio
.
,
CLR. ,
.


, CLR
, . (type objects). , CLR
-.
(), (), .
- (open type),
CLR (
).

. , (closed type). CLR . ,
, .
, CLR ,
. :
using System;
using System.Collections.Generic;
//
internal sealed class DictionaryStringKey<TValue> :
Dictionary<String, TValue> {
}
public static class Program {
public static void Main() {
Object o = null;
// Dictionary<,>
Type t = typeof(Dictionary<,>);
// ()
o = CreateInstance(t);
Console.WriteLine();
// DictionaryStringKey<>

310

12.
t = typeof(DictionaryStringKey<>);

// ()
o = CreateInstance(t);
Console.WriteLine();
// DictionaryStringKey<Guid>
t = typeof(DictionaryStringKey<Guid>);
// ()
o = CreateInstance(t);
//
Console.WriteLine("Object type=" + o.GetType());
}
private static Object CreateInstance(Type t) {
Object o = null;
try {
o = Activator.CreateInstance(t);
Console.Write("Created instance of {0}", t.ToString());
}
catch (ArgumentException e) {
Console.WriteLine(e.Message);
}
return o;
}
}

, :
Cannot create an instance of System.Collections.Generic.
Dictionary`2[TKey,TValue] because Type.ContainsGenericParameters is true.
Cannot create an instance of DictionaryStringKey`1[TValue] because
Type.ContainsGenericParameters is true.
Created instance of DictionaryStringKey`1[System.Guid]
Object type=DictionaryStringKey`1[System.Guid]

, CreateInstance
Activator ArgumentException. , .
,
(`), ,
(arity) , . , Dictionary 2,
TKey TValue. DictionaryStringKey 1,
TValue.

311

, CLR
- (.4). , . , , List<T>,
List<DateTime> List<String>,
.
(. 8), .
, . , ,
, :
internal sealed class GenericTypeThatRequiresAnEnum<T> {
static GenericTypeThatRequiresAnEnum() {
if (!typeof(T).IsEnum) {
throw new ArgumentException("T must be an enumerated type");
}
}
}

CLR (constraints),

. . ,
,

, .


, , . CLR
-, ,
. , List<T> Object ,
List<String> List<Guid> Object. ,
DictionaryStringKey<TValue> Dictionary<String, TValue>, DictionaryStringKey<Guid> Dictionary<String,
Guid>. ,
, , , .
, Node .
internal sealed class Node<T> {
public T m_data;
public Node<T> m_next;
public Node(T data) : this(data, null) {
}

312

12.

public Node(T data, Node<T> next) {


m_data = data; m_next = next;
}

public override String ToString() {


return m_data.ToString() +
((m_next != null) ? m_next.ToString() : null);
}

:
private static void SameDataLinkedList() {
Node<Char> head = new Node<Char>('C');
head = new Node<Char>('B', head);
head = new Node<Char>('A', head);
Console.WriteLine(head.ToString()); // "ABC"
}

Node m_next ,
m_data . ,

( ) . , Node ,
Char, DateTime, String , ,
Node<Object>,
, .
,
Node, TypedNode ( Node
).
,
. :
internal class Node {
protected Node m_next;

public Node(Node next) {


m_next = next;
}

internal sealed class TypedNode<T> : Node {


public T m_data;
public TypedNode(T data) : this(data, null) {
}
public TypedNode(T data, Node next) : base(next) {
m_data = data;
}
public override String ToString() {

313

return m_data.ToString() +
((m_next != null) ? m_next.ToString() : String.Empty);


. :
private static void DifferentDataLinkedList() {
Node head = new TypedNode<Char>('.');
head = new TypedNode<DateTime>(DateTime.Now, head);
head = new TypedNode<String>("Today is ", head);
Console.WriteLine(head.ToString());
}


.
(<) (>),
. ,
. ,
:
List<DateTime> dt = new List<DateTime>();

:
internal sealed class DateTimeList : List<DateTime> {
// !
}

( < >):
DateTimeList dt = new DateTimeList();

,
.
, . :
, :
Boolean sameType = (typeof(List<DateTime>) == typeof(DateTimeList));

sameType false, . , ,
, DateTimeList,
List<DateTime>. ,
List<DateTime>, DateTimeList, DateTimeList List<DateTime>. .
, C#
, .

314

12.


using:
using DateTimeList = System.Collections.Generic.List<System.DateTime>;

using DateTimeList.
DateTimeList
System.Collections.Generic.List<System.DateTime>. , ,
.
sameType true:
Boolean sameType = (typeof(List<DateTime>) == typeof(DateTimeList));


C#,
:
using System;
using System.Collections.Generic;
...
internal sealed class SomeType {
private static void SomeMethod () {
// , dtl
// System.Collections.Generic.List<System.DateTime>
var dtl = List<DateTime>();
...
}
}


JIT- CLR IL-
-, ,
. , ,
. : CLR
+ ,
(code explosion);
, .
, CLR , . -,
, CLR + . ,
List<DateTime> (
), CLR List<DateTime>
. .

315

, CLR ,
. , , CLR List<String>,
List<Stream>, String Stream . ,
. CLR ,

(32- 32- 64-
64- Windows), .
, CLR . ,
.
(, Int32 UInt32 32- ), CLR ,
.


,
. CLR
.
(, IComparable)

, .
CLR .
-,
, -.
.
FCL (
System.Collections.Generic) :
public interface IEnumerator<T> : IDisposable, IEnumerator {
T Current { get; }
}


.
, Triangle
Point, Current Point:
internal sealed class Triangle : IEnumerator<Point> {
private Point[] m_vertices;
// Current IEnumerator<Point> - Point

316

12.

public Point Current { get { ... } }


...

, ,
-:
internal sealed class ArrayEnumerator<T> : IEnumerator<T> {
private T[] m_array;
// Current IEnumerator<T> T
public T Current { get { ... } }
...
}

: ArrayEnumerator T (
T , , ArrayEnumerator,
T ). , Current T.
13.


CLR
, .
, . 17,
: Invoke, BeginInvoke EndInvoke.
,
, .
, :
public delegate TReturn CallMe<TReturn, TKey, TValue>(
TKey key, TValue value);

, :
public sealed class CallMe<TReturn, TKey, TValue> : MulticastDelegate {
public CallMe(Object object, IntPtr method);
public virtual TReturn Invoke(TKey key, TValue value);
public virtual IAsyncResult BeginInvoke(TKey key, TValue value,
AsyncCallback callback, Object object);
public virtual TReturn EndInvoke(IAsyncResult result);
}

317

, , Action
Func FCL. 17.

-

-
.
-. - :
. - . -.
. - ,
. C# in. -
, , .
. -
. #
out.
, , .
, :
public delegate TResult Func<in T, out TResult>(T arg);

- T in, ,
- TResult out, .
:
Func<Object, ArgumentException> fn1 = null;

Func -:
Func<String, Exception> fn2 = fn1; //
Exception e = fn2("");

, fn1 , Object
ArgumentException. fn2 ,
String Exception.
String , Object ( String
Object), , ArgumentException, Exception ( ArgumentException
Exception), ,
.

318

12.

,
. , - (boxing).
, - . :
void ProcessCollection(IEnumerable<Object> collection) { ... }

, List<DateTime> -
DateTime Object, DateTime Object.
:
void ProcessCollection<T>(IEnumerable<T> collection) { ... }

ProcessCollection(IEnumerable<Object> collection)
, JIT-.
ProcessCollection<T> (IEnumerable<T> collection)
JIT-, T, . T, ,
JIT-,
.
-,
out ref. , :
delegate void SomeDelegate<in T>(ref T t);

( : - 'T'
'SomeDelegate<T>.Invoke(ref T)'. - 'T' ):
Invalid variance: The type parameter 'T' must be invariantly valid on
'SomeDelegate<T>.Invoke(ref T)'. 'T' is contravariant


in out , .
,
.
, -
, . :
public interface IEnumerator<out T> : IEnumerator {
Boolean MoveNext();
T Current { get; }
}

T :

319

// IEnumerable
Int32 Count(IEnumerable<Object> collection) { ... }
...
// IEnumerable<String> Count
Int32 c = Count(new[] { "Grant" });

, in
out . ,
,
. , C# ,
. , ,
,
- .
, - ,
, -,
.
. - , ,
. in out
-, , .



, , -.
- ,
. CLR
-, , .
, -
-:
internal sealed class GenericType<T> {
private T m_value;
public GenericType(T value) { m_value = value; }
public TOutput Converter<TOutput>() {
TOutput result = (TOutput) Convert.ChangeType(m_value, typeof(TOutput));

320

12.
return result;

GenericType - (T),
Converter (TOutput). GenericType,
. Converter ,
m_value, , . -
.
Swap:
private static void Swap<T>(ref T o1, ref T o2) {
T temp = o1;
o1 = o2;
o2 = temp;
}

Swap :
private static void CallingSwap() {
Int32 n1 = 1, n2 = 2;
Console.WriteLine("n1={0}, n2={1}", n1, n2);
Swap<Int32>(ref n1, ref n2);
Console.WriteLine("n1={0}, n2={1}", n1, n2);
String s1 = "Aidan", s2 = "Grant";
Console.WriteLine("s1={0}, s2={1}", s1, s2);
Swap<String>(ref s1, ref s2);
Console.WriteLine("s1={0}, s2={1}", s1, s2);
}

, out
ref, , ,
out/ref, , , . out/ref 9. , Exchange CompareExchange
Interlocked 1:
public static class Interlocked {
public static T Exchange<T>(ref T location1, T value) where T: class;
public static T CompareExchange<T>(
ref T location1, T value, T comparand) where T: class;
}


C#
. ,

where .

321

# (type inference)
. ,
( ) ,
. :
private static void CallingSwapUsingInference() {
Int32 n1 = 1, n2 = 2;
Swap(ref n1, ref n2); // Swap<Int32>
String s1 = "Aidan";
Object s2 = "Grant";
Swap(ref s1, ref s2); // ,
}

, Swap
< >. Swap C# ,
n1 n2 Int32, Swap,
- Int32.
C#
, , .
Swap C# , s1 String,
s2 Object ( s2 String). s1 s2
,
Swap ( CS0411:
Program.Swap<T>(ref T, ref T) .
):
error CS0411: The type arguments for method 'Program.Swap<T>(ref T, ref T)' cannot
be inferred from the usage. Try specifying the type arguments explicitly

,
, -,
:
private static void Display(String s) {
Console.WriteLine(s);
}
private static void Display<T>(T o) {
Display(o.ToString()); // Display(String)
}

Display :
Display("Jeff"); // Display(String)
Display(123); // Display<T>(T)
Display<String>("Aidan"); // Display<T>(T)

Display,
String, Display ( T String).

C# , ,

322

12.

Display, String.
Display, String,
Display. , ,
.
Display, ToString, String,
.
Display String.
, , .
,
Display, . Display
ToString ,
Display.


C# , , , ,
-.
, -
.
C#
, # Microsoft , .
#
, . ,
+
. , +,
.


C# , , ,
. :
private static Boolean MethodTakingAnyType<T>(T o) {
T temp = o;
Console.WriteLine(o.ToString());
Boolean b = temp.Equals(o);
return b;
}

323

(temp) T,
.
, , , , ,
, , Object (, ToString Equals).
:
private static T Min<T>(T o1, T o2) {
if (o1.CompareTo(o2) < 0) return o1;
return o2;
}

Min o1 CompareTo.
CompareTo, #
, . ( CS0117: T CompareTo):
error CS0117: 'T' does not contain a definition for 'CompareTo'

, , , ,
Object, ! . ,
CLR
(constraints), .
,
, .
Min, ( ):
public static T Min<T>(T o1, T o2) where T : IComparable<T> {
if (o1.CompareTo(o2) < 0) return o1;
return o2;
}

where C# , T IComparable (T).


CompareTo,
IComparable<T>.
, ,
, , .
:
private static void CallMin() {
Object o1 = "Jeff", o2 = "Richter";
Object oMin = Min<Object>(o1, o2); // CS0311
}

324

12.

( CS0311: object
- 'T'
'SomeType.Min<T>(T,T)'.
'Object' 'System.IComparable<object>'.
Error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic
type or method 'SomeType.Min<T>(T, T)'. There is no implicit
reference conversion from 'object' to 'System.IComparable<object>'.

, System.Object IComparable<Object>. System.Object


.
, , .
,
( Min). CLR
.
. :
//
internal
internal
internal

:
sealed class AType {}
sealed class AType<T> {}
sealed class AType<T1, T2> {}

// : AType<T>, .
internal sealed class AType<T> where T : IComparable<T> {}
// : AType<T1, T2>
internal sealed class AType<T3, T4> {}
internal sealed class
//
private static void
private static void
private static void

AnotherType {
:
M() {}
M<T>() {}
M<T1, T2>() {}

// : M<T>,
private static void M<T>() where T : IComparable<T> {}
// : M<T1, T2>.
private static void M<T3, T4>() {}
}


-, , ,
, . ,
-, -. ,
-, , -
, . :

325

internal class Base {


public virtual void M<T1, T2>()
where T1 : struct
where T2 : class {
}
}
internal sealed class Derived : Base {
public override void M<T3, T4>()
where T3 : EventArgs //
where T4 : class //
{ }
}

( CS0460:

):
Error CS0460: Constraints for override and explicit interface implementation
methods are inherited from the base method, so they cannot be
specified directly

M<T3, T4> Derived where,


. : (
T1 T3, 2 4), ( ) .
, CLR
. -
: (primary), (secondary) /
(constructor constraint).
.


- .
, .
: System.Object,
System.Array, System.Delegate, System.MulticastDelegate, System.ValueType,
System.Enum System.Void.
,
- , ,
.
:
internal sealed class PrimaryConstraintOfStream<T> where T : Stream {
public void M(T stream) {
stream.Close();// OK
}
}

326

12.

- T Stream ( System.IO), ,
, PrimaryConstraintOfStream,
Stream (, FileStream). -
, System.Object.
System.Object, C#
( CS0702: object):
error CS0702: Constraint cannot be special class 'object'

: class struct. class


, -
. -, -, -, :
internal sealed class PrimaryConstraintOfClass<T> where T : class {
public void M() {
T temp = null;// , T
}
}

temp null , , T ,
null. T , ,
null.
struct ,
.
, . CLR
System.Nullable<T> ,
null . ,
Nullable<T> struct, CLR
, Nullable<Nullable<T>>.
null 19.
, -
struct:
internal sealed class PrimaryConstraintOfStruct<T> where T : struct {
public static T Factory() {
// ,
//
return new T();
}
}

T new , ,
T , . T ,

327

, ,
.


- . ,
- , .
,
, (
, ). .13.
(type parameter constraint). ,
, ,
- . .
-:
private static List<TBase> ConvertIList<T, TBase>(IList<T> list)
where T : TBase {
List<TBase> baseList = new List<TBase>(list.Count);
for (Int32 index = 0; index < list.Count; index++) {
baseList.Add(list[index]);
}
return baseList;
}

ConvertIList -, T
TBase. , -
T, -, TBase.
ConvertIList:
private static void CallingConvertIList() {
// List<String> ( IList<String>)
IList<String> ls = new List<String>();
ls.Add("A String");
// IList<String> IList<Object>
IList<Object> lo = ConvertIList<String, Object>(ls);
// IList<String> IList<IComparable>
IList<IComparable> lc = ConvertIList<String, IComparable>(ls);
// IList<String> IList<IComparable<String>>
IList<IComparable<String>> lcs =
ConvertIList<String, IComparable<String>>(ls);
// IList<String> IList<String>
IList<String> ls2 = ConvertIList<String, String>(ls);

328

12.

// IList<String> IList<Exception>
IList<Exception> le = ConvertIList<String, Exception>(ls); //
}

ConvertIList , String
Object. String Object,
-. ConvertIList
, String IComparable.
String IComparable,
-. ConvertIList ,
String IComparable<String>. String
IComparable<String>, -.
ConvertIList , String
. ConvertIList , String
Exception. String Exception,
,
( CS0311: string 'T' Program.ConvertIList<T,TBase>(System.
Collectons.Generic.IList<T>).
'string' 'System.Exception':
error CS0311: The type 'string' cannot be used as type parameter 'T' in the
generic type or method Program.ConvertIList<T,TBase>(System.Collections.Ge
neric.IList<T>)'. There is no implicit reference conversion from 'string' to
'System.Exception'.


- .
, -
, .
, #
struct, .
.
- :
internal sealed class ConstructorConstraint<T> where T : new() {
public static T Factory() {
// ,
// ,
// ,
//
return new T();
}
}

new T , , T . ,

329

, ,
, -.

, .
CLR (, , C#)
. Microsoft,
, .


, -
,
, .


, , :
private static void CastingAGenericTypeVariable1<T>(T obj) {
Int32 x = (Int32) obj ; //
String s = (String) obj; //
}

,
. ,
, Object:
private static void CastingAGenericTypeVariable2<T>(T obj) {
Int32 x = (Int32) (Object) obj ; //
String s = (String) (Object) obj; //
}

, CLR
InvalidCastException.
as C#.
String ( Int32
):
private static void CastingAGenericTypeVariable3<T>(T obj) {
String s = obj as String; //
}

null ,
:

330

12.

private static void SettingAGenericTypeVariableToNull<T>() {


T temp = null; // CS0403: null T
// because it could be a value type...
// ( CS0403: null ,
// T ...)
}

T , , null .
, temp null,
. C# Microsoft , .
# default:
private static void SettingAGenericTypeVariableToDefaultValue<T>() {
T temp = default(T); //
}

default C# JIT CLR , temp null, T , temp, .


null
null == !=
, :
private static void ComparingAGenericTypeVariableWithNull<T>(T obj) {
if (obj == null)
{ /* */ }
}

T , . obj null. C#
, .
JIT, , if true,
if .
!=, JIT-
if ( ), if.
, struct, # ,
, null,
.


, :

331

private static void ComparingTwoGenericTypeVariables<T>(T o1, T o2) {


if (o1 == o2) { } //
}

T ,
,
, ==. T
class, , == true, . T
, operator==,
, ==. , !=.
(Byte, Int32,
Single, Decimal ..) # , .
ComparingTwoGenericTypeVariables struct,
. - ,
, ,
, . ,
; C# ,
.

,
. 5 , C#
Byte, Int16, Int32, Int64, Decimal . , , C#
, ( +,
, * /).
, . ,

. , :
private static T Sum<T>(T num) where T : struct {
T sum = default(T) ;
for (T n = default(T) ; n < num ; n++)
sum += n;
return sum;
}

, :

struct default(T), sum n -

. :
CS0019: < T :

error CS0019: Operator '<' cannot be applied to operands


of type 'T' and 'T'

332

12.

CS0023: ++ :
error CS0023: Operator '++' cannot be applied to operand of type 'T'

CS0019: += T :
error CS0019: Operator '+=' cannot be applied to operands
of type 'T' and 'T'

CLR,
( , )
. ,
, (.23),
dynamic (. 5), ..
.
, CLR Microsoft
.

13.

(multiple inheritance) ,
. , TransmitData,
, ReceiveData, .
, SocketPort, , . SocketPort
: TransmitData ReceiveData.
, SocketPort, .
CLR ( , )
. CLR (interfaces).
,
, ,
, .


.NET Framework System.Object, 4
: ToString, Equals, GetHashCode GetType. ,
Object. , , Object,
.
Object :
. ,
Object, -
.
. ,
Object, Object .
CLR (
Object). .
, ,
.

334

13.

CLR , , , .
.
,
CLR . ,
,
. C# CLR
, , ,
.
,
. , , ,
.
, , .


,
. , ,
( C# ),
,
.
, .
CLR ,
, , CLS-
,
. C#
.
C# ,
interface.
Framework Class Library:
public interface IDisposable {
void Dispose();
}
public interface IEnumerable {
IEnumerator GetEnumerator();
}
public interface IEnumerable<T> : IEnumerable {

335

IEnumerator<T> GetEnumerator();

public interface ICollection<T> : IEnumerable<T>, IEnumerable {


void Add(T item);
void Clear();
Boolean Contains(T item);
void CopyTo(T[] array, Int32 arrayIndex);
Boolean Remove(T item);
Int32 Count { get; } //
Boolean IsReadOnly { get; } //
}

CLR, ,
. CLR , . ,
.
(public, protected, internal ..).
I , . CLR
( ) .
, .12.
. ,
, .
. ,
TCollection<T> TEnumerable<T> IEnumerable.
:
, ICollection<T>,
, ICollection<T>, IEnumerable<T>
IEnumerable;
, , ICollection<T>,
,
IEnumerable<T> IEnumerable.


, , ,
.
C# , ,
.

336

13.

System.IComparable<T> ( MSCorLib.dll):
public interface IComparable<T> {
Int32 CompareTo(T other);
}

, , , , Point:
using System;
// Point System.Object
// IComparable<T> Point
public sealed class Point : IComparable<Point> {
private Int32 m_x, m_y;
public Point(Int32 x, Int32 y) {
m_x = x;
m_y = y;
}
// IComparable<T> Point
public Int32 CompareTo(Point other) {
return Math.Sign(Math.Sqrt(m_x * m_x + m_y * m_y)
- Math.Sqrt(other.m_x * other.m_x + other.m_y * other.m_y));
}
public override String ToString() {
return String.Format("({0}, {1})", m_x, m_y);
}
}
public static class Program {
public static void Main() {
Point[] points = new Point[] {
new Point(3, 3),
new Point(1, 2),
};
// CompareTo IComparable<T> Point
if (points[0].CompareTo(points[1]) > 0) {
Point tempPoint = points[0];
points[0] = points[1];
points[1] = tempPoint;
}
Console.WriteLine("Points from closest to (0, 0) to farthest:");
foreach (Point p in points)
Console.WriteLine(p);
}
}

C# , , ,
public. CLR , -

337

. ,
, , .
. ,
, .
,
,
.
, . :
using System;
public static class Program {
public static void Main() {
/************************* *************************/
Base b = new Base();
// Dispose b: "Dispose Base"
b.Dispose();
// Dispose b: "Dispose Base"
((IDisposable)b).Dispose();
/************************* ************************/
Derived d = new Derived();
// Dispose d: "Dispose Derived"
d.Dispose();
// Dispose d: "Dispose Derived"
((IDisposable)d).Dispose();
/************************* *************************/
b = new Derived();
// Dispose b: "Dispose Base"
b.Dispose();
// Dispose b: "Dispose Derived"
((IDisposable)b).Dispose();
}
}
// Object IDisposable
internal class Base : IDisposable {
//
public void Dispose() {
Console.WriteLine("Base's Dispose");
}
}

338

13.

// Base IDisposable
internal class Derived : Base, IDisposable {
// Dispose Base.
// 'new' ,
// Dispose IDisposable
new public void Dispose() {
Console.WriteLine("Derived's Dispose");
// : ,
// ( )
// base.Dispose();
}
}

System.String FCL System.Object. , String :


IComparable, ICloneable, IConvertible, IEnumerable, IComparable<String> ,
IEnumerable<Char> IEquatable<String>. , String ( ) ,
Object. String ,
.
CLR , ,
. ,
, . CLR , Object,
, :
// s String
String s = "Jeffrey";
// s, ,
// String, Object, IComparable, ICloneable,
// IConvertible, IEnumerable ..
// cloneable String
ICloneable cloneable = s;
// cloneable, ,
// ICloneable ( ,
// Object)
// comparable String
IComparable comparable = s;
// comparable, ,
// IComparable ( ,
// Object)

( )

339

// enumerable String
//
// ,
IEnumerable enumerable = (IEnumerable) comparable;
// enumerable, ,
// IEnumerable ( ,
// Object)

String
, , ,
, String, "Jeffrey".
, . s String, , ,
String (, Length). s
, Object (, GetType).
cloneable ICloneable, ,
Clone, . , , Object (, GetType),
CLR , Object.
cloneable ,
, String. comparable CompareTo ,
Object, .

, ( ) .
, ,
, CLR . CLR ,
.


( )
CLR,
(.1). , , ,
. ,
, , . , :

340

13.

internal sealed class SimpleType : IDisposable {


public void Dispose() { Console.WriteLine("Dispose"); }
}

, :
, Object
;
,
IDisposable ( IDisposable
Dispose);
, Dispose, SimpleType.
, C# , SimpleType Dispose Dispose
IDisposable. C# ,
,
. , . ,
Dispose , C#
.
, C#
, , SimpleType
. ,
Dispose ,
Dispose IDisposable.
public sealed class Program {
public static void Main() {
SimpleType st = new SimpleType();
// Dispose
st.Dispose();
// Dispose IDisposable
IDisposable d = st;
d.Dispose();
}
}

Dispose , SimpleType . d
IDisposable. d SimpleType.
d.Dispose() Dispose IDisposable. C# , Dispose
Dispose IDisposable,
, - .
:

341

Dispose
Dispose

SimpleType, :
internal sealed class SimpleType : IDisposable {
public void Dispose() { Console.WriteLine("public Dispose"); }
void IDisposable.Dispose() { Console.WriteLine("IDisposable Dispose"); }
}

Main, , :
public Dispose
IDisposable Dispose

C# ,
( IDisposable.Dispose), (Explicit Interface Method Implementation, EIMI).
: C#
( ).
, (private),

. .
, EIMI- , ,
. , EIMI- ; ( , ) .
, , .
EIMI.


C# CLR
.
.
-, . (, IComparable)
, Object.

, . :
private void SomeMethod1() {
Int32 x = 1, y = 2;
IComparable c = x;

342

13.

// CompareTo Object,
// y Int32
c.CompareTo(y); //
// CompareTo Object,
// "2" ( String) ,
// ArgumentException
c.CompareTo("2");
}

, , FCL IComparable<T>.
, :
private void SomeMethod2() {
Int32 x = 1, y = 2;
IComparable<Int32> c = x;
// CompareTo Object,
// y Int32
c.CompareTo(y); //
// CompareTo Int32,
// "2" ( String)
// String Int32
c.CompareTo("2"); //
}

,
. :
SomeMethod1 CompareTo IComparable
Object; y ( Int32)
y. SomeMethod2 CompareTo
IComparable<T> Int32; y ,
.

FCL IComparable,
ICollection, IList, IDictionary .
,
. FCL , , .NET Framework .

, .
,
, .
, IEnumerable<T>
IEnumerable. IEnumerable<T>,
IEnumerable.

343

, ,
, .
,
Object, ,
. , ,

.

,
,
. , :
using System;
// IComparable<T>
public sealed class Number: IComparable<Int32>, IComparable<String> {
private Int32 m_val = 5;
// CompareTo IComparable<Int32>
public Int32 CompareTo(Int32 n) {
return m_val.CompareTo(n);
}
// CompareTo IComparable<String>
public Int32 CompareTo(String s) {
return m_val.CompareTo(Int32.Parse(s));
}
}
public static class Program {
public static void Main() {
Number n = new Number();
// n 5 Int32
IComparable<Int32> cInt32 = n;
Int32 result = cInt32.CompareTo(5);
// n "5" String
IComparable<String> cString = n;
result = cString.CompareTo("5");
}
}


,
.
12.

344

13.


.
- .
, - .
. :
public static class SomeType {
private static void Test() {
Int32 x = 5;
Guid g = new Guid();
// M ,
// Int32 IComparable, IConvertible
M(x);
// M ,
// Guid IComparable, IConvertible
M(g);
}
// T M ,
// : IComparable IConvertible
private static Int32 M<T>(T t) where T : IComparable, IConvertible {
...
}
}

!
, . ,
, . ,
.
, , ,
( ), .
, .

. M
x ( Int32, ). x M . M t.CompareTo(...),
(
, CompareTo).

345

M , x M
:
private static Int32 M(IComparable t) {
...
}

C# IL, ,
.
C# IL-; ,
.

, ,
. ,
:
public interface IWindow {
Object GetMenu();
}
public interface IRestaurant {
Object GetMenu();
}

, .
:
// System.Object
// IWindow IRestaurant
public sealed class MarioPizzeria : IWindow, IRestaurant {
// GetMenu IWindow
Object IWindow.GetMenu() { ... }
// GetMenu IRestaurant
Object IRestaurant.GetMenu() { ... }
// GetMenu (),
//
public Object GetMenu() { ... }
}

346

13.

GetMenu,
C#, GetMenu .
, MarioPizzeria, :
MarioPizzeria mp = new MarioPizzeria();
// GetMenu MarioPizzeria
mp.GetMenu();
// IWindow.GetMenu
IWindow window = mp;
window.GetMenu();
// IRestaurant.GetMenu
IRestaurant restaurant = mp;
restaurant.GetMenu();

, . ,

. , , . -
System.Object
System.Object,
. ,
(EIMI) .
IComparable:
public interface IComparable {
Int32 CompareTo(Object other);
}

,
System.Object. ,
, :
internal struct SomeValueType : IComparable {
private Int32 m_x;
public SomeValueType(Int32 x) { m_x = x; }
public Int32 CompareTo(Object other) {

347

return(m_x _ ((SomeValueType) other).m_x);

SomeValueType, :
public static void Main() {
SomeValueType v = new SomeValueType(0);
Object o = new Object();
Int32 n = v.CompareTo(v); //
n = v.CompareTo(o); // InvalidCastException
}

:
v
CompareTo, , CompareTo
Object;
,
CompareTo other SomeValueType, InvalidCastException.
EIMI.
SomeValueType, :
internal struct SomeValueType : IComparable {
private Int32 m_x;
public SomeValueType(Int32 x) { m_x = x; }
public Int32 CompareTo(SomeValueType other) {
return(m_x _ other.m_x);
}
// : public/private
Int32 IComparable.CompareTo(Object other) {
return CompareTo((SomeValueType) other);
}
}

. -,
CompareTo. Object, SomeValueType. , , other SomeValueType, .
-, CompareTo
, SomeValueType ,
IComparable. SomeValueType
CompareTo, IComparable.
CompareTo,
.

348

13.


:
public static void Main() {
SomeValueType v = new SomeValueType(0);
Object o = new Object();
Int32 n = v.CompareTo(v); //
n = v.CompareTo(o); //
}

, :
public static void Main() {
SomeValueType v = new SomeValueType(0);
IComparable c = v; // !
Object o = new Object();
Int32 n = c.CompareTo(v); //
n = c.CompareTo(o); // InvalidCastException
}

,
CLR .
Main .
EIMI , IConvertible,
ICollection, IList IDictionary.
.



EIMI, - , . ,
EIMI .
, EIMI (, ).
( ):
, , EIMI-,
IntelliSense- Microsoft Visual Studio;
;
EIMI .

349

.NET Framework
,
. , Int32 ,
IConvertible. , , ; , ,
IConvertible Int32 . ,
.
public static void Main() {
Int32 x = 5;
Single s = x.ToSingle(null); //
// IConvertible
}

C#
( CS0117: int ToSingle):
error CS0117: 'int' does not contain a definition for 'ToSingle'

; ,
Int32 ToSingle , .
ToSingle Int32,
IConvertible:
public static void Main() {
Int32 x = 5;
Single s = ((IConvertible) x).ToSingle(null);
}

,
.
Int32 IConvertible
, . .
, , EIMI ,
.
:
internal class Base : IComparable {
// (EIMI)
Int32 IComparable.CompareTo(Object o) {
Console.WriteLine("Base's CompareTo");
return 0;
}
}
internal sealed class Derived : Base, IComparable {
// ,
public Int32 CompareTo(Object o) {

350

13.

Console.WriteLine("Derived's CompareTo");
// EIMI :
// "error CS0117: 'Base' does not contain a definition for 'CompareTo'"
base.CompareTo(o);
return 0;
}
}

CompareTo Derived base.CompareTo,


C#. , Base
CompcareTo, .
CompareTo,
IComparable. CompareTo Derived :
// ,
public Int32 CompareTo(Object o) {
Console.WriteLine("Derived's CompareTo");
// EIMI
//
IComparable c = this;
c.CompareTo(o);
}

return 0;

this c ( IComparable), c CompareTo. CompareTo


Derived CompareTo IComparable
Derived, . ,
Derived IComparable:
internal sealed class Derived : Base /*, IComparable */ { ... }

CompareTo CompareTo Base.


,
.

, .
Derived .
Base Derived:
internal class Base : IComparable {
// (EIMI)
Int32 IComparable.CompareTo(Object o) {
Console.WriteLine("Base's IComparable CompareTo");
return CompareTo(o); //
}

: ?

351

//
// ( )
public virtual Int32 CompareTo(Object o) {
Console.WriteLine("Base's virtual CompareTo");
return 0;
}
}
internal sealed class Derived : Base, IComparable {
// ,
public override Int32 CompareTo(Object o) {
Console.WriteLine("Derived's CompareTo");
// Base
return base.CompareTo(o);
}
}

: ,
. ,
.
, . EIMI,

, . !
,
, .

:
?
,
? . ,
.
. .
, ,
. . ,
(IConvertible),
(ISerializable) .. ,
System.ValueType
. .

352

13.

. , , .
,
, .
.
. ,
. , COM
COM-
Microsoft Word Microsoft Internet Explorer.
,
.
. ,
.
.

.
FCL , , . System.IO.Stream , , Read Write. (System.
IO.FileStream, System.IO.MemoryStream System.Net.Sockets.NetworkStream)
Stream. Microsoft
Stream ,
. ,
-,
Stream.
, , , : Stream
.
Windows Forms, Button, CheckBox, ListBox
System.Windows.Forms.Control, , Control;
, .
(collections), Microsoft
FCL . System.Collections.Generic
: IEnumerable<T>,
ICollection<T>, IList<T> IDictionary<TKey, TValue>. , Microsoft
(, List<T>, Dictionary<TKey,
TValue>, Queue<T>, Stack<T> .), . , -
. , List<T>, Dictionary<TKey, TValue>
Queue<T> .

: ?

353

, , .
, , . , IList<T>, ,
, , .
.
, , , . , FCL
IComparer<T>, .
, FCL Comparer<T>, ()
Compare IComparer. ,
.

III

14. , . .. .. ..356
15. . .. ..403
16. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 416
17. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..434
18. . .. .. .. .. .. .. .. .. .. ..464
19. Null- . .. .. .. .. 485

14. ,

,
Microsoft .NET Framework. System.Char
.
System.String, (
, ).
System.Text.StringBuilder.
,
.
System.Security.SecureString,
,
.

.NET Framework 16-


, . System.Char ( ). System.Char
, : MinValue,
'\0', MaxValue, '\uffff'.
Char GetUnicodeCategory,
System.Globalization.
UnicodeCategory, : ,
, , ,
.. ( ).
Char ,
: IsDigit, IsLetter, IsWhiteSpace, IsUpper, IsLower, IsPunctuation, Is
LetterOrDigit, IsControl, IsNumber, IsSeparator, IsSurrogate, IsLowSurrogate,
I s H i g h S u r r o g a t e I s S y m b o l .
GetUnicodeCategory true false.
, String
.
, ToLowerInvariant ToUpperInvariant

357

. (culture), (
, CurrentCulture System.
Globalization.CultureInfo), ToLower ToUpper.
,
CultureInfo.
ToLower ToUpper, . , U+0069 (
i) U+0130 (
I ),
U+0049 ( I).
, Char . Equals true,
Char 16- . CompareTo ( IComparable IComparable<Char>)
. ConvertFromUtf32 , UTF-16,
UTF-32. ConvertToUtf32 UTF-32
. ToString ,
, Parse TryParse
String UTF-16.
, GetNumericValue .
:
using System;
public static class Program {
public static void Main() {
Double d; //
d = Char.GetNumericValue('\u0033'); //
//
Console.WriteLine(d.ToString()); //

'\u0033' " 3"


'3'

"3"

// '\u00bc' " ('1/4')"


d = Char.GetNumericValue('\u00bc');
Console.WriteLine(d.ToString()); // "0.25"
// 'A' " A"
d = Char.GetNumericValue('A');
Console.WriteLine(d.ToString()); // "-1"
}
}

Char, .
. ,
IL- - . -

358

14. ,

Char , Int32,
. , (, C#)
, :
(. 5).
Convert. System.Convert , Char . ,

OverflowException.
IConvertible. Char
.NET Framework Class Library (FCL)
IConvertible, , ToUInt16 ToChar.
, : Char
. IConvertible System.
InvalidCastException, (, Char Boolean) . (
Char FCL) EIMI-
IConvertible (.13), , -
IConvertible.
IConvertible GetTypeCode
, IFormatProvider. ,
- .
null, .
:
using System;
public static class Program {
public static void Main() {
Char c;
Int32 n;
// " - " C#
c = (Char) 65;
Console.WriteLine(c); // "A"
n = (Int32) c;
Console.WriteLine(n); // "65"
c = unchecked((Char) (65536 + 65));
Console.WriteLine(c); // "A"
// " - " Convert

System.String

359

c = Convert.ToChar(65);
Console.WriteLine(c); // "A"
n = Convert.ToInt32(c);
Console.WriteLine(n); // "65"
// Convert
try {
c = Convert.ToChar(70000); // 16
Console.WriteLine(c); //
}
catch (OverflowException) {
Console.WriteLine("Can't convert 70000 to a Char.");
}
// " - " IConvertible
c = ((IConvertible) 65).ToChar(null);
Console.WriteLine(c); // "A"
n = ((IConvertible) c).ToInt32(null);
Console.WriteLine(n); // "65"
}
}

System.String
, System.
String, .
Object, , . String
(IComparable/IComparable<String>, ICloneable,
IConvertible, IEnumerable/IEnumerable<Char> IEquatable<String>).


( C#) String ,

. ,
.
C# new String
:
using System;
public static class Program {
public static void Main() {

360

14. ,

String s = new String("Hi there."); //


Console.WriteLine(s);
}
}

:
using System;
public static class Program {
public static void Main() {
String s = "Hi there.";
Console.WriteLine(s);
}
}

ILDasm.exe:

.method public hidebysig static void Main() cil managed


{
.entrypoint
// Code size 13 (0xd)
.maxstack 1
.locals init (string V_0)
IL_0000: ldstr "Hi there."
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(string)
IL_000c: ret
} // end of method Program::Main

IL- newobj.
. IL- ldstr
( ), String ,
. , String CLR
.
, String Char*
SByte*. new String, Char* SByte*.
String ,
Char . , , .
C# . , ,
, , C# ,
C/C++:
// String
String s = "Hi\r\nthere.";

System.String

361


, , .
System.Environment NewLine, Windows , .
NewLine ,
. , CLI UNIX NewLine ,
\n. ,
:
String s = "Hi" + Environment.NewLine + "there.";

, +
C#:
//
String s = "Hi" + " " + "there.";

, ,
"Hi there.". +
. + ,
. System.Text.
StringBuilder ( ).
, C# ,
.
(verbatim strings)
.
,
(@) :
//
String file = "C:\\Windows\\System32\\Notepad.exe";
//
String file = @"C:\Windows\System32\Notepad.exe";

. @ ,
(\) ,
,
.
, , , String.

362

14. ,


, String , ;
, . .
, :
if (s.ToUpperInvariant().Substring(10, 21).EndsWith("EXE")) {
...
}

ToUpperInvariant ; s
. SubString , ToUpperInvariant,
, EndsWith .
,
ToUpperInvariant SubString,
. ,
String , .

. , CLR String
, , .
, , (string
interning), .
String CLR.
, CLR
.
: String . , , String,
, String CLR.
, CLR String,
.


, .
, .
, , ( ,
).

,
String:
Boolean Equals(String value, StringComparison comparisonType)
static Boolean Equals(String a, String b, StringComparison comparisonType)

System.String

363

static Int32 Compare(String strA, String strB,


StringComparison comparisonType)
static Int32 Compare(string strA, string strB,
Boolean ignoreCase, CultureInfo culture)
static Int32 Compare(String strA, String strB,
CultureInfo culture, CompareOptions options)
static Int32 Compare(String strA, Int32 indexA, String strB, Int32 indexB,
Int32 length, StringComparison comparisonType)
static Int32 Compare(String strA, Int32 indexA, String strB, Int32 indexB,
Int32 length, CultureInfo culture, CompareOptions options)
static Int32 Compare(String strA, Int32 indexA, String strB, Int32 indexB,
Int32 length, Boolean ignoreCase, CultureInfo culture)
Boolean StartsWith(String value, StringComparison comparisonType)
Boolean StartsWith(String value,
Boolean ignoreCase, CultureInfo culture)
Boolean EndsWith(String value, StringComparison comparisonType)
Boolean EndsWith(String value, Boolean ignoreCase, CultureInfo culture)

. ,
, ,

, .
comparisonType ( )
, StringComparison,
:
public enum StringComparison {
CurrentCulture = 0,
CurrentCultureIgnoreCase = 1,
InvariantCulture = 2,
InvariantCultureIgnoreCase = 3,
Ordinal = 4,
OrdinalIgnoreCase = 5
}

options ,
CompareOptions:
[Flags]
public enum CompareOptions {
None = 0,
IgnoreCase = 1,
IgnoreNonSpace = 2,
IgnoreSymbols = 4,
IgnoreKanaType = 8,
IgnoreWidth = 0x00000010,
Ordinal = 0x40000000,
OrdinalIgnoreCase = 0x10000000,
StringSort = 0x20000000
}

364

14. ,

, CompareOptions,
.
Ordinal OrdinalIgnoreCase, Compare
.
:
, URL-, ,
, , XML-, XML- .. , .
StringComparison.
Ordinal StringComparison.OrdinalIgnoreCase.
,
.
,
( ), StringComparison.CurrentCulture
StringComparison.CurrentCultureIgnoreCase.

StringComparison.InvariantCulture
StringComparison.InvariantCultureIgnoreCase. ,
, StringComparison.Ordinal
StringComparison.OrdinalIgnoreCase. ,
,
.


, String ToUpperInvariant
ToLowerInvariant. ToUpperInvariant, ToLowerInvariant - , Microsoft
. , FCL

.

, .

StartsWith, EndsWith Compare Boolean
CultureInfo.
. - ( RFC 1766) .NET Framework
System.Globalization.CultureInfo. , en-US -

System.String

365

() , en-AU
, de-DE . CLR
,
CultureInfo.
CurrentUICulture , . Web Forms, ,
,
.
Win32- GetUserDefaultUILanguage
CultureInfo, Windows. MUI (Multilingual User Interface) Windows
Regional and Language Options (
) .

String Equals, StartsWith,


EndsWith Compare , . Microsoft
( ). , String CompareTo (
IComparable), CompareOrdinal == !=. ,
, ,
, . , CompareTo
, Equals . ,
, .

CurrentCulture ,
CurrentUICulture, , .
CultureInfo .
Win32- GetUserDefaultLCID
CultureInfo. Regional Options
( ) Regional and Language Options ( ) .
,
,
DefaultThreadCurrentCulture DefaultThreadCurrentUICulture CultureInfo.
CurrentUICulture CurrentCulture
CultureInfo,
. . , ,

366

14. ,

, , .
CurrentUICulture CultureInfo, es (), CurrentCulture CultureInfo,
en-US.
CultureInfo System.
Globalization.CompareInfo,
. :
using System;
using System.Globalization;
public static class Program {
public static void Main() {
String s1 = "Strasse";
String s2 = "Strae";
Boolean eq;
// CompareOrdinal
eq = String.Compare(s1, s2, StringComparison.Ordinal) == 0;
Console.WriteLine("Ordinal comparison: '{0}' {2} '{1}'", s1, s2,
eq ? "==" : "!=");
// (de) (DE)
CultureInfo ci = new CultureInfo("de-DE");
// Compare
eq = String.Compare(s1, s2, true, ci) == 0;
Console.WriteLine("Cultural comparison: '{0}' {2} '{1}'", s1, s2,
eq ? "==" : "!=");
}
}

:
Ordinal comparison: 'Strasse' != 'Strae'
Cultural comparison: 'Strasse' == 'Strae'

Compare ,
(character expansions),
, .
ss. AE. Compare
0 .

. ,

System.String

367

. CompareInfo CultureInfo. ,
CompareInfo
,
CompareInfo.
Compare String . ,
CurrentCulture . , Compare, CompareInfo
Compare CompareInfo, (,
). , ,
Compare CompareInfo.
Compare CompareInfo
CompareOptions. .
.NET Framework.

:
using
using
using
using
using

System;
System.Text;
System.Windows.Forms;
System.Globalization;
System.Threading;

public sealed class Program {


public static void Main() {
String output = String.Empty;
String[] symbol = new String[] { "<", "=", ">" };
Int32 x;
CultureInfo ci;
// ,
//
String s1 = "cot";
String s2 = "cte";
// ()
ci = new CultureInfo("fr-FR");
x = Math.Sign(ci.CompareInfo.Compare(s1, s2));
output += String.Format("{0} Compare: {1} {3} {2}",
ci.Name, s1, s2, symbol[x + 1]);
output += Environment.NewLine;
// ()
ci = new CultureInfo("ja-JP");
x = Math.Sign(ci.CompareInfo.Compare(s1, s2));

368

14. ,

output += String.Format("{0} Compare: {1} {3} {2}",


ci.Name, s1, s2, symbol[x + 1]);
output += Environment.NewLine;
//
ci = Thread.CurrentThread.CurrentCulture;
x = Math.Sign(ci.CompareInfo.Compare(s1, s2));
output += String.Format("{0} Compare: {1} {3} {2}",
ci.Name, s1, s2, symbol[x + 1]);
output += Environment.NewLine + Environment.NewLine;
//
//
//
//
//
//
s1
s2


CompareInfo.Compare

"shinkansen" (
) :

= " "; // ("\u3057\u3093\u304b\u3093\u305b\u3093")
= " "; // ("\u30b7\u30f3\u30ab\u30f3\u30bb\u30f3")

//
ci = new CultureInfo("ja-JP");
x = Math.Sign(String.Compare(s1, s2, true, ci));
output += String.Format("Simple {0} Compare: {1} {3} {2}",
ci.Name, s1, s2, symbol[x + 1]);
output += Environment.NewLine;
// ,
CompareInfo compareInfo = CompareInfo.GetCompareInfo("ja-JP");
x = Math.Sign(compareInfo.Compare(s1, s2,
CompareOptions.IgnoreKanaType));
output += String.Format("Advanced {0} Compare: {1} {3} {2}",
ci.Name, s1, s2, symbol[x + 1]);
MessageBox.Show(output, "Comparing Strings For Sorting");
}
}

ANSI,
.
Microsoft Visual Studio, Save File As, Save With Encoding.
(UTF-8 with signature) Codepage 65001. C#
, .

,
.14.1.

System.String

369

. 14.1.

Compare, CompareInfo IndexOf, IsLastIndexOf,


IsPrefix IsSuffix. -

,
CompareOptions,
Compare, IndexOf, LastIndexOf, StartsWith EndsWith String.
, , FCL System.StringComparer,
.
,
.


, ,
.
(ordinal comparison) CLR , . ,
, .
CLR ,
.

. , ,
.

, CLR (string interning).
CLR -,
,
. , , . String , -:
public static String Intern(String str);
public static String IsInterned(String str);

370

14. ,

, Intern, String -.
, String.
, -, . String, ,
. , ,
-,
String. String, -,
,
.
Intern , IsInterned String
-. , IsInterned
. null,
-.
CLR ,
. ,
- -,
Microsoft . System.Runtime.CompilerServices.CompilationRelaxations
Attribute, System.Runtime.CompilerServices.
CompilationRelaxations.NoStringInterning,
ECMA CLR , . ,
C#
/.
/, CLR
, .
, ,
Intern String.
:
String s1 = "Hello";
String s2 = "Hello";
Console.WriteLine(Object.ReferenceEquals(s1, s2)); // 'False'
s1 = String.Intern(s1);
s2 = String.Intern(s2);
Console.WriteLine(Object.ReferenceEquals(s1, s2)); // 'True'

ReferenceEquals s1 - "Hello" , s2 - "Hello".


, False. CLR
4.5, True. , CLR /, C#,
"Hello" . , s1 s2

System.String

371

. , ,
,
/ , "Hello"
. , CLR 4.5 /,
NGen.exe.
ReferenceEquals "Hello" , s1 "Hello".
Intern s2 "Hello", s1. ReferenceEquals
True ,
/.
, .
NumTimesWordAppearsEquals : ,
. ,
, :
private static Int32 NumTimesWordAppearsEquals(String word, String[]
wordlist) {
Int32 count = 0;
for (Int32 wordnum = 0; wordnum < wordlist.Length; wordnum++) {
if (word.Equals(wordlist[wordnum], StringComparison.Ordinal))
count++;
}
return count;
}

, Equals String,
, .
. , wordlist
, String, . ,
, .
, :
private static Int32 NumTimesWordAppearsIntern(String word, String[]
wordlist) {
// , wordlist
//
word = String.Intern(word);
Int32 count = 0;
for (Int32 wordnum = 0; wordnum < wordlist.Length; wordnum++) {
if (Object.ReferenceEquals(word, wordlist[wordnum]))
count++;
}
return count;
}

372

14. ,

, wordlist
. -, ,
, wordlist String . -,
, , ,
.
NumTimesWordAppearsIntern , NumTimes
WordAppearsEquals ,
, NumTimesWordAppearsIntern - ,
wordlist ( ).
NumTimesWordAppearsIntern , ,
wordlist. ,
, .
, C# ,
.



.
,
.
, ( C#)
.

. .
Microsoft C/C++
(string pooling). ,
. , .


,
.
String,
Length, Chars ( C#), GetEnumerator, ToCharArray, Contains, IndexOf,
LastIndexOf, IndexOfAny LastIndexOfAny.
System.Char 16-
, . , Unicode-
. , U+0625 (

System.String

373

) U+0650 ( ) , .
, ,
16- . (high surrogate),
(low surrogate).
U+D800 U+DBFF, U+DC00 U+DFFF.
Unicode
.
- .
System.Globalization.StringInfo.
,
. , , LengthInTextElements StringInfo.
SubstringByTextElements StringInfo,
.
, StringInfo GetTextElementEnumerator,
System.Globalization.TextElementEnumerator, ,
, .
, ParseCombiningCharacters
StringInfo, Int32,
.
.

StringInfo :
using
using
using
using

System;
System.Text;
System.Globalization;
System.Windows.Forms;

public sealed class Program {


public static void Main() {
//
String s = "a\u0304\u0308bc\u0327";
SubstringByTextElements(s);
EnumTextElements(s);
EnumTextElementIndexes(s);
}
private static void SubstringByTextElements(String s) {
String output = String.Empty;
StringInfo si = new StringInfo(s);
for (Int32 element = 0; element < si.LengthInTextElements; element++) {
output += String.Format(

374

14. ,

"Text element {0} is '{1}'{2}",


element, si.SubstringByTextElements(element, 1),
Environment.NewLine);
}
MessageBox.Show(output, "Result of SubstringByTextElements");
}
private static void EnumTextElements(String s) {
String output = String.Empty;
TextElementEnumerator charEnum =
StringInfo.GetTextElementEnumerator(s);
while (charEnum.MoveNext()) {
output += String.Format(
"Character at index {0} is '{1}'{2}",
charEnum.ElementIndex, charEnum.GetTextElement(),
Environment.NewLine);
}
MessageBox.Show(output, "Result of GetTextElementEnumerator");
}
private static void EnumTextElementIndexes(String s) {
String output = String.Empty;
Int32[] textElemIndex = StringInfo.ParseCombiningCharacters(s);
for (Int32 i = 0; i < textElemIndex.Length; i++) {
output += String.Format(
"Character {0} starts at index {1}{2}",
i, textElemIndex[i], Environment.NewLine);
}
MessageBox.Show(output, "Result of ParseCombiningCharacters");
}
}

(.14.214.4).

. 14.2.

SubstringByTextElements

. 14.3.

GetTextElementEnumerator

. 14.4.

ParseCombiningCharacters

375


. 14.1 String,
.
14.1.

Clone

(this).
, String .
ICloneable String

Copy

. , .
. , ,

(),

CopyTo

Substring

ToString

(this)

, String
: Insert, Remove, PadLeft, Replace,
Split, Join, ToLower, ToUpper, Trim, Concat, Format . ,
; , ( ).


String ,
String FCL System.
Text.StringBuilder. String. ,
String, StringBuilder,
, , .
StringBuilder
Char. StringBuilder,

376

14. ,

, . ,
, StringBuilder , ,
. .
StringBuilder,
StringBuilder String, ToString
StringBuilder. -,
StringBuilder. ,
. String, ToString,
. , , , StringBuilder, ,
, ToString, ,
, ToString.

StringBuilder
String, StringBuilder CLR
. , ( C#)
StringBuilder . StringBuilder ,
:
StringBuilder sb = new StringBuilder();

StringBuilder . ,
StringBuilder.
(maximum capacity) Int32,
, .
Int32.MaxValue ( ). ,
,
. StringBuilder .
(capacity) Int32,
StringBuilder. 16. ,
StringBuilder,
StringBuilder. StringBuilder ,
. ,
StringBuilder , ,
, . .
,
, .

377

(character array) Char, . ( )


.
Length StringBuilder. Length
StringBuilder. StringBuilder
, String . ,
Length 0.

StringBuilder
StringBuilder String . , StringBuilder ,
, . StringBuilder
:
, ;
ToString StringBuilder.
. 14.2 StringBuilder.
14.2. StringBuilder

MaxCapacity

Capacity

/
.
, , ,
MaxCapacity,
ArgumentOutOfRangeException

EnsureCapacity

,
, ,
.
StringBuilder,
. ,
, ,

Length

.

. 0
StringBuilder

378

14. ,

14.2 ()

ToString

String,

StringBuilder

Chars

. C# ( ),
( [])

Clear

StringBuilder, Length 0

Append

,
. ,

Insert

,
. ,

AppendFormat

,
.
.

StringBuilder

AppendLine

Replace

Remove

Equals

true, StringBuilder
,

CopyTo

StringBuilder
Char

: StringBuilder
StringBuilder.
:

379

StringBuilder sb = new StringBuilder();


String s = sb.AppendFormat("{0} {1}", "Jeffrey", "Richter").
Replace(' ', '-').Remove(4, 3).ToString();
Console.WriteLine(s); // "Jeff-Richter"

StringBuilder String.
, String ToLower, ToUpper, EndsWith, PadLeft, Trim
.., StringBuilder. StringBuilder
Replace,
( ). -
String
StringBuilder. , , ,
:
// StringBuilder
StringBuilder sb = new StringBuilder();
// , StringBuilder
sb.AppendFormat("{0} {1}" "Jeffrey", "Richter").Replace(" ", "-");
// StringBuilder String,
//
String s = sb.ToString().ToUpper();
// StringBuilder ( Char)
sb.Length = 0;
// String StringBuilder
//
sb.Append(s).Insert(8, "Marc-");
// StringBuilder String
s = sb.ToString();
// String
Console.WriteLine(s); // "JEFFREY-Marc-RICHTER"

- , StringBuilder
, String. ,
Microsoft StringBuilder,
.

, , (, Byte, Int32, Single ..) DateTime.

380

14. ,

.NET Framework - ,
,
. , FCL ,
. .

ToString.
System.Object, . ToString ,
,
. , ,
, ,
.
ToString System.Object
. ,
. , , FileStream Hashtable?
, , ToString . ,
FCL (Byte, Int32, UInt64, Double ..),
ToString,
. Visual Studio .
ToString . ,
ToString,
.


ToString . -,
, , , , ,
. -,
, . ,
.
, .
ToString,
.
, System.IFormattable:
public interface IFormattable {
String ToString(String format, IFormatProvider formatProvider);
}

381

FCL (Byte, SByte, Int16/UInt16, Int32/UInt32, Int64/


UInt64, Single, Double, Decimal DateTime) . , , GUID.
IFormattable,

, .
ToString IFormattable . ,
format, , . , formatProvider, , System.
IFormatProvider. ToString . .
, ToString IFormattable, .
, System.FormatException.
FCL . , DateTime
: "d" , "D"
, "g" , "M" /, "s"
, "T" , "u" ISO 8601,
"U" , "Y" / ..
: "G" , "F"
, "D" "X" .
.15.
, :
"C" , "D" , "E" () , "F" , "G" ,
"N" , "P" , "R" (round-trip)
"X" .
, .
,
ToString ,
, ..
. .NET Framework SDK,
.
null,
ToString "G". , ,
. , , , , ;
. , ToString
.
, .
,
. ToString ToString IFormattable null
formatProvider.

382

14. ,

(
, , ), .
ToString Guid, GUID, , GUID.
, .
T o S t r i n g
formatProvider. null, ToString , , System.Threading.
Thread.CurrentThread.CurrentCulture. System.
Globalization.CultureInfo.
, ToString NumberFormat DateTimeFormat .
System.Globalization.NumberFormatInfo System.
Globalization.DateTimeFormatInfo . NumberFormatInfo , CurrencyDecimalSeparator, CurrencySymbol,
NegativeSign, NumberGroupSeparator PercentSymbol. , DateTimeFormatInfo , Calendar, DateSeparator, DayNames,
LongDatePattern, ShortTimePattern TimeSeparator. ToString
.
ToString IFormattable null , IFormatProvider:
public interface IFormatProvider {
Object GetFormat(Type formatType);
}

IFormatProvider :
, , , ,
, .
System.Globalization.CultureInfo
FCL , IFormatProvider.
, , , CultureInfo
ToString formatProvider. Decimal :
Decimal price = 123.54M;
String s = price.ToString("C", new CultureInfo("vi-VN"));
MessageBox.Show(s);

, (.14.5).
ToString Decimal, , formatProvider
null, GetFormat :
NumberFormatInfo nfi = (NumberFormatInfo)
formatProvider.GetFormat(typeof(NumberFormatInfo));

383

. 14.5.

ToString (CultureInfo) . ( Decimal)


. ( DateTime)
GetFormat :
DateTimeFormatInfo dtfi = (DateTimeFormatInfo)
formatProvider.GetFormat(typeof(DateTimeFormatInfo));

GetFormat ,
, . .NET
Framework GetFormat
/; .
, , ,
InvariantCulture System.Globalization.CultureInfo
formatProvider ToString:
Decimal price = 123.54M;
String s = price.ToString("C", CultureInfo.InvariantCulture);
MessageBox.Show(s);


(.14.6). : . (U+00A4).

. 14.6. , .

384

14. ,

. ,
.
FCL IFormatProvider :
CultureInfo , NumberFormatInfo
DateTimeFormatInfo. GetFormat NumberFormatInfo,
, NumberFormatInfo. , this, null. GetFormat
DateTimeFormatInfo this, DateTimeFormatInfo,
null .
. ,
, .
ToString, null formatProvider.
ToString
ToString. , Decimal
ToString:
// ToString(null, null)
// : ,
public override String ToString();
// ToString
// ToString IFormattable
// : ,
public String ToString(String format, IFormatProvider formatProvider);
// ToString(format, null)
// : , ,
//
public String ToString(String format);
// ToString(null, formatProvider)
// ToString IConvertible
// : ,
//
public String ToString(IFormatProvider formatProvider);


, .
.
, :
String s = String.Format("On {0}, {1} is {2} years old.",
new DateTime(2012, 4, 22, 14, 35, 5), "Aidan", 9);
Console.WriteLine(s);

385

en-US,
:
On 4/22/2012 2:35:05 PM, Aidan is 9 years old.

Format String ,

. Format {0} (
), {1} (Aidan) {2} ,
(9).
Format ToString, . , . ,
,
.
,
. ,
0 2:
String s = String.Format("On {0:D}, {1} is {2:E} years old.",
new DateTime(2012, 4, 22, 14, 35, 5), "Aidan", 9);
Console.WriteLine(s);

en-US,
:
On Sunday, April 22, 2012, Aidan is 9.000000E+000 years old.

, Format , 0 IFormattable
ToString, D null. , Format ToString IFormattable 2,
E null. IFormattable,
Format ToString ,
.
String
Format. , IFormatProvider,
, . ,
Format ToString ,
IFormatProvider.
String StringBuilder,
AppendFormat StringBuilder . , Format String , ,
StringBuilder.

386

14. ,

AppendFormat ,
IFormatProvider.
System.Console Write WriteLine,
. Console Write WriteLine, IFormatProvider.

, Format String,
IFormatProvider, Write
WriteLine Console. , ,
, , , .


, .NET Framework
. ,
AppendFormat StringBuilder ,
. ,
ToString AppendFormat , , .
Format String.
. ,
HTML-,
, Int32 .
, Int32 String,
: <B> </B>.
, :
using System;
using System.Text;
using System.Threading;
public static class Program {
public static void Main() {
StringBuilder sb = new StringBuilder();
sb.AppendFormat(new BoldInt32s(), "{0} {1} {2:M}", "Jeff", 123,
DateTime.Now);
Console.WriteLine(sb);
}
}
internal sealed class BoldInt32s : IFormatProvider, ICustomFormatter {
public Object GetFormat(Type formatType) {
if (formatType == typeof(ICustomFormatter)) return this;
return Thread.CurrentThread.CurrentCulture.GetFormat(formatType);
}
public String Format(String format, Object arg, IFormatProvider

387

formatProvider) {
String s;
IFormattable formattable = arg as IFormattable;
if (formattable == null) s = arg.ToString();
else s = formattable.ToString(format, formatProvider);

if (arg.GetType() == typeof(Int32))
return "<B>" + s + "</B>";
return s;

en-US
( ):
Jeff <B>123</B> September 1

Main StringBuilder ,
. AppendFormat
BoldInt32s. ,
IFormatProvider,
ICustomFormatter:
public interface ICustomFormatter {
String Format(String format, Object arg,
IFormatProvider formatProvider);
}

Format , AppendFormat StringBuilder .

. AppendFormat, ,
. AppendFormat:
public StringBuilder AppendFormat(IFormatProvider formatProvider,
String format, params Object[] args) {
// IFormatProvider , ,
// ICustomFormatter
ICustomFormatter cf = null;
if (formatProvider != null)
cf = (ICustomFormatter)
formatProvider.GetFormat(typeof(ICustomFormatter));
// (
// )
// StringBuilder.
Boolean MoreReplaceableArgumentsToAppend = true;
while (MoreReplaceableArgumentsToAppend) {

388

14. ,

// argFormat ,
// format
String argFormat = /* ... */;
// argObj
// - args
Object argObj = /* ... */;
// argStr ,
//
String argStr = null;
// ,
//
if (cf != null)
argStr = cf.Format(argFormat, argObj, formatProvider);
//
// , -
if (argStr == null) {
// ,
//
IFormattable formattable = argObj as IFormattable;
if (formattable != null) {
// ;
// -
argStr = formattable.ToString(argFormat, formatProvider);
} else {
// ;
//
if (argObj != null) argStr = argObj.ToString();
else argStr = String.Empty;
}
}
// argStr ( - )
/* ... */
// , ,
MoreReplaceableArgumentsToAppend = /* ... */;
}
return this;
}

Main AppendFormat, GetFormat


, ICustomFormatter. GetFormat,
BoldInt32s, , ICustomFormatter,
, . GetFormat - ,
GetFormat CultureInfo, .
AppendFormat Format ICustomFormatter.

389

Format, BoldInt32s. Format ,


IFormattable. ,
ToString ( Object);
ToString, .
, , , Int32,
, HTML- <B> </B>, . Int32, .


. : ,
.
, . Microsoft ,
.
, , ,
Parse. String, ; Parse . FCL Parse
, DateTime, TimeSpan
(, SQL).
, .
(Byte, SByte, Int16/UInt16, Int32/UInt32, Int64/UInt64, Single, Double, Decimal
BigInteger) Parse. Parse
Int32 ( Parse ).
public static Int32 Parse(String s, NumberStyles style, IFormatProvider
provider);

, . s
String , Int32. style System.
Globalization.NumberStyles
, Parse . provider
IFormatProvider , Parse
, .
, Parse
System.FormatException, :
Int32 x = Int32.Parse(" 123", NumberStyles.None, null);

390

14. ,

, Parse style:
Int32 x = Int32.Parse(" 123", NumberStyles.AllowLeadingWhite, null);

NumberStyles, . .NET Framework SDK.

Int32 x = Int32.Parse("1A", NumberStyles.HexNumber, null);


Console.WriteLine(x); // "26".

Parse .
Parse . ,
Int32 Parse:
// NumberStyles.Integer
//
public static Int32 Parse(String s);
//
public static Int32 Parse(String s, NumberStyles style);
// NumberStyles.Integer
public static Int32 Parse(String s, IFormatProvider provider)
// ,
public static int Parse(String s, NumberStyles style,
IFormatProvider provider);

DateTime Parse:
public static DateTime Parse(String s,
IFormatProvider provider, DateTimeStyles styles);

Parse
, Parse DateTime , System.Globalization.DateTimeStyles,
NumberStyles. ,
DateTimeStyles, . .NET Framework SDK.
DateTime Parse:
// ,
// DateTimeStyles.None
public static DateTime Parse(String s);
// DateTimeStyles.None
public static DateTime Parse(String s, IFormatProvider provider);
//
public static DateTime Parse(String s,
IFormatProvider provider, DateTimeStyles styles);

391

.
, Parse DateTime
, , . DateTime
ParseExact, , , , ,
. . , DateTimeFormatInfo,
.NET Framework SDK.

Microsoft : Parse (- ,
),
. Microsoft
TryParse , DateTime, TimeSpan
IPAddress. TryParse
Int32:
public static Boolean TryParse(String s, NumberStyles style,
IFormatProvider provider, out Int32 result);

, true false, ,
Int32. true, ,
,
. TryXxx 20.

:

Win32- ,
Unicode Multi-Byte Character Set (MBCS).
, ,
. CLR 16- ,
16- . .
.
,
16- ,
. (encode) 16-
, (decode)
16- .

, , . ,

392

14. ,

, Windows95, , Shift-JIS ( 932).


Shift-JIS CLR ,
Windows95.

System.IO.BinaryWriter System.IO.StreamWriter. System.IO.BinaryReader System.IO.StreamReader.
, UTF-8 (UTF
Unicode Transformation Format).
.
, FCL , . UTF-16 UTF-8.
UTF-16 16- 2 .
, , . UTF-16 - (Unicode encoding).
, , UTF-16,
(big endian) (little endian), .
UTF-8 , , , . 0x0080,
,
. 0x0080 0x07FF,
, 2 . , 0x0800
, , 3 .
, - (surrogate character pairs) 4 . UTF-8 ,
UTF-16,
0x0800 .
UTF-16 UTF-8, FCL .
UTF-32 4 . ,
, . , UTF-32
-,
4 . , UTF-32
,
, . , UTF-32
, .
UTF-7 , 7. ,

393

, . Unicode Consortium
UTF-7.
ASCII 16- ASCII-; 16 0x0080 .
0x007F , . , ASCII- (
0x00 0x7F), ,
( ).
ASCII-, .
, FCL 16-
. ASCII, , . UTF-16 UTF-8 ,
, - .
,
, System.Text.Encoding. Encoding ,
, Encoding.

UTF-8:
using System;
using System.Text;
public static class Program {
public static void Main() {
//
String s = "Hi there.";
// , Encoding, ""
// UTF-8
Encoding encodingUTF8 = Encoding.UTF8;
//
Byte[] encodedBytes = encodingUTF8.GetBytes(s);
//
Console.WriteLine("Encoded bytes: " +
BitConverter.ToString(encodedBytes));
//
String decodedString = encodingUTF8.GetString(encodedBytes);
//
Console.WriteLine("Decoded string: " + decodedString);
}
}

394

14. ,

:
Encoded bytes: 48-69-20-74-68-65-72-65-2E
Decoded string: Hi there.

UTF8, Encoding : Unicode,


BigEndianUnicode, UTF32, UTF7, ASCII Default. ,


, Regional and Language Options (
) (. Win32-
GetACP). Default , ,
, ,
.
, Encoding
GetEncoding, ( ).
GetEncoding , /,
. , GetEncoding
"Shift-JIS" 932.
Encoding (
GetEncoding) .

; .
.
GetEncoding Encoding, System.Text.
UnicodeEncoding, System.Text.UTF8Encoding, System.Text.UTF32Encoding, System.
Text.UTF7Encoding System.Text.ASCIIEncoding. ,
,
.
UnicodeEncoding, UTF8Encoding, UTF32Encoding UTF7Encoding
, (Byte Order
Mark, BOM). ,
;
.
, BinaryWriter StreamWriter . ASCIIEncoding ,
. ASCIIEncoding (, )
ASCII Encoding.
ASCIIEncoding , .

395

, Encoding, GetBytes, . ( .) GetChars


GetString. (
.) GetBytes GetString
.
, Encoding, GetByteCount, ,
, ,
. . GetCharCount,
,
. ,
.
GetByteCount GetCharCount ,
/.
, GetMaxByteCount GetMaxCharCount
,
, .
, Encoding, , .
. .NET Framework SDK.
, ,
:
using System;
using System.Text;
public static class Program {
public static void Main() {
foreach (EncodingInfo ei in Encoding.GetEncodings()) {
Encoding e = ei.GetEncoding();
Console.WriteLine("{1}{0}" +
"\tCodePage={2}, WindowsCodePage={3}{0}" +
"\tWebName={4}, HeaderName={5}, BodyName={6}{0}" +
"\tIsBrowserDisplay={7}, IsBrowserSave={8}{0}" +
"\tIsMailNewsDisplay={9}, IsMailNewsSave={10}{0}",
Environment.NewLine,
e.EncodingName, e.CodePage, e.WindowsCodePage,
e.WebName, e.HeaderName, e.BodyName,
e.IsBrowserDisplay, e.IsBrowserSave,
e.IsMailNewsDisplay, e.IsMailNewsSave);
}
}
}

( ):

396

14. ,

IBM EBCDIC (US-Canada)


CodePage=37, WindowsCodePage=1252
WebName=IBM037, HeaderName=IBM037, BodyName=IBM037
IsBrowserDisplay=False, IsBrowserSave=False
IsMailNewsDisplay=False, IsMailNewsSave=False
OEM United States
CodePage=437, WindowsCodePage=1252
WebName=IBM437, HeaderName=IBM437, BodyName=IBM437
IsBrowserDisplay=False, IsBrowserSave=False
IsMailNewsDisplay=False, IsMailNewsSave=False
IBM EBCDIC (International)
CodePage=500, WindowsCodePage=1252
WebName=IBM500, HeaderName=IBM500, BodyName=IBM500
IsBrowserDisplay=False, IsBrowserSave=False
IsMailNewsDisplay=False, IsMailNewsSave=False
Arabic (ASMO 708)
CodePage=708, WindowsCodePage=1256
WebName=ASMO-708, HeaderName=ASMO-708, BodyName=ASMO-708
IsBrowserDisplay=True, IsBrowserSave=True
IsMailNewsDisplay=False, IsMailNewsSave=False
Unicode
CodePage=1200, WindowsCodePage=1200
WebName=utf-16, HeaderName=utf-16, BodyName=utf-16
IsBrowserDisplay=False, IsBrowserSave=True
IsMailNewsDisplay=False, IsMailNewsSave=False
Unicode (Big-Endian)
CodePage=1201, WindowsCodePage=1200
WebName=unicodeFFFE, HeaderName=unicodeFFFE, BodyName=unicodeFFFE
IsBrowserDisplay=False, IsBrowserSave=False
IsMailNewsDisplay=False, IsMailNewsSave=False
Western European (DOS)
CodePage=850, WindowsCodePage=1252
WebName=ibm850, HeaderName=ibm850, BodyName=ibm850
IsBrowserDisplay=False, IsBrowserSave=False
IsMailNewsDisplay=False, IsMailNewsSave=False
Unicode (UTF-8)
CodePage=65001, WindowsCodePage=1200
WebName=utf-8, HeaderName=utf-8, BodyName=utf-8
IsBrowserDisplay=True, IsBrowserSave=True
IsMailNewsDisplay=True, IsMailNewsSave=True

, Encoding, .14.3.

397

14.3. , Encoding

GetPreamble

, , .
BOM- (byte order mark) (preamble).
, BOM- , . , Encoding,
0 , . UTF8Encoding ,
3 : 0xEF, 0xBB, 0xBF.
UnicodeEncoding , : 0xFE, 0xFF (big endian) 0xFF, 0xFE (little endian).
.

Convert

.
GetChars
GetBytes
.

Equals

true, Encoding

GetHashCode

, UTF-16 System.Net.Sockets.NetworkStream. ,
, 5, 7.
UTF-16 .
GetString Encoding 5
, . GetString
7, GetString , ,
!
,
Encoding
. ,
,
, .

398

14. ,

,
Encoding ( )
GetDecoder.
, System.Text.Decoder. Decoder,
Encoding, . .NET Framework
SDK ,
Decoder, FCL Decoder .
FCL, GetDecoder
.
Decoder : GetChars
GetCharCount. ,
GetChars GetCharCount
Encoding. , ,
.
, .


, , .
Decoder .
, Encoding, /
. , Decoder, . , GetDecoder Encoding GetEncoder.
,
System.Text.Encoder. , .NET Framework SDK
,
Encoder, FCL Encoder .
, Decoder, FCL,
GetEncoder
.
, Encoder, : GetBytes GetByteCount.
, Encoder,
, .

Base-64
UTF-16 UTF-8 .
base-64. FCL
base-64. , ,
Encoding, -
base-64 ,
System.Convert.

399

base-64 ,
FromBase64String FromBase64CharArray Convert.
base-64
ToBase64String ToBase64CharArray Convert.
:
using System;
public static class Program {
public static void Main() {
// 10 ,
Byte[] bytes = new Byte[10];
new Random().NextBytes(bytes);
//
Console.WriteLine(BitConverter.ToString(bytes));
// base-64
String s = Convert.ToBase64String(bytes);
Console.WriteLine(s);
// base-64
bytes = Convert.FromBase64String(s);
Console.WriteLine(BitConverter.ToString(bytes));
}
}

( ,
):
3B-B9-27-40-59-35-86-54-5F-F1
O7knQFk1hlRf8Q==
3B-B9-27-40-59-35-86-54-5F-F1


String ,
. , String ,
, ,
. String
, CLR
( String ),
, .
, ,

400

14. ,

,
.

, .
Microsoft FCL System.
Security.SecureString. SecureString
, .
.

.
, ,
AppendChar, InsertAt, RemoveAt SetAt.
,
. , . ,
, ,
, .
SecureString IDisposable,
, . ,
Dispose SecureString
SecureString using. Dispose , ,
. SecureString
, SafeBuffer, .
SafeBuffer CriticalFinalizerObject (.21), Finalize
SecureString, .
String, SecureString
.
, , SecureString,
. , FCL SecureString , ,
SecureString, . 4 .NET Framework SecureString :
(Cryptographic Service Provider,
CSP) . System.Security.Cryptography.CspParameters;
, X.509 .
System.Security.Cryptography.X509Certificates.X509Certificate System.
Security.Cryptography.X509Certificates.X509Certificate2;
.
System.Diagnostics.Process System.Diagnostics.ProcessStartInfo;

401

. System.
Diagnostics.Eventing.Reader.EventLogSession;
System.Windows.Controls.PasswordBox
. SecurePassword.
, ,
SecureString. SecureString
, ,
.
, .
.
SecureString String
,
. SecureString ToString
( String).
Secure
String ( /unsafe C#):
using System;
using System.Security;
using System.Runtime.InteropServices;
public static class Program {
public static void Main() {
using (SecureString ss = new SecureString()) {
Console.Write("Please enter password: ");
while (true) {
ConsoleKeyInfo cki = Console.ReadKey(true);
if (cki.Key == ConsoleKey.Enter) break;
// SecureString
ss.AppendChar(cki.KeyChar);
Console.Write("*");
}
Console.WriteLine();
// ,
DisplaySecureString(ss);
}
// 'using' SecureString Disposed,
//
}
// ,
private unsafe static void DisplaySecureString(SecureString ss) {
Char* pc = null;
try {
// SecureString

402

14. ,
pc = (Char*) Marshal.SecureStringToCoTaskMemUnicode(ss);

// ,
// SecureString
for (Int32 index = 0; pc[index] != 0; index++)
Console.Write(pc[index]);
}
finally {
// ,
// SecureString
if (pc != null)
Marshal.ZeroFreeCoTaskMemUnicode((IntPtr) pc);
}
}
}

System.Runtime.InteropServices.Marshal 5 ,
SecureString
. , SecureString, IntPtr. ,
. .14.4 System.Runtime.InteropServices.Marshal,
SecureString ,
.
14.4. Marshal
SecureString

SecureStringToBSTR

ZeroFreeBSTR

SecureStringToCoTaskMemAnsi

ZeroFreeCoTaskMemAnsi

SecureStringToCoTaskMemUnicode

ZeroFreeCoTaskMemUnicode

SecureStringToGlobalAllocAnsi

ZeroFreeGlobalAllocAnsi

SecureStringToGlobalAllocUnicode

ZeroFreeGlobalAllocUnicode

15.

Windows ,
, . -
(CLR) .NET
Framework (FCL). , , , . ,
, , , ,
.


(enumerated type) , , . Color,
, :
internal enum Color {
White, //
Red, //
Green, //
Blue, //
Orange //
}

0
1
2
3
4

, White 0, Green 1 ..
- .
, , ,
. , ,
,
( White 0, 0 White).
- , , . ,
, ,
, .

404

15.

. , ,
Color.Orange ( ),
Fruit ().
CLR ,
. ,
,
(, C++).
System.Enum, System.ValueType, , , System.Object.
, (.5)
, .
, ,
. , ,
(extension methods).
C#
. ,
Color :
internal struct Color : System.Enum {
// ,
//
public const Color White = (Color) 0;
public const Color Red = (Color) 1;
public const Color Green = (Color) 2;
public const Color Blue = (Color) 3;
public const Color Orange = (Color) 4;
// Color
//
public Int32 value__;
}

C# ,
, System.Enum.
.
-, ,
.
, .
,
, , .
System.Enum,
,

405

, .
.

.
, . .
, ,
. , , , ,
. 7.

, System.Enum GetUnderlyingType,
System.Type GetEnumUnderlyingType:
public static Type GetUnderlyingType(Type enumType); //
// System.Enum
public Type GetEnumUnderlyingType(); // System.Type

,
. ,
byte, sbyte, short, ushort, int ( C# ), uint, long ulong. C# FCL.
C# ;
FCL (, Int32) ( CS1008:
byte, sbyte, short, ushort, int, uint, long ulong):
error CS1008: Type byte, sbyte, short, ushort, int, uint, long, or ulong expected

C# ,
byte (System.Byte):
internal enum Color : byte {
White,
Red,
Green,
Blue,
Orange
}

C o l o r ,
GetUnderlyingType :
// "System.Byte"
Console.WriteLine(Enum.GetUnderlyingType(typeof(Color)));

C# ,
(==, !=,

406

15.

<, >, <=, >=, +, , ^, &, |, ~, ++ ). value__

, C# .
.
ToString, System.Enum:
Color c = Color.Blue;
Console.WriteLine(c); //
Console.WriteLine(c.ToString()); //
Console.WriteLine(c.ToString("G")); //
Console.WriteLine(c.ToString("D")); //
Console.WriteLine(c.ToString("X")); //

"Blue" ( )
"Blue" ( )
"Blue" ( )
"3" ( )
"03" ( )

ToString
. ,
. byte/sbyte , short/
ushort , int/uint , long/ulong .
.

ToString System.Enum Format,


:
public static String Format(Type enumType, Object value, String format);

ToString .
, Format
value, . ,
"Blue":
// "Blue"
Console.WriteLine(Enum.Format(typeof(Color), 3, "G"));

, . ,
, . ,
.

GetValues System.Enum GetEnumValues System.Type ,


.
:

407

public static Array GetValues(Type enumType); // System.Enum


public Array GetEnumValues(); // System.Type

ToString
:
Color[] colors = (Color[]) Enum.GetValues(typeof(Color));
Console.WriteLine("Number of symbols defined: " + colors.Length);
Console.WriteLine("Value\tSymbol\n-----\t------");
foreach (Color c in colors) {
//
Console.WriteLine("{0,5:D}\t{0:G}", c);
}

:
Number of symbols defined: 5
Value
Symbol
---------0
White
1
Red
2
Green
3
Blue
4
Orange

GetValues GetEnumVal , Array,


. :
public static TEnum[] GetEnumValues<TEnum>() where TEnum : struct {
return (TEnum[])Enum.GetValues(typeof(TEnum));
}

GetEnumValues
:
Color[] colors = GetEnumValues<Color>();

,
. ,
( , ..)
ToString ( ,
). GetValues, System.Enum System.Type :
//
public static String GetName(Type enumType, Object value); //
// System.Enum
public String GetEnumName(Object value); // System.Type
// :

408

15.

//
public static String[] GetNames(Type enumType); // System.Enum
public String[] GetEnumNames(); // System.Type

,
( ) .
, , ,
.
Parse TryParse Enum:
public static Object Parse(Type enumType, String value);
public static Object Parse(Type enumType, String value, Boolean ignoreCase);
public static Boolean TryParse<TEnum>(String value,
out TEnum result) where TEnum: struct;
public static Boolean TryParse<TEnum>(String value,
Boolean ignoreCase, out TEnum result)
where TEnum : struct;

:
// Orange 4, 'c' 4
Color c = (Color) Enum.Parse(typeof(Color), "orange", true);
// Brown , ArgumentException
c = (Color) Enum.Parse(typeof(Color), "Brown", false);
// Color 1
Enum.TryParse<Color>("1", false, out c);
// Color 23
Enum.TryParse<Color>("23", false, out c);

, IsDefined Enum IsEnum-

Defined Type:

public static Boolean IsDefined(Type enumType, Object value); //


// System.Enum
public Boolean IsEnumDefined(Object value); // System.Type


:
// "True", Color
// Red 1
Console.WriteLine(Enum.IsDefined(typeof(Color), 1));
// "True", Color
// White 0
Console.WriteLine(Enum.IsDefined(typeof(Color), "White"));
// "False",
Console.WriteLine(Enum.IsDefined(typeof(Color), "white"));
// "False", Color
// 10
Console.WriteLine(Enum.IsDefined(typeof(Color), (Byte)10));

IsDefined . :
public void SetColor(Color c) {
if (!Enum.IsDefined(typeof(Color), c)) {

409

throw(new ArgumentOutOfRangeException("c", c, "Invalid Color value."));


}
// , White, Red, Green, Blue Orange
...
}

,
SetColor :
SetColor((Color) 547);

547 , SetColor
ArgumentOutOfRangeException ,
.

IsDefined . , , -,
, . , .
, ,
, . , Color
, SetColor . SetColor
IsDefined , White, Red, Green, Blue
Orange. Color Purple,
SetColor ,
.

ToObject System.Enum,
Byte, SByte, Int16, UInt16, Int32, UInt32, Int64
UInt64 .
.
,
. , :
, . FCL ,
, .
, .
.


. GetAttributes
System.IO.File FileAttributes. FileAttri

410

15.

butes , Int32,
- . FCL FileAttributes

:
[Flags, Serializable]
public enum FileAttributes {
ReadOnly = 0x0001,
Hidden = 0x0002,
System = 0x0004,
Directory = 0x0010,
Archive = 0x0020,
Device = 0x0040,
Normal = 0x0080,
Temporary = 0x0100,
SparseFile = 0x0200,
ReparsePoint = 0x0400,
Compressed = 0x0800,
Offline = 0x1000,
NotContentIndexed = 0x2000,
Encrypted = 0x4000
}

, :
String file = Assembly.GetEntryAssembly().Location;
FileAttributes attributes = File.GetAttributes(file);
Console.WriteLine("Is {0} hidden? {1}", file, (
attributes & FileAttributes.Hidden) != 0);

Enum HasFlag, :
public Boolean HasFlag(Enum flag);

ConsoleWriteLine:
Console.WriteLine("Is {0} hidden? {1}", file,
attributes.HasFlag(FileAttributes.Hidden));

HasFlag. ,
Enum, , ,
.

, :
File.SetAttributes(file, FileAttributes.ReadOnly | FileAttributes.Hidden);

FileAttributes , , ,
.
, .

411

, ,
, .
,
, .
.
None,
0. , (. ReadWrite).

System.FlagsAttribute:
[Flags] // C# "Flags" "FlagsAttribute"
internal enum Actions {
None = 0
Read = 0x0001,
Write = 0x0002,
ReadWrite = Actions.Read | Actions.Write,
Delete = 0x0004,
Query = 0x0008,
Sync = 0x0010
}

Actions ,
.
. , :
Actions actions = Actions.Read | Actions.Delete; // 0x0005
Console.WriteLine(actions.ToString()); // "Read, Delete"

ToString
. 0x0005 . Actions [Flags], ToString
. 0x0001 0x0005
, ToString "Read, Delete".
Actions [Flags], "5".
ToString
: "G" (), "D" () "X" ().
, [Flags].
, , . , ToString
:
1. , ,
.
2. (AND)
.

412

15.

, .
.
3.
, , .
.
4. , , .
5. , ,
.
6. , 0.
, Actions
[Flags]. "F":
// [Flags] //
internal enum Actions {
None = 0
Read = 0x0001,
Write = 0x0002,
ReadWrite = Actions.Read | Actions.Write,
Delete = 0x0004,
Query = 0x0008,
Sync = 0x0010
}
Actions actions = Actions.Read | Actions.Delete; // 0x0005
Console.WriteLine(actions.ToString("F")); // "Read, Delete"

, -
, ,
, .
: , ,
. , Actions All, 0x001F.
Actions 0x001F "All". .
.
, , Parse
Enum TryParse. :
// Query 8, 'a' 8
Actions a = (Actions) Enum.Parse(typeof(Actions), "Query", true);

413

Console.WriteLine(a.ToString()); // "Query"
// Query, Read, 'a'
// 9
Enum.TryParse<Actions>("Query, Read", false, out a);
Console.WriteLine(a.ToString()); // "Read, Query"
// Actions enum 28
a = (Actions) Enum.Parse(typeof(Actions), "28", false);
Console.WriteLine(a.ToString()); // "Delete, Query, Sync"

Parse TryParse :
1. .
2. , (+)
(), ,
, .
3. ,
.
4. . , Parse System.
ArgumentException, TryParse false. (OR)
, .
5. .
IsDefined . :
, ,
. , , , .
, .

, false.

,
. ,

414

15.

,
. ,
C# (extension method),
8.
FileAttributes . :
internal static class FileAttributesExtensionMethods {
public static Boolean IsSet(
this FileAttributes flags, FileAttributes flagToTest) {
if (flagToTest == 0)
throw new ArgumentOutOfRangeException(
"flagToTest", "Value must not be 0");
return (flags & flagToTest) == flagToTest;
}
public static Boolean IsClear(
this FileAttributes flags, FileAttributes flagToTest) {
if (flagToTest == 0)
throw new ArgumentOutOfRangeException(
"flagToTest", "Value must not be 0");
return !IsSet(flags, flagToTest);
}
public static Boolean AnyFlagsSet(
this FileAttributes flags, FileAttributes testFlags) {
return ((flags & testFlags) != 0);
}
public static FileAttributes Set(
this FileAttributes flags, FileAttributes setFlags) {
return flags | setFlags;
}
public static FileAttributes Clear(
this FileAttributes flags, FileAttributes clearFlags) {
return flags & ~clearFlags;
}
public static void ForEach(this FileAttributes flags,
Action<FileAttributes> processFlag) {
if (processFlag == null) throw new ArgumentNullException("processFlag");
for (UInt32 bit = 1; bit != 0; bit <<= 1) {
UInt32 temp = ((UInt32)flags) & bit;
if (temp != 0) processFlag((FileAttributes)temp);
}
}
}

415

.
, , :
FileAttributes fa = FileAttributes.System;
fa = fa.Set(FileAttributes.ReadOnly);
fa = fa.Clear(FileAttributes.System);
fa.ForEach(f => Console.WriteLine(f));

16.

,
. Microsoft .NET (CLR)
(single-dimension), (multidimension) (jagged) .
System.Array, System.Object. ,
,
, . :
Int32[] myIntegers; //
myIntegers = new Int32[100]; // Int32 100

myIntegers,
Int32.
null, .
100 Int32; 0.
, 100
Int32 .
, , , .
myIntegers.
:
Control[] myControls; //
myControls = new Control[50]; // 50
// Control

myControls
Control. null,
.
50 Control, null. Control ,
, - .
myControls.
.16.1 ,
.
Controls :
myControls[1] = new Button();
myControls[2] = new TextBox();
myControls[3] = myControls[2]; //

417

myControls[46] = new DataGrid();


myControls[48] = new ComboBox();
myControls[49] = new Button();

. 16.1.

(CLS),
. , C#,
, , ,
Microsoft Visual Basic .NET. , , Microsoft
.
CLR , .

, , 0. .
, . ,
( 0) .
.
.
.
, SZ-, . , (Intermediate Language, IL),
newarr, ldelem, ldelema, ldlen stelem. , ,
. :
// Doubles
Double[,] myDoubles = new Double[10, 20];

418

16.

//
String[,,] myStrings = new String[5, 3, 10];

CLR (jagged)
.
, .
. ,
Point:
// Point
Point[][] myPolygons = new Point[3][];
// myPolygons[0] 10 Point
myPolygons[0] = new Point[10];
// myPolygons[1] 20 Point
myPolygons[1] = new Point[20];
// myPolygons[2] 30 Point
myPolygons[2] = new Point[30];
//
for (Int32 x = 0; x < myPolygons[0].Length; x++)
Console.WriteLine(myPolygons[0][x]);

CLR . , 100 0 99,


5 100 System.Index.OutOfRange.
, CLR-.
,
, . , ,
,
. .



. C#
:
String[] names = new String[] { "Aidan", "Grant" };

(array initializer).

419

,
.
String.
,
var:
// :
var names = new String[] { "Aidan", "Grant" };

, names
String[], ,
(=). C#, .
new []
:
// :
var names = new[] { "Aidan", "Grant", null };

,
, ,
.
String null. ,
String.
:
//
//
var names = new[] { "Aidan", "Grant", 123 };

( CS0826:
):
error CS0826: No best type found for implicitly-typed array

, Int32
Object.
Object, Int32
, 123. ,
, ,
.
:
String[] names = { "Aidan", "Grant" };

,
. new, ,

420

16.

. , ,
:
//
var names = { "Aidan", "Grant" };

:
error CS0820: Cannot initialize an implicitly-typed local variable with
an array initializer
error CS0622: Can only use array initializer expressions to assign array types.
Try using a new expression instead

,
,
,
new. ,
, , . , new,
, , .

. (
.10.)
:
// ,
// :
var kids = new[] {new { Name="Aidan" }, new { Name="Grant" }};
// ( ):
foreach (var kid in kids)
Console.WriteLine(kid.Name);

,
( new ). ( Name String)
. ( new
). ,
.
kids, .
foreach, kid .
:
Aidan
Grant

421


CLR .
; ,
. CLR
. ,
Array.Copy,
. :
// FileStream
FileStream[,] fs2dim = new FileStream[5, 10];
// Object
Object[,] o2dim = fs2dim;
//
// CS0030: 'object[*,*]'
// 'System.IO.Stream[]'
Stream[] s1dim = (Stream[]) o2dim;
// Stream
Stream[,] s2dim = (Stream[,]) o2dim;
// String
// ,
// InvalidCastException
String[,] st2dim = (String[,]) o2dim;
// Int32 ( )
Int32[] i1dim = new Int32[5];
//
// CS0030:
// 'int[]' 'object[]'
Object[] o1dim = (Object[]) i1dim;
//
// Array.Copy
// Int32
Object[] ob1dim = new Object[i1dim.Length];
Array.Copy(i1dim, ob1dim, i1dim.Length);

Array.Copy .
memmove C,
. . Copy
:
,
Int32[] Object[].

422

16.

,
Object[] Int32[].
(widening) ,
Int32[] Double[].
,
. , ,
Object[] IFormattable[]. Object[]
IFormattable[], .
Copy:
// ,
internal struct MyValueType : IComparable {
public Int32 CompareTo(Object obj) {
...
}
}
public static class Program {
public static void Main() {
// 100
MyValueType[] src = new MyValueType[100];
// IComparable
IComparable[] dest = new IComparable[src.Length];
// IComparable
//
Array.Copy(src, dest, src.Length);
}
}

, FCL

Array.Copy.

, ,
(array covariance). , . , :

String[] sa = new String[100];


Object[] oa = sa; // oa String
oa[5] = "Jeff"; // CLR oa String;
//
oa[3] = 5; // CLR oa Int32;
// ArrayTypeMismatchException

oa, Object[],
String[].
5, Int32, Object.
, CLR , -

System.Array

423

Int32. ,
ArrayTypeMismatchException.


BlockCopy System.Buffer, Array.Copy. ,
, Array.Copy.
Int32 ,
. BlockCopy . ,
Byte[], ,
Char[].
.
ConstrainedCopy System.Array. ,
,
. ConstrainedCopy
(Constrained Execution Region, CER). ,
, ,
. ,
, .

System.Array
:
FileStream[] fsArray;

FileStream[] . FileStream[]
System.Array
. fsArray. , System.Array
, Clone, CopyTo, GetLength, GetLongLength, GetLowerBound,
GetUpperBound, Length Rank.
System.Array , AsReadOnly, BinarySearch, Clear, ConstrainedCopy, ConvertAll,
Copy, Exists, Find, FindAll, FindIndex, FindLast, FindLastIndex, ForEach, IndexOf,
LastIndexOf, Resize, Reverse, Sort TrueForAll. . . , ,

424

16.

.
SDK.

IEnumerable,
ICollection IList
,
, IEnumerable , ICollection IList .
,
System.Array. ,
System.Object.
, System.Array
, .
CLR ,
IEnumerable<T>, ICollection<T> IList<T> System.Array,
,
, .

. : CLR IEnumerable<T>, ICollection<T> IList<T> ( T
),
, .
.
Object
Array ( IEnumerable, ICollection, IList)
Object[] (IEnumerable, ICollection, IList of Object)
String[] (IEnumerable, ICollection, IList of String)
Stream[] (IEnumerable, ICollection, IList of Stream)
FileStream[] (IEnumerable, ICollection, IList of FileStream)
.
. ( )
.

:
FileStream[] fsArray;

FileStream[] CLR IEnumerable<FileStream>, ICollection<FileStream>


IList<FileStream>. , FileStream[] IEnumerable<Stream> , IEnumerable<Object> ,
ICollection<Stream>, ICollection<Object>, IList<Stream> IList<Object>.

425

CLR ,
fsArray .
, :
void M1(IList<FileStream> fsList) { ... }
void M2(ICollection<Stream> sCollection) { ... }
void M3(IEnumerable<Object> oEnumerable) { ... }

, , ,
,
. :
DateTime[] dtArray; //

DateTime[]
IEnumerable<DateTime>, ICollection<DateTime> IList<DateTime>;
, System.ValueType System.Object,
. , dtArray
M3 . - ( ).


,
. , .
, . ,
Array.Copy (shallow) ,
, .
, .
, ; , ,
, ,
. , .
, Array.Copy,
. ,
.
, ,
, null,
. Microsoft ,
. ,
, :
//
Appointment[] appointments = GetAppointmentsForToday();

426

16.

for (Int32 a = 0; a < appointments.Length; a++) {


...
}

, :
//
Appointment[] appointments = GetAppointmentsForToday();
if (appointments != null) {
for (Int32 a = 0, a < appointments.Length; a++) {
// appointments[a]
}
}

, null
, .
. , ,
,
.


, .
CreateInstance Array.
,
, , , . ,
. , CreateInstance,
ElementType[] ( ElementType ),
.
GetValue SetValue Array.

System.Decimal. 2005 2009 , 1 4 .
. ,
, GetLowerBound
GetUpperBound System.Array:
using System;
public static class DynamicArrays {
public static void Main() {
// [2005..2009][1..4]
Int32[] lowerBounds = { 2005, 1 };

427

Int32[] lengths = { 5, 4 };
Decimal[,] quarterlyRevenue = (Decimal[,])
Array.CreateInstance(typeof(Decimal), lengths, lowerBounds);
Console.WriteLine("{0,4} {1,9} {2,9} {3,9} {4,9}",
"Year", "Q1", "Q2", "Q3", "Q4");
Int32 firstYear = quarterlyRevenue.GetLowerBound(0);
Int32 lastYear = quarterlyRevenue.GetUpperBound(0);
Int32 firstQuarter = quarterlyRevenue.GetLowerBound(1);
Int32 lastQuarter = quarterlyRevenue.GetUpperBound(1);
for (Int32 year = firstYear; year <= lastYear; year++) {
Console.Write(year + " ");
for (Int32 quarter = firstQuarter;
quarter <= lastQuarter; quarter++) {
Console.Write("{0,9:C} ", quarterlyRevenue[year, quarter]);
}
Console.WriteLine();
}
}
}

:
Year
2005
2006
2007
2008
2009

Q1
$0.00
$0.00
$0.00
$0.00
$0.00

Q2
$0.00
$0.00
$0.00
$0.00
$0.00

Q3
$0.00
$0.00
$0.00
$0.00
$0.00

Q4
$0.00
$0.00
$0.00
$0.00
$0.00


CLR :
.
SZ- ( single-dimensional, zero-based), .
.
( ):
using System;
public sealed class Program {
public static void Main() {
Array a;
//
//

428

16.
a = new String[0];
Console.WriteLine(a.GetType()); // "System.String[]"

//
//
a = Array.CreateInstance(typeof(String),
new Int32[] { 0 }, new Int32[] { 0 });
Console.WriteLine(a.GetType()); // "System.String[]"
// 1
a = Array.CreateInstance(typeof(String),
new Int32[] { 0 }, new Int32[] { 1 });
Console.WriteLine(a.GetType()); // "System.String[*]" <-- !
Console.WriteLine();
//
//
a = new String[0, 0];
Console.WriteLine(a.GetType()); // "System.String[,]"
//
//
a = Array.CreateInstance(typeof(String),
new Int32[] { 0, 0 }, new Int32[] { 0, 0 });
Console.WriteLine(a.GetType()); // "System.String[,]"
// 1
a = Array.CreateInstance(typeof(String),
new Int32[] { 0, 0 }, new Int32[] { 1, 1 });
Console.WriteLine(a.GetType()); // "System.String[,]"
}
}

Console.WriteLine .
System.String[], ,
System.String[*] . * , CLR
. C# String[*] ,

. ,
GetValue SetValue Array,
.
, ,
: System.String[,]. CLR
. ,
System.String[*,*], CLR
*. ,
.

429

,
. . -,
(newarr, ldelem, ldelema, ldlen stelem)
JIT- . , ,
. ,
. ,
:
using System;
public static class Program {
public static void Main() {
Int32[] a = new Int32[5];
for(Int32 index = 0; index < a.Length; index++) {
// - a[index]
}
}
}

Length
for. , JIT- , Length
Array, ,

, .
.
.
JIT- , .
,
.
Length .
, JIT- ,
, Length- 1. , , .
, :
(0 >= a.GetLowerBound(0)) && ((Length 1) <= a.GetUpperBound(0))

. , ,
.
.
, .

. , ,

430

16.

.
. ,
( ).
, C# CLR
() .
. SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Char, Single,
Double, Decimal, Boolean,
.
,
. ; ,
, ,
. , , Security Permission,
Skip Verification.
,
,
:
using System;
using System.Diagnostics;
public static class Program {
private const Int32 c_numElements = 10000;
public static void Main() {
//
Int32[,] a2Dim = new Int32[c_numElements, c_numElements];
// ( )
Int32[][] aJagged = new Int32[c_numElements][];
for (Int32 x = 0; x < c_numElements; x++)
aJagged[x] = new Int32[c_numElements];
// 1: ,
Safe2DimArrayAccess(a2Dim);
// 2:
SafeJaggedArrayAccess(aJagged);
// 3:
Unsafe2DimArrayAccess(a2Dim);
}
private static Int32 Safe2DimArrayAccess(Int32[,] a) {

431

Int32 sum = 0;
for (Int32 x = 0; x < c_numElements; x++) {
for (Int32 y = 0; y < c_numElements; y++) {
sum += a[x, y];
}
}
return sum;
}
private static Int32 SafeJaggedArrayAccess(Int32[][] a) {
Int32 sum = 0;
for (Int32 x = 0; x < c_numElements; x++) {
for (Int32 y = 0; y < c_numElements; y++) {
sum += a[x][y];
}
}
return sum;
}
private static unsafe Int32 Unsafe2DimArrayAccess(Int32[,] a) {
Int32 sum = 0;
fixed (Int32* pi = a) {
for (Int32 x = 0; x < c_numElements; x++) {
Int32 baseOfDim = x * c_numElements;
for (Int32 y = 0; y < c_numElements; y++) {
sum += pi[baseOfDim + y];
}
}
}
return sum;
}
}

Unsafe2DimArrayAccess unsafe,
fixed C#.
/unsafe Allow Unsafe Code Build
Microsoft Visual Studio.
, , :

- fixed ;
,
, ,
;
- CLR
(, Microsoft
Silverlight).

432

16.



,
:
, (
);
, (
SecureString 14 , SecureStringToCoTaskMemUnicode System.
Runtime.InteropServices.Marshal);
, .
,
. stackalloc
C# ( alloca C).
.
. , , ,
FCL-. ()
. . C# /unsafe.
StackallocDemo
stackalloc:
using System;
public static class Program {
public static void Main() {
StackallocDemo();
InlineArrayDemo();
}
private static void StackallocDemo() {
unsafe {
const Int32 width = 20;
Char* pc = stackalloc Char[width]; //
//
String s = "Jeffrey Richter"; // 15
for (Int32 index = 0; index < width; index++) {
pc[width - index - 1] =
(index < s.Length) ? s[index] : '.';
}

433

// ".....rethciR yerffeJ"
Console.WriteLine(new String(pc, 0, width));
}
}
private static void InlineArrayDemo() {
unsafe {
CharArray ca; //
Int32 widthInBytes = sizeof(CharArray);
Int32 width = widthInBytes / 2;
String s = "Jeffrey Richter"; // 15
for (Int32 index = 0; index < width; index++) {
ca.Characters[width - index - 1] =
(index < s.Length) ? s[index] : '.';
}
// ".....rethciR yerffeJ"
Console.WriteLine(new String(ca.Characters, 0, width));
}
}
}
internal unsafe struct CharArray {
//
public fixed Char Characters[20];
}

, ,
, ; . ,
.
CharArray. :
( ),
( ) ;
, , unsafe;
fixed;
;
: Boolean, Char, SByte,
Byte, Int32, UInt32, Int64, UInt64, Single Double.
, ,
. , , , InlineArrayDemo, -
, StackallocDemo.

17.

, . Microsoft
.NET Framework (delegates).
, C++,
. ,
(
CLR). , , ,
.


qsort C
. Windows , ,
. .NET Framework
. ,
: ,
, , .
C/C++ ,
.
, , , . ,
C/C++ (
).
.NET Framework ,
Windows.
,
. ,
:
using System;
using System.Windows.Forms;
using System.IO;
// ;

435

// Int32, void
internal delegate void Feedback(Int32 value);
public sealed class Program {
public static void Main() {
StaticDelegateDemo();
InstanceDelegateDemo();
ChainDelegateDemo1(new Program());
ChainDelegateDemo2(new Program());
}
private static void StaticDelegateDemo() {
Console.WriteLine("----- Static Delegate Demo -----");
Counter(1, 3, null);
Counter(1, 3, new Feedback(Program.FeedbackToConsole));
Counter(1, 3, new Feedback(FeedbackToMsgBox)); // "Program."
//
Console.WriteLine();
}
private static void InstanceDelegateDemo() {
Console.WriteLine("----- Instance Delegate Demo -----");
Program p = new Program();
Counter(1, 3, new Feedback(p.FeedbackToFile));
}

Console.WriteLine();

private static void ChainDelegateDemo1(Program p) {


Console.WriteLine("----- Chain Delegate Demo 1 -----");
Feedback fb1 = new Feedback(FeedbackToConsole);
Feedback fb2 = new Feedback(FeedbackToMsgBox);
Feedback fb3 = new Feedback(p.FeedbackToFile);
Feedback fbChain = null;
fbChain = (Feedback) Delegate.Combine(fbChain, fb1);
fbChain = (Feedback) Delegate.Combine(fbChain, fb2);
fbChain = (Feedback) Delegate.Combine(fbChain, fb3);
Counter(1, 2, fbChain);
Console.WriteLine();
fbChain = (Feedback)
Delegate.Remove(fbChain, new Feedback(FeedbackToMsgBox));
Counter(1, 2, fbChain);
}
private static void ChainDelegateDemo2(Program p) {
Console.WriteLine("----- Chain Delegate Demo 2 -----");
Feedback fb1 = new Feedback(FeedbackToConsole);
Feedback fb2 = new Feedback(FeedbackToMsgBox);
Feedback fb3 = new Feedback(p.FeedbackToFile);
Feedback fbChain = null;

436

17.

fbChain +=
fbChain +=
fbChain +=
Counter(1,

fb1;
fb2;
fb3;
2, fbChain);

Console.WriteLine();
fbChain -= new Feedback(FeedbackToMsgBox);
Counter(1, 2, fbChain);
}
private static void Counter(Int32 from, Int32 to, Feedback fb) {
for (Int32 val = from; val <= to; val++) {
// ,
if (fb != null)
fb(val);
}
}
private static void FeedbackToConsole(Int32 value) {
Console.WriteLine("Item=" + value);
}
private static void FeedbackToMsgBox(Int32 value) {
MessageBox.Show("Item=" + value);
}
private void FeedbackToFile(Int32 value) {
using (StreamWriter sw = new StreamWriter("Status", true)) {
sw.WriteLine("Item=" + value);
}
}

.
Feedback. . ,
Int32 void. typedef
C/C++, .
Program Counter.
, from to.
fb, Feedback. Counter , fb
null, ( fb).

. ,
.

437


, Counter,
.
StaticDelegateDemo .
StaticDelegateDemo Counter, fb null.
.
Counter StaticDelegateDemo Feedback.
,
, .
Program.FeedbackToConsole Feedback, ,
. new
Counter,
FeedbackToConsole. .

FeedbackToConsole Program , Counter.


, . Counter
, . ,
,
,
, .

Counter StaticDelegateDemo
, Feedback
Program.FeedbackToMsgBox. FeedbackToMsgBox ,
,
.
. , Feedback ,
FeedbackToConsole FeedbackToMsgBox Program
. ,
( Int32) (void). FeedbackToConsole :
private static Boolean FeedbackToConsole(String value) {
...
}

FeedbackToConsole ):

error CS0123: No overload for 'FeedbackToConsole' matches delegate 'Feedback'

438

17.

C#, CLR . (covariance) ,


, , .
(contra-variance) , , . :
delegate Object MyCallback(FileStream s);

, ,
, :
String SomeMethod(Stream s);

, SomeMethod ( String),
, (Object);
. SomeMethod ( Stream)
(FileStream);
.
,
, void. , MyCallback :
Int32 SomeOtherMethod(Stream s);

, SomeOtherMethod
( Int32), ,
MyCallback ( Object), ,
Int32 . void , ,
.
,
.


,
. InstanceDelegateDemo .
, p Program
InstanceDelegateDemo. , .
Counter Feedback,
p.FeedbackToFile.
FeedbackToFile, , -

439

. Counter ,
fb, FeedbackToFile,
p
this.
FeedbackToFile FeedbackToConsole FeedbackTo
MsgBox , (
Status AppBase ).
, ,
. , .
,
. ,
.


.
C# delegate, new ,
.
.
,
.
CLR. ,
.
.
:
internal delegate void Feedback(Int32 value);

, :
internal class Feedback : System.MulticastDelegate {
//
public Feedback(Object object, IntPtr method);
// ,
public virtual void Invoke(Int32 value);
// ,
public virtual IAsyncResult BeginInvoke(Int32 value,
AsyncCallback callback, Object object);
public virtual void EndInvoke(IAsyncResult result);
}

440

17.

, , : ,
Invoke, BeginInvoke EndInvoke. Invoke. BeginInvoke EndInvoke
.NET Framework,
. ,
27.
ILDasm.exe, ,
(17.1).

. 17.1.

Feedback,
System.MulticastDelegate Framework Class Library (
MulticastDelegate).

System.MulticastDelegate System.Delegate,
, , System.Object.
, FCL . ,
MulticastDelegate, , Delegate. , Combine Remove ( , , ).
, Delegate.
MulticastDelegate,
Delegate,
.

, internal. public,
Feedback . ,
( ), -

441

. , ,
, .
MulticastDelegate,
, .
.17.1.
17.1. MulticastDelegate

_target

System.Object


, null. ,
,
. ,
,
this

_methodPtr

System.IntPtr

,
CLR

_invocationList

System.Object

null.

( )

, :
, .
, Program.FeedbackToConsole
p.FeedbackToFile. , ,
!
, , , ,
, .
object . IntPtr (
MethodDef MemberRef), , method. object
null.
_target _methodPtr . ,
null _invocationList.
, .
, .
fbStatic fbInstance Feedback, , .17.2:
Feedback fbStatic = new Feedback(Program.FeedbackToConsole);
Feedback fbInstance = new Feedback(new Program().FeedbackToFile);

442

17.

. 17.2. ,.

, , .
Counter:
private static void Counter(Int32 from, Int32 to, Feedback fb) {
for (Int32 val = from; val <= to; val++) {
// ,
if (fb != null)
fb(val);
}
}

. if , fb null. , . , fb
, Feedback; ,
, null. , fb,
(val). .
Invoke , , fb
. ,
fb(val);

, :
fb.Invoke(val);

ILDasm.exe Counter,
, , Invoke.
IL- Counter. IL_0009
Invoke Feedback.
.method private hidebysig static void Counter(int32 from,
int32 'to',
class Feedback fb) cil managed
{
// Code size 23 (0x17)
.maxstack 2
.locals init (int32 V_0)

( )
IL_0000:
IL_0001:
IL_0002:
IL_0004:
IL_0005:
IL_0007:
IL_0008:
IL_0009:
IL_000e:
IL_000f:
IL_0010:
IL_0011:
IL_0012:
IL_0013:
IL_0014:
IL_0016:
} // end

443

ldarg.0
stloc.0
br.s IL_0012
ldarg.2
brfalse.s IL_000e
ldarg.2
ldloc.0
callvirt instance void Feedback::Invoke(int32)
ldloc.0
ldc.i4.1
add
stloc.0
ldloc.0
ldarg.1
ble.s IL_0004
ret
of method Program::Counter

Counter , Invoke:
private static void Counter(Int32 from, Int32 to, Feedback fb) {
for (Int32 val = from; val <= to; val++) {
// ,
if (fb != null)
fb.Invoke(val);
}
}

, , Invoke Feedback. , _target


_methodPtr . , Invoke ,
Feedback, Invoke Int32
void.


( )
,
. (chaining) , , . ,
,
ChainDelegateDemo1. Console.WriteLine , fb1, fb2 fb3
(.17.3).

444

17.

. 17.3. , .
fb1, fb2 fb3

Feedback, fbChain, , ,
. fbChain null
. Combine
Delegate :
fbChain = (Feedback) Delegate.Combine(fbChain, fb1);

Combine ,
null fb1.
fb1, fbChain ,
fb1. .17.4.

fb Chain

. 17.4.

( )

445

Combine:

fbChain = (Feedback) Delegate.Combine(fbChain, fb2);

Combine , fbChain , , _target


_methodPtr . , ,
_invocationList .
( 0) , FeedbackToConsole (
fbChain). ( 1) , FeedbackToMsgBox (
fb2). fbChain
(.17.5).

. 17.5.

Combine:
fbChain = (Feedback) Delegate.Combine(fbChain, fb3);

, , fbChain , , .17.6. ,
_target
_methodPtr, _invocationList
. ( 0 1) , .
( 2) ,

446

17.

FeedbackToFile (
fb3). , fbChain
. ,
_invocationList, .

. 17.6.

, , fbChain
Counter:
Counter(1, 2, fbChain);

Counter Invoke
Feedback. , . Invoke
, fbChain, ,
_invocationList null.
, , ,
. : FeedbackToConsole, FeedbackToMsgBox , ,
FeedbackToFile.
Invoke Feedback (
):

( )

447

public void Invoke(Int32 value) {


Delegate[] delegateSet = _invocationList as Delegate[];
if (delegateSet != null) {
// ,
foreach (Feedback d in delegateSet)
d(value); //
} else {
// .
// .
_methodPtr.Invoke(_target, value);
// .
// , , C#.
}
}

Remove
Delegate. Chain
DelegateDemo1:
fbChain = (Feedback) Delegate.Remove(
fbChain, new Feedback(FeedbackToMsgBox));

Remove ( ), , (
fbChain). , _target _methodPtr (
Feedback). ,
, _invocationList,
, .
Remove null.
, Remove ,
_target _methodPtr.
Feedback,
void. :
public delegate Int32 Feedback(Int32 value);

Invoke :
public Int32 Invoke(Int32 value) {
Int32 result;
Delegate[] delegateSet = _invocationList as Delegate[];
if (delegateSet != null) {
// ,
foreach (Feedback d in delegateSet)
result = d(value); //
} else {
// .
// .
result = _methodPtr.Invoke(_target, value);

448

17.

// .
// , , C#.
}
return result;
}

result.
( ); , Invoke.

C#
, C# += -= .
Delegate.Combine Delegate.Remove .
.
ChainDelegateDemo1 ChainDelegateDemo2 (. )
IL-code. , +=
-= ChainDelegateDemo2 .
IL-
ILDasm.exe. , C# += -= Combine
Remove Delegate .

, .
Invoke ,
. , . ,
,
. . . , ,
, . , .

GetInvocationList MulticastDelegate.
:
public abstract class MulticastDelegate : Delegate {
// ,
//
public sealed override Delegate[] GetInvocationList();
}

( )

449

GetInvocationList ,
MulticastDelegate. ,

- . , ;
. _invocationList null,
, .
, , :
using System;
using System.Reflection;
using System.Text;
// Light
internal sealed class Light {
// Light
public String SwitchPosition() {
return "The light is off";
}
}
// Fan
internal sealed class Fan {
// Fan
public String Speed() {
throw new InvalidOperationException("The fan broke due to overheating");
}
}
// Speaker
internal sealed class Speaker {
// Speaker
public String Volume() {
return "The volume is loud";
}
}
public sealed class Program {
// ,
private delegate String GetStatus();
public static void Main() {
//
GetStatus getStatus = null;
//
//
getStatus += new GetStatus(new Light().SwitchPosition);
getStatus += new GetStatus(new Fan().Speed);

450

17.
getStatus += new GetStatus(new Speaker().Volume);

//
Console.WriteLine(GetComponentStatusReport(getStatus));
}
//
private static String GetComponentStatusReport(GetStatus status) {
// ,
if (status == null) return null;
//
StringBuilder report = new StringBuilder();
//
Delegate[] arrayOfDelegates = status.GetInvocationList();
//
foreach (GetStatus getStatus in arrayOfDelegates) {
try {
//
report.AppendFormat("{0}{1}{1}", getStatus(), Environment.NewLine);
}
catch (InvalidOperationException e) {
//
Object component = getStatus.Target;
report.AppendFormat(
"Failed to get status from {1}{2}{0} Error: {3}{0}{0}",
Environment.NewLine,
((component == null) ? "" : component.GetType() + "."),
getStatus.Method.Name,
e.Message);
}
}
//
return report.ToString();
}
}

:
The light is off
Failed to get status from Fan.Speed
Error: The fan broke due to overheating
The volume is loud

451


, .NET Framework ,
Microsoft . FCL
. .
MSCorLib.dll 50. :
public
public
public
public
public
public

delegate
delegate
delegate
delegate
delegate
delegate

void
void
void
void
void
void

TryCode(Object userData);
WaitCallback(Object state);
TimerCallback(Object state);
ContextCallback(Object state);
SendOrPostCallback(Object state);
ParameterizedThreadStart(Object obj);

?
:
, Object void.
.
.NET Framework ,
(
System), ,
16:
public
public
public
public
...
public

delegate
delegate
delegate
delegate

void
void
void
void

Action(); //
Action<T>(T obj);
Action<T1, T2>(T1 arg1, T2 arg2);
Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);

delegate void Action<T1, ..., T16>(T1 arg1, ..., T16 arg16);

.NET Framework 17 Action,


16.
, , .
Action .NET Framework 17 Func,
:
public
public
public
public
...
public

delegate
delegate
delegate
delegate

TResult
TResult
TResult
TResult

Func<TResult>();
Func<T, TResult>(T arg);
Func<T1, T2, TResult>(T1 arg1, T2 arg2);
Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);

delegate TResult Func<T1,..., T16, TResult>(T1 arg1, ..., T16 arg16);

;
. , ,
ref out, :
delegate void Bar(ref Int32 z);

452

17.

,
params,
-.
, , ,
.
12.

- . ,
:
button1.Click += new EventHandler(button1_Click);

button1_Click , :
void button1_Click(Object sender, EventArgs e) {
// ...
}

button1_Click ,
. EventHandler ,
button1_Click. CLR,
, . .

:
button1.Click += button1_Click;

, C#
. , , IL, CLR . ,
,
C#; .

1:
, C#
, . :

453

internal sealed class AClass {


public static void CallbackWithoutNewingADelegateObject() {
ThreadPool.QueueUserWorkItem(SomeAsyncTask, 5);
}

private static void SomeAsyncTask(Object o) {


Console.WriteLine(o);
}

QueueUserWorkItem ThreadPool
WaitCallback, , , SomeAsyncTask.
, ,
, WaitCallback,
. IL-,
WaitCallback, ,
.

2:
SomeAsyncTask
QueueUserWorkItem ThreadPool. C#
, . ,
:
internal sealed class AClass {
public static void CallbackWithoutNewingADelegateObject() {
ThreadPool.QueueUserWorkItem( obj => Console.WriteLine(obj ), 5);
}
}

, QueueUserWorkItem (
) !
C# - (lambda expression)
=>. - , . -,
(
AClass). (anonymous function),
, .
,
ILDasm.exe.
, <CallbackWithoutNewingADelegateObject
>b__0, , Object,
void.
, <,
C# . ,
-

454

17.

, . , C#
<, CLR .

, , - .
ILDasm.exe , C#
System.Runtime.CompilerServices.CompilerGeneratedAttribute.
, , .
, =>.

-
(,
unsafe). , , .
, -
. ,
public, protected, internal, virtual, sealed, override abstract .

C# ( ):
internal sealed class AClass {
//
// : CallbackWithoutNewingADelegateObject
//
// :
[CompilerGenerated]
private static WaitCallback <>9__CachedAnonymousMethodDelegate1;
public static void CallbackWithoutNewingADelegateObject() {
if (<>9__CachedAnonymousMethodDelegate1 == null) {
//
<>9__CachedAnonymousMethodDelegate1 =
new WaitCallback(<CallbackWithoutNewingADelegateObject>b__0);
}
ThreadPool.QueueUserWorkItem(<>9__CachedAnonymousMethodDelegate1, 5);
}

[CompilerGenerated]
private static void <CallbackWithoutNewingADelegateObject>b__0(
Object obj) {
Console.WriteLine(obj);
}

- WaitCallback:
void Object. , -

455

, obj =>.
Console.WriteLine
void. void, ,
WaitCallback.
, private;
, (
). ,
.
- ( CallbackWithoutNewingADe
legateObject ). ,
. :
internal sealed class AClass {
private static String sm_name; //
public static void CallbackWithoutNewingADelegateObject() {
ThreadPool.QueueUserWorkItem(
//
obj =>Console.WriteLine(sm_name+ ": " + obj),
5);
}
}

CallbackWithoutNewingADelegateObject , .
, ,
this.
, :
internal sealed class AClass {
private String m_name; //
//
public void CallbackWithoutNewingADelegateObject() {
ThreadPool.QueueUserWorkItem(
//
obj => Console.WriteLine(m_name+ ": " + obj),
5);
}
}

, -,
=>. , :
// ,
Func<String> f = () => "Jeff";
//

456

17.

//
Func<Int32, String> f2 = (Int32 n) => n.ToString();
Func<Int32, Int32, String> f3 =
(Int32 n1, Int32 n2) => (n1 + n2).ToString();
//
//
Func<Int32, String> f4 = (n) => n.ToString();
Func<Int32, Int32, String> f5 = (n1, n2) => (n1 + n2).ToString();
// ,
Func<Int32, String> f6 = n => n.ToString();
// ref/out ref/out
Bar b = (out Int32 n) => n = 5;

, Bar :
delegate void Bar(out Int32 z);

=>.
, .
-,
Func.
. , ThreadPool.QueueUserWorkItem
-, Console.WriteLine
( void).
, . ,
return, :
Func<Int32, Int32, String> f7 = (n1, n2) => {
Int32 sum = n1 + n2; return sum.ToString(); };

, , .
,
, .
.
, .
,
-.
, .

457

C# 2.0. ( C#3.0),
. -
, ,
. , ,
, C#2.0, .
-.

3:

, .

. :
internal sealed class AClass {
public static void UsingLocalVariablesInTheCallbackCode(Int32 numToDo) {
//
Int32[] squares = new Int32[numToDo];
AutoResetEvent done = new AutoResetEvent(false);
//
for (Int32 n = 0; n < squares.Length; n++) {
ThreadPool.QueueUserWorkItem(
obj => {
Int32 num = (Int32) obj;
//
squares[num] = num * num;
// ,
if (Interlocked.Decrement(ref numToDo) == 0)
done.Set();
},
n);
}
//
done.WaitOne();
//
for (Int32 n = 0; n < squares.Length; n++)
Console.WriteLine("Index {0}, Square={1}", n, squares[n]);
}
}

, C# , . -

458

17.

numToDo squares done.


-.
, - ( CLR). ?
,
, . ,
. UsingLocalVariablesInTheCallbackCode
, , ,
, .

- / ,
, . /
, .
, ,
. ,
.

, , . ( ):
internal sealed class AClass {
public static void UsingLocalVariablesInTheCallbackCode(Int32 numToDo) {
//
WaitCallback callback1 = null;
//
<>c__DisplayClass2 class1 = new <>c__DisplayClass2();
//
class1.numToDo = numToDo;
class1.squares = new Int32[class1.numToDo];
class1.done = new AutoResetEvent(false);
//
for (Int32 n = 0; n < class1.squares.Length; n++) {
if (callback1 == null) {
//
//
callback1 = new WaitCallback(
class1.<UsingLocalVariablesInTheCallbackCode>b__0);
}
ThreadPool.QueueUserWorkItem(callback1, n);
}

459

//
class1.done.WaitOne();
//
for (Int32 n = 0; n < class1.squares.Length; n++)
Console.WriteLine("Index {0}, Square={1}", n, class1.squares[n]);
}
// ,
// AClass
[CompilerGenerated]
private sealed class <>c__DisplayClass2 : Object {
//
//
public Int32[] squares;
public Int32 numToDo;
public AutoResetEvent done;
//
public <>c__DisplayClass2 { }
//
public void <UsingLocalVariablesInTheCallbackCode>b__0(Object obj) {
Int32 num = (Int32) obj;
squares[num] = num * num;
if (Interlocked.Decrement(ref numToDo) == 0)
done.Set();
}
}
}

, , . .
, , ,
.
, Visual Studio - .
:
, -.
. , -
. - ,
, :
// String
String[] names = { "Jeff", "Kristin", "Aidan", "Grant" };
// 'a'
Char charToFind = 'a';

460

17.
names = Array.FindAll(names, name => name.IndexOf(charToFind) >= 0);
//
names = Array.ConvertAll(names, name => name.ToUpper());
//
Array.ForEach(names, Console.WriteLine);


,
. , fb Feedback (.
), :
fb(item); // item Int32

, . , ,
.
, . 11 EventSet
, .
.
,
.
, System.Reflection.MethodInfo Create
Delegate ,
.
:
public abstract class MethodInfo : MethodBase {
// , .
public virtual Delegate CreateDelegate(Type delegateType);
// , ;
// target 'this'.
public virtual Delegate CreateDelegate(Type delegateType, Object target);
}

, DynamicInvoke
Delegate, :
public abstract class Delegate {
//
public Object DynamicInvoke(params Object[] args);
}

461

API (. 23)
MethodInfo , . CreateDelegate , Delegate
delegateType.
, CreateDelegate target,
,
this.
DynamicInvoke System.Delegate
, , . DynamicInvoke
, .
, ;
ArgumentException. ,
.
CreateDelegate DynamicInvoke:
using System;
using System.Reflection;
using System.IO;
//
internal delegate Object TwoInt32s(Int32 n1, Int32 n2);
internal delegate Object OneString(String s1);
public static class DelegateReflection {
public static void Main(String[] args) {
if (args.Length < 2) {
String usage =
@"Usage:" +
"{0} delType methodName [Arg1] [Arg2]" +
"{0}
where delType must be TwoInt32s or OneString" +
"{0} if delType is TwoInt32s, methodName must be Add or Subtract" +
"{0} if delType is OneString, methodName must be NumChars or Reverse"
+
"{0}" +
"{0}Examples:" +
"{0}
TwoInt32s Add 123 321" +
"{0}
TwoInt32s Subtract 123 321" +
"{0}
OneString NumChars \"Hello there\"" +
"{0}
OneString Reverse \"Hello there\"";
Console.WriteLine(usage, Environment.NewLine);
return;
}
// delType
Type delType = Type.GetType(args[0]);
if (delType == null) {
Console.WriteLine("Invalid delType argument: " + args[0]);

462

17.

return;

Delegate d;
try {
// Arg1
MethodInfo mi =
typeof(DelegateReflection).GetTypeInfo().GetDeclaredMethod(args[1]);
// ,
d = mi.CreateDelegate(delType);
}
catch (ArgumentException) {
Console.WriteLine("Invalid methodName argument: " + args[1]);
return;
}
// , ,
//
Object[] callbackArgs = new Object[args.Length 2];
if (d.GetType() == typeof(TwoInt32s)) {
try {
// String Int32
for (Int32 a = 2; a < args.Length; a++)
callbackArgs[a 2] = Int32.Parse(args[a]);
}
catch (FormatException) {
Console.WriteLine("Parameters must be integers.");
return;
}
}
if (d.GetType() == typeof(OneString)) {
// String
Array.Copy(args, 2, callbackArgs, 0, callbackArgs.Length);
}
try {
//
Object result = d.DynamicInvoke(callbackArgs);
Console.WriteLine("Result = " + result);
}
catch (TargetParameterCountException) {
Console.WriteLine("Incorrect number of parameters specified.");
}
}
// , Int32
private static Object Add(Int32 n1, Int32 n2) {
return n1 + n2;
}


// , Int32
private static Object Subtract(Int32 n1, Int32 n2) {
return n1 n2;
}
// , String
private static Object NumChars(String s1) {
return s1.Length;
}
// , String
private static Object Reverse(String s1) {
return new String(s1.Reverse().ToArray());
}
}

463

18.

Microsoft .NET
Framework (custom attributes).
, .
,
.
. .NET
Framework (Windows Forms, WPF, WCF ..),
. ,
.NET Framework.

public, private, static ,


. ,
? ,
, -
. , ,
, , .
, ,
. -
, Microsoft
, ,
, . , CLR-
.
,
.

465

.
;
.
.NET Framework (FCL) , . :
DllImport CLR ,
DLL-.
Serializable , .
AssemblyVersion .
Flags .
. C#
, .. , ;
, :
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal sealed class OSVERSIONINFO {
public OSVERSIONINFO() {
OSVersionInfoSize = (UInt32) Marshal.SizeOf(this);
}
public
public
public
public
public

UInt32
UInt32
UInt32
UInt32
UInt32

OSVersionInfoSize = 0;
MajorVersion = 0;
MinorVersion = 0;
BuildNumber = 0;
PlatformId = 0;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]


public String CSDVersion = null;
}
internal sealed class MyClass {
[DllImport("Kernel32", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean GetVersionEx([In, Out] OSVERSIONINFO ver);
}

StructLayout OSVERSIONINFO,
MarshalAs CSDVersion, DllImport GetVersionEx,
In Out ver GetVersionEx. -

466

18.

. , Visual
Basic .NET (<>).
CLR ,
.
: TypeDef (, , , ),
MethodDef (), ParamDef, FieldDef, PropertyDef, EventDef, AssemblyDef
ModuleDef. , C# , , , ,
(, , , , ), , (
), , , ,
, .
, , .

. , ,
.
:
using System;
[assembly: SomeAttr] //
[module: SomeAttr] //
[type: SomeAttr] //
internal sealed class SomeType<[typevar: SomeAttr] T> { //
//
[field: SomeAttr] //
public Int32 SomeField = 0;
[return: SomeAttr] //
[method: SomeAttr] //
public Int32 SomeMethod(
[param: SomeAttr] //
Int32 SomeParam) { return SomeParam; }
[property: SomeAttr] //
public String SomeProp {
[method: SomeAttr] // get
get { return null; }
}
[event: SomeAttr] //
[field: SomeAttr] //
[method: SomeAttr] //
//
public event EventHandler
}


,

add remove
SomeEvent;

, , , , .

467

. (CLS) System.Attribute.
C# CLS- . .NET
Framework SDK : StructLayoutAttribute, MarshalAsAttribute, DllImportAttribute,
InAttribute OutAttribute . System.
Runtime.InteropServices,
. , System.Attribute, CLS- .

Attribute,
. , [DllImport(...)]
[DllImportAttribute(...)].

, .
. ,
. ,

. . ,
DllImport GetVersionEx:
[DllImport("Kernel32", CharSet = CharSet.Auto, SetLastError = true)]

, - .
DllImportAttribute , String.
"Kernel32". (positional
parameters); .
?
DllImportAttribute
. "Kernel32", CharSet
SetLastError CharSet.Auto true .
, , (named
parameters); . , DllImportAttribute.
, . , ver
GetVersionEx In Out. , . C#
;

468

18.

.
, . , ,
Attribute .

:
[Serializable][Flags]
[Serializable, Flags]
[FlagsAttribute, SerializableAttribute]
[FlagsAttribute()][Serializable()]


, ,
System.Attribute, . . , Microsoft
.
FlagsAttribute:
namespace System {
public class FlagsAttribute : System.Attribute {
public FlagsAttribute() {
}
}
}

, FlagsAttribute Attribute;
CLS-.
Attribute. ,
. ,
. FlagsAttribute
.

. , , .
,
( ) . /, ( )
. ,
.
.
. ,
, .

469

, FlagsAttribute
, . .
, System.
AttributeUsageAttribute:
namespace System {
[AttributeUsage(AttributeTargets.Enum, Inherited = false)]
public class FlagsAttribute : System.Attribute {
public FlagsAttribute() {
}
}
}

AttributeUsageAttribute . , , , ,
, . AttributeUsage
,
.
.
AttributeUsage ,
Flags .
, ,
AttributeUsageAttribute, . FCL:
[Serializable]
[AttributeUsage(AttributeTargets.Class, Inherited=true)]
public sealed class AttributeUsageAttribute : Attribute {
internal static AttributeUsageAttribute Default =
new AttributeUsageAttribute(AttributeTargets.All);
internal Boolean m_allowMultiple = false;
internal AttributeTargets m_attributeTarget = AttributeTargets.All;
internal Boolean m_inherited = true;
//
public AttributeUsageAttribute(AttributeTargets validOn) {
m_attributeTarget = validOn;
}
internal AttributeUsageAttribute(AttributeTargets validOn,
Boolean allowMultiple, Boolean inherited) {
m_attributeTarget = validOn;
m_allowMultiple = allowMultiple;
m_inherited = inherited;
}
public Boolean AllowMultiple {
get { return m_allowMultiple; }
set { m_allowMultiple = value; }
}

470

18.

public Boolean Inherited {


get { return m_inherited; }
set { m_inherited = value; }
}

public AttributeTargets ValidOn {


get { return m_attributeTarget; }
}

, AttributeUsageAttribute ,
,
. System.AttributeTargets FCL :
[Flags, Serializable]
public enum AttributeTargets {
Assembly = 0x0001,
Module = 0x0002,
Class = 0x0004,
Struct = 0x0008,
Enum = 0x0010,
Constructor = 0x0020,
Method = 0x0040,
Property = 0x0080,
Field = 0x0100,
Event = 0x0200,
Interface = 0x0400,
Parameter = 0x0800,
Delegate = 0x1000,
ReturnValue = 0x2000,
GenericParameter = 0x4000,
All = Assembly | Module | Class | Struct | Enum |
Constructor | Method | Property | Field | Event |
Interface | Parameter | Delegate | ReturnValue |
GenericParameter
}

AttributeUsageAttribute ,
AllowMultiple Inherited.

. ,
Flags Serializable:
[Flags][Flags]
internal enum Color {
Red
}

,
( CS0579: Flags):
error CS0579: Duplicate 'Flags' attribute

471

, FCL
ConditionalAttribute. AllowMultiple
true. .
Inherited AttributeUsageAttribute ,
, ,
.
:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
Inherited=true)]
internal class TastyAttribute : Attribute {
}
[Tasty][Serializable]
internal class BaseType {
[Tasty] protected virtual void DoSomething() { }
}
internal class DerivedType : BaseType {
protected override void DoSomething() { }
}

DerivedType DoSomething
Tasty, TastyAttribute .
DerivedType , SerializableAttribute FCL

.
, .NET Framework
, , , , ,
. , Inherited
true. ,
.
.


AttributeUsage, CLR , . , .
AttributeUsageAttribute.

, , , .

472

18.

,
, .
, ,
. : Boolean, Char, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double,
String, Type, Object .
, ,
, ,
CLS.
, , , . ,
, Type,
typeof C#,
. , Object
Int32, String ( null). ,
.
:
using System;
internal enum Color { Red }
[AttributeUsage(AttributeTargets.All)]
internal sealed class SomeAttribute : Attribute {
public SomeAttribute(String name, Object o, Type[] types) {
// 'name' String
// 'o' ( )
// 'types' Types
//
}
}
[Some("Jeff", Color.Red, new Type[] { typeof(Math), typeof(Console) })]
internal sealed class SomeType {
}

,
, .
, .
, .

, , .
.

473

,
, . ,
. ,
, ,
.
.


.
, ,
.
15, System.Enum
Flags ToString Format. ,
Flags , .
, (reflection). 23,
.
Microsoft,
Format Enum, :
public override String ToString() {
// FlagsAttribute?
if (this.GetType().IsDefined(typeof(FlagsAttribute), false)) {
// ; ,
//
...
} else {
// ; ,
//
...
}
...
}

IsDefined Type, ,
FlagsAttribute. IsDefined
true, , FlagsAttribute ,
Format , .

.

474

18.

, , (
), . !
FCL .
System.Type IsDefined, .
, ,
. System.Reflection.CustomAttribute
Extensions. CLS- .
: IsDefined,
GetCustomAttributes GetCustomAttribute.
. , (, , , , ,
, , , ,
), . , .
.18.1.
18.1. System.Reflection.CustomAttributeExtensions,
CLS-.

IsDefined

true , Attribute,
. , ( )

GetCustomAttributes

, .
()
, .
,
. ,
AllowMultiple true,

GetCustomAttribute

.
()
, .
, null.
System.Reflection.
AmbiguousMatchException. , AllowMultiple false

475

,
IsDefined .
, , , IsDefined .
GetCustomAttributes
GetCustomAttribute.
,
.
.
.
, ,
.
, .
System.Reflection , : Assembly, Module, ParameterInfo,
MemberInfo, Type, MethodInfo, ConstructorInfo, FieldInfo, EventInfo, PropertyInfo
*Builder. IsDefined
GetCustomAttributes.
GetCustomAttributes, , , Object (Object[])
Attribute (Attribute[]). , ,
, ,
CLS. , .
.NET Framework .

, , inherit,
Attribute, Type MethodInfo.
.
, , ,
Attribute.

, . IsDefined, GetCustomAttribute GetCustomAttributes


.
,
, , .
,
sealed.

. ;
:

476

18.

using System;
using System.Diagnostics;
using System.Reflection;
[assembly: CLSCompliant(true)]
[Serializable]
[DefaultMemberAttribute("Main")]
[DebuggerDisplayAttribute("Richter", Name = "Jeff",
Target = typeof(Program))]
public sealed class Program {
[Conditional("Debug")]
[Conditional("Release")]
public void DoSomething() { }
public Program() {
}
[CLSCompliant(true)]
[STAThread]
public static void Main() {
// ,
ShowAttributes(typeof(Program));
// ,
var members =
from m in typeof(Program).GetTypeInfo().DeclaredMembers.OfType<MethodBase>()
where m.IsPublic
select m;
foreach (MemberInfo member in members) {
// ,
ShowAttributes(member);
}
}
private static void ShowAttributes(MemberInfo attributeTarget) {
var attributes = attributeTarget.GetCustomAttributes<Attribute>();
Console.WriteLine("Attributes applied to {0}: {1}",
attributeTarget.Name, (attributes.Count() == 0 ? "None" : String.Empty));
foreach (Attribute attribute in attributes) {
//
Console.WriteLine(" {0}", attribute.GetType().ToString());
if (attribute is DefaultMemberAttribute)
Console.WriteLine(" MemberName={0}",
((DefaultMemberAttribute) attribute).MemberName);
if (attribute is ConditionalAttribute)

477

Console.WriteLine(" ConditionString={0}",
((ConditionalAttribute) attribute).ConditionString);
if (attribute is CLSCompliantAttribute)
Console.WriteLine(" IsCompliant={0}",
((CLSCompliantAttribute) attribute).IsCompliant);
DebuggerDisplayAttribute dda = attribute as DebuggerDisplayAttribute;
if (dda != null) {
Console.WriteLine(" Value={0}, Name={1}, Target={2}",
dda.Value, dda.Name, dda.Target);
}
}
Console.WriteLine();
}
}

, :
Attributes applied to Program:
System.SerializableAttribute
System.Diagnostics.DebuggerDisplayAttribute
Value=Richter, Name=Jeff, Target=Program
System.Reflection.DefaultMemberAttribute
MemberName=Main
Attributes applied to DoSomething:
System.Diagnostics.ConditionalAttribute
ConditionString=Release
System.Diagnostics.ConditionalAttribute
ConditionString=Debug
Attributes applied to Main:
System.CLSCompliantAttribute
IsCompliant=True
System.STAThreadAttribute
Attributes applied to .ctor: None


, , , . , ,
, .
System.Attribute Equals Object, . ,
false. Equals
( Equals ).

478

18.

, true.
Equals ,
.
System.Attribute Match,
.
Equals .
Equals Match (
true , )
:
using System;
[Flags]
internal enum Accounts {
Savings = 0x0001,
Checking = 0x0002,
Brokerage = 0x0004
}
[AttributeUsage(AttributeTargets.Class)]
internal sealed class AccountsAttribute : Attribute {
private Accounts m_accounts;
public AccountsAttribute(Accounts accounts) {
m_accounts = accounts;
}
public override Boolean Match(Object obj) {
// Match
// Attribute,
// if (!base.Match(obj)) return false;
//
//
//
//
if

'this' null, obj null,



. , ,
Match
(obj == null) return false;

//
//
//
if


. , ,
Match
(this.GetType() != obj.GetType()) return false;

// obj
// . ,
//
AccountsAttribute other = (AccountsAttribute) obj;
//
//
//
if


, accounts 'this'
accounts others
((other.m_accounts & m_accounts) != m_accounts)

479

return false;
return true; //
}
public override Boolean Equals(Object obj) {
// Equals
// Object,
// if (!base.Equals(obj)) return false;
//
//
//
//
if

'this' null, obj null



. , ,
Equals
(obj == null) return false;

//
//
//
if


. , ,
Equals
(this.GetType() != obj.GetType()) return false;

// obj
// . ,
//
AccountsAttribute other = (AccountsAttribute) obj;
// 'this' other
if (other.m_accounts != m_accounts)
return false;
return true; //
}
// GetHashCode, Equals
public override Int32 GetHashCode() {
return (Int32) m_accounts;
}
}
[Accounts(Accounts.Savings)]
internal sealed class ChildAccount { }
[Accounts(Accounts.Savings | Accounts.Checking | Accounts.Brokerage)]
internal sealed class AdultAccount { }
public sealed class Program {
public static void Main() {
CanWriteCheck(new ChildAccount());
CanWriteCheck(new AdultAccount());
//
// , AccountsAttribute

480

18.
CanWriteCheck(new Program());

private static void CanWriteCheck(Object obj) {


//
Attribute checking = new AccountsAttribute(Accounts.Checking);
// ,
Attribute validAccounts =
obj.GetType().GetCustomAttribute<AccountsAttribute>(false);
// "Checking",
// ,
if ((validAccounts != null) && checking.Match(validAccounts)) {
Console.WriteLine("{0} types can write checks.", obj.GetType());
} else {
Console.WriteLine("{0} types can NOT write checks.", obj.GetType());
}
}
}

:
ChildAccount types can NOT write checks.
AdultAccount types can write checks.
Program types can NOT write checks.


,
Attribute
, . , ,
, Attribute . ,
GetCustomAttribute(s) Attribute
, . CLR
( , , ). ,
set ,
. .

System.Reflection.CustomAttributeData.
GetCustomAttributes,
. :

481

Assembly, Module, ParameterInfo, MemberInfo. System.Reflection,


23. CustomAttributeData ,
ReflectionOnlyLoad Assembly ( 23).
, , CLR
- , .
GetCustomAttributes CustomAttributeData -: CustomAttributeData
IList<CustomAttributeData>.
. CustomAttributeData
, , .
, Constructor ,
. ConstructorArguments ,
IList<CustomAttributeTyped
Argument>. NamedArguments ,
IList<CustomAttributeNamedArgument>.
, ,
set . .
, CustomAttributeData:
using
using
using
using

System;
System.Diagnostics;
System.Reflection;
System.Collections.Generic;

[assembly: CLSCompliant(true)]
[Serializable]
[DefaultMemberAttribute("Main")]
[DebuggerDisplayAttribute("Richter", Name="Jeff", Target=typeof(Program))]
public sealed class Program {
[Conditional("Debug")]
[Conditional("Release")]
public void DoSomething() { }
public Program() {
}
[CLSCompliant(true)]
[STAThread]
public static void Main() {
// ,
ShowAttributes(typeof(Program));

482

18.

//
MemberInfo[] members = typeof(Program).FindMembers(
MemberTypes.Constructor | MemberTypes.Method,
BindingFlags.DeclaredOnly | BindingFlags.Instance |
BindingFlags.Public | BindingFlags.Static,
Type.FilterName, "*");
foreach (MemberInfo member in members) {
// ,
ShowAttributes(member);
}
}
private static void ShowAttributes(MemberInfo attributeTarget) {
IList<CustomAttributeData> attributes =
CustomAttributeData.GetCustomAttributes(attributeTarget);
Console.WriteLine("Attributes applied to {0}: {1}",
attributeTarget.Name, (
attributes.Count == 0 ? "None" : String.Empty));
foreach (CustomAttributeData attribute in attributes) {
//
Type t = attribute.Constructor.DeclaringType;
Console.WriteLine(" {0}", t.ToString());
Console.WriteLine(" Constructor called={0}", attribute.Constructor);
IList<CustomAttributeTypedArgument> posArgs =
attribute.ConstructorArguments;
Console.WriteLine(" Positional arguments passed to constructor:" +
((posArgs.Count == 0) ? " None" : String.Empty));
foreach (CustomAttributeTypedArgument pa in posArgs) {
Console.WriteLine(" Type={0}, Value={1}",
pa.ArgumentType, pa.Value);
}
IList<CustomAttributeNamedArgument> namedArgs =
attribute.NamedArguments;
Console.WriteLine(" Named arguments set after construction:" +
((namedArgs.Count == 0) ? " None" : String.Empty));
foreach(CustomAttributeNamedArgument na in namedArgs) {
Console.WriteLine(" Name={0}, Type={1}, Value={2}",
na.MemberInfo.Name, na.TypedValue.ArgumentType,
na.TypedValue.Value);
}

Console.WriteLine();
}
Console.WriteLine();

483

:
Attributes applied to Program:
System.SerializableAttribute
Constructor called=Void .ctor()
Positional arguments passed to constructor: None
Named arguments set after construction: None
System.Diagnostics.DebuggerDisplayAttribute
Constructor called=Void .ctor(System.String)
Positional arguments passed to constructor:
Type=System.String, Value=Richter
Named arguments set after construction:
Name=Name, Type=System.String, Value=Jeff
Name=Target, Type=System.Type, Value=Program
System.Reflection.DefaultMemberAttribute
Constructor called=Void .ctor(System.String)
Positional arguments passed to constructor:
Type=System.String, Value=Main
Named arguments set after construction: None
Attributes applied to DoSomething:
System.Diagnostics.ConditionalAttribute
Constructor called=Void .ctor(System.String)
Positional arguments passed to constructor:
Type=System.String, Value=Release
Named arguments set after construction: None
System.Diagnostics.ConditionalAttribute
Constructor called=Void .ctor(System.String)
Positional arguments passed to constructor:
Type=System.String, Value=Debug
Named arguments set after construction: None
Attributes applied to Main:
System.CLSCompliantAttribute
Constructor called=Void .ctor(Boolean)
Positional arguments passed to constructor:
Type=System.Boolean, Value=True
Named arguments set after construction: None
System.STAThreadAttribute
Constructor called=Void .ctor()
Positional arguments passed to constructor: None
Named arguments set after construction: None
Attributes applied to .ctor: None

484

18.


,
. ,
.
. ,
Microsoft Visual Studio (FxCopCmd.exe) System.Diagnostics.
CodeAnalysis.SuppressMessageAttribute,
. ,
. ,
SuppressMessage ,
. , , ,
.
, System.Diagnostics.
ConditionalAttribute , (conditional
attribute). :
//#define TEST
#define VERIFY
using System;
using System.Diagnostics;
[Conditional("TEST")][Conditional("VERIFY")]
public sealed class CondAttribute : Attribute {
}
[Cond]
public sealed class Program {
public static void Main() {
Console.WriteLine("CondAttribute is {0}applied to Program type.",
Attribute.IsDefined(typeof(Program),
typeof(CondAttribute)) ? "" : "not ");
}
}

, CondAttribute,
,
TEST VERIFY.
.

19. Null-

, null;
.
. . ,
32- , FCL Int32.
, null,
.
.NET Framework, (CLR)
Int32 null.

Microsoft ADO.NET ,
null. , , System.Data.SqlTypes null- -
. , SqlDecimal 38 ,
Decimal 29. SqlString
, String.

: Java java.util.Date ,
, null. CLR
System.DateTime .
Java
- CLR, . Java null, CLR , .
, Microsoft CLR null-
(nullable value type). , ,
FCL System.Nullable<T>.
:
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct Nullable<T> where T : struct {
//
private Boolean hasValue = false; // null
internal T value = default(T); // ,
//

486

19. Null-

public Nullable(T value) {


this.value = value;
this.hasValue = true;
}
public Boolean HasValue { get { return hasValue; } }
public T Value {
get {
if (!hasValue) {
throw new InvalidOperationException(
"Nullable object must have a value.");
}
return value;
}
}
public T GetValueOrDefault() { return value; }
public T GetValueOrDefault(T defaultValue) {
if (!HasValue) return defaultValue;
return value;
}
public override Boolean Equals(Object other) {
if (!HasValue) return (other == null);
if (other == null) return false;
return value.Equals(other);
}
public override int GetHashCode() {
if (!HasValue) return 0;
return value.GetHashCode();
}
public override string ToString() {
if (!HasValue) return "";
return value.ToString();
}
public static implicit operator Nullable<T>(T value) {
return new Nullable<T>(value);
}

public static explicit operator T(Nullable<T> value) {


return value.Value;
}

, , null. Nullable<T> ,
, ,

C# null-

487

,
Boolean. , T Nullable

null.
, null- Int32, :
Nullable<Int32> x = 5;
Nullable<Int32> y = null;
Console.WriteLine("x: HasValue={0}, Value={1}", x.HasValue, x.Value);
Console.WriteLine("y: HasValue={0}, Value={1}",
y.HasValue, y.GetValueOrDefault());

:
x: HasValue=True, Value=5
y: HasValue=False, Value=0

C# null-

x y
Nullable<Int32> . , C# null- ,
.
C# .
x y , :
Int32? x = 5;
Int32? y = null;

C# Int32? Nullable<Int32>.
, null-
. C# null- . .
private static void ConversionsAndCasting() {
// Int32 Nullable<Int32>
Int32? a = 5;
// 'null' Nullable<Int32>
Int32? b = null;
// Nullable<Int32> Int32
Int32 c = (Int32) a;
//

488

19. Null-

// null-
Double? d = 5; // Int32->Double? (d 5.0 double)
Double? e = b; // Int32?->Double? (e null)
}

C# null- .
:
private static void Operators() {
Int32? a = 5;
Int32? b = null;
// (+ ++ - -- ! ~)
a++; // a = 6
b = -b; // b = null
// (+ - * / % & | ^ << >>)
a = a + 3; // a = 9
b = b * 3; // b = null;
//
if
if
if

(== !=)
(a == null) { /* */ } else { /* */ }
(b == null) { /* */ } else { /* */ }
(a != b) { /* */ } else { /* */ }

// (<> <= >=)


if (a < b) { /* */ } else { /* */ }
}

C#:
(+++, -, --, ! , ~). null,
null.
(+, -, *, /, %, &, |, ^, <<, >>). null,
.
& | ?.
SQL.
null, ,
null, null.
, null .
,
true, false null.
(==, !=). null,
. , .
null, .
(<, >, <=, >=). null , false.
null, .

C# null-
1
2
True

False

Null

true

false

null

& = true

& = false

& = null

| = true

| = true

| = true

& = false

& = false

& = false

| = true

| = false

| = null

& = null

& = false

& = null

| = true

| = null

| = null

489

, null-
. , :
private static Int32? NullableCodeSize(Int32? a, Int32? b) {
return a + b;
}

IL-,
null-
. C#:
private static Nullable<Int32> NullableCodeSize(Nullable<Int32> a,

Nullable<Int32> b) {
Nullable<Int32> nullable1 = a;
Nullable<Int32> nullable2 = b;
if (!(nullable1.HasValue & nullable2.HasValue)) {
return new Nullable<Int32>();
}
return new Nullable<Int32>(
nullable1.GetValueOrDefault() + nullable2.GetValueOrDefault());


, . , ,
8. null-
, . , Point,
== !=:
using System;
internal struct Point {
private Int32 m_x, m_y;
public Point(Int32 x, Int32 y) { m_x = x; m_y = y; }
public static Boolean operator==(Point p1, Point p2) {

490

19. Null-
return (p1.m_x == p2.m_x) && (p1.m_y == p2.m_y);

public static Boolean operator!=(Point p1, Point p2) {


return !(p1 == p2);
}
}

null- Point,
:
internal static
public static
Point? p1 =
Point? p2 =

class Program {
void Main() {
new Point(1, 1);
new Point(2, 2);

Console.WriteLine("Are points equal? " + (p1 == p2).ToString());


Console.WriteLine("Are points not equal? " + (p1 != p2).ToString());

:
Are points equal? False
Are points not equal? True


null
C# null- (null-coalescing
operator). ?? .
null, . . null- .
, null- .
:
private static void NullCoalescingOperator() {
Int32? b = null;
// :
// x = (b.HasValue) ? b.Value : 123
Int32 x = b ?? 123;
Console.WriteLine(x); // "123"
// :
// String temp = GetFilename();

CLR null-

491

// filename = (temp != null) ? temp : "Untitled";


String filename = GetFilename() ?? "Untitled";

null-
?. ?? . -,
:
Func<String> f = () => SomeMethod() ?? "Untitled";

, ,
:
Func<String> f = () => { var temp = SomeMethod();
return temp != null ? temp : "Untitled";};

-, ?? :
String s = SomeMethod1() ?? SomeMethod2() ?? "Untitled";

, ,
:
String s;
var sm1 = SomeMethod1();
if (sm1 != null) s = sm1;
else {
var sm2 = SomeMethod2();
if (sm2 != null) s = sm2;
else s = "Untitled";
}

CLR null-

CLR null- .
, GetType
.
null- CLR.
. CLR .

null-
Nullable<Int32>,
null. ,
Object,

492

19. Null-

Nullable<Int32>. null , Nullable<Int32> null.

CLR , null-
.
Nullable<T> null
null.
CLR . , Nullable<Int32>
5 Int32 .
:
// Nullable<T> null T
Int32? n = null;
Object o = n; // o null
Console.WriteLine("o is null={0}", o == null); // "True"
n = 5;
o = n; // o Int32
Console.WriteLine("o's type={0}", o.GetType()); // "System.Int32"

null-
CLR T T Nullable<T>.
null
Nullable<T>, CLR Nullable<T> null. :
// Int32
Object o = 5;
// Nullable<Int32> Int32
Int32? a = (Int32?) o; // a = 5
Int32 b = (Int32) o; // b = 5
// , null
o = null;
// "" Nullable<Int32> Int32
a = (Int32?) o; // a = null
b = (Int32) o; // NullReferenceException

GetType null-

GetType Nullable<T> CLR T


Nullable<T>. :
Int32? x = 5;
// "System.Int32", "System.Nullable<Int32>"
Console.WriteLine(x.GetType());

CLR null-

493

null-

n Nullable<Int32> IComparable<Int32>. Nullable<T>
Int32 IComparable<Int32>.
, CLR , ,
.
Int32? n = 5;
Int32 result = ((IComparable) n).CompareTo(5); //
//
Console.WriteLine(result); // 0

CLR
null- .
:
Int32 result = ((IComparable) (Int32) n).CompareTo(5); //

IV

20. . .. 496
21.
() . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..554
22. CLR . .. .. .. ..606
23. . .. .. .. .. .. .. .. .. 636
24. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 666
25.
WinRT. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 698

20.

(exception handling),
. cc
. , .
, , , .
,
. ,
, . , ,
, - .
, CLR,
.
Microsoft
, , . ,
, , , ,
,
. .


, ,
. , FileStream StringBuilder. , ,
.. ( , ,
..) .
.
, Read, Write, Flush, Append, Insert, Remove
.. ,
. :
internal sealed class Account {
public static void Transfer(Account from, Account to, Decimal amount) {
from -= amount;
to += amount;
}
}

497

Transfer Account Decimal, ,


. ,
.
, . , from
to null; from to
; , , ; ,
; amount
0,
.
Transfer
, .
, void.
Transfer ,
, .
- , , , :
Boolean f = "Jeff".Substring(1, 1).ToUpper().EndsWith("E"); // true

, 1.
, . ,
, ,
"E". , . , ,
. , - .
- , / , / ,
, ,
. -
. .NET Framework
,
(exception handling).

,
. ,
: , .
, Read .
. ,
Read, , .

C# .

498

20.
,
. , ,
. ,
,
.


C#,
, . ,
.
.NET Framework
C#. , .NET
Framework (Structured Exception
Handling, SEH) Windows. SEH ,
Windows via C/C++ (Microsoft Press,2007).
, .
. try,
catch finally.
private void SomeMethod() {
try {
// ,
//
}
catch (InvalidOperationException) {
//
// InvalidOperationException
}
catch (IOException) {
//
// IOException
}
catch {
// .
//
//
throw;
}
finally {
// ,
// , try.
//
}

499

// , finally, , try
//
// catch,
}


. .
, try
finally try catch.
.

try
try , / . finally. try
, .
catch. catch
,
. try
catch finally; , C#
.

,
try. .
try ,
, ,
try.

catch
catch , .
try catch,
. try , CLR
catch.
, finally ( , , ). finally, ,
.
catch (catch type). C# System.Exception .
catch
InvalidOperationException ( ) IOException (, ,
). ( -

500

20.

) .
catch System.Exception, ,
, , .

catch Microsoft Visual Studio


$exception.

catch CLR ,
. ,
( ) , , System.Exception (
).
,
.
, try ( ), catch
. CLR
, . catch ,
. .
catch CLR
finally, try,
, catch .
finally catch,
.
finally ,
catch.
. :
,
;
, ;
catch .
, , . CLR
:
catch, .

501

finally ( , ,
). finally . finally , , catch.
C# , , System.
Exception. catch
(, ,
). , ,
,
. , Exception
.

FirstChanceException AppDomain , CLR .


22.

finally
finally 1. try. try , finally
:
private void ReadData(String pathname) {
FileStream fs = null;
try {
fs = new FileStream(pathname, FileMode.Open);
//
}
catch (IOException) {
// IOException
}
finally {
//
if (fs != null) fs.Close();
}
}


ThreadAbortException, finally. TerminateThread FailFast System.Environment,
finally . , Windows ,
.
1

502

20.

try , . ,
finally,
.
finally,
( ).
try finally,
. finally,
catch. , try
finally.
finally, ,
. , finally
. , , try. catch finally
( ) .
, .
.
, , . ,
,
( , ).
catch finally, CLR , finally.
,
try. ( ), . CLR , .
, , .
, .
. - ,
, .
. ,
, , :
void Method() {
try {
...
}

void Method() {
try {
...
}

catch (XxxException) {
...
}
catch (YyyException) {
...
}
catch {
...; throw;
}
finally {
...
}

503

handle (XxxException) {
...
}
handle (YyyException) {
...
}
compensate {
...; throw;
}
cleanup {
...
}

CLS- CLS-
, CLR,
Exception, (Common Language Specification, CLS). , CLR
,
CLS String, Int32 DateTime.
C# , Exception,
.
, , ,
Exception. CLR2.0 catch
CLS- . C# , , CLS- ,
, .
2.0, CLR RuntimeWrappedException, System.Runtime.CompilerServices .
Exception, CLS-
. Object,
WrappedException
. CLR2.0 CLS- RuntimeWrappedException,
. CLS CLS-. ,
Exception,
, .
2.0 CLS- :

504

20.

private void SomeMethod() {


try {
// try ,
//
}
catch (Exception e) {
// C# 2.0 CLS-
// C# 2.0
// CLS-
throw; //
}
catch {
// C#
// , CLS
throw; //
}
}

, CLR , catch ( ),
.
CLR2.0, catch , (CS1058: catch
. System.Runtime.
CompilerServices.RuntimeWrappedException):
CS1058: A previous catch clause already catches all exceptions. All non-exceptions
thrown will be wrapped in a System.Runtime.CompilerServices.RuntimeWrappedException

.NET Framework 2.0. , catch. . CLR,


, catch (Exception) RuntimeWrappedException. ,
CLR CLS-
catch, . CLR ,
RuntimeCompatibilityAttribute, , :
using System.Runtime.CompilerServices;
[assembly:RuntimeCompatibility(WrapNonExceptionThrows = false)]

.
. ( CLR
System.Runtime.CompilerServices.RuntimeWrappedException),
( CLR ).

System.Exception

505

System.Exception
CLR
Int32 String. Microsoft , . ,
System.Exception.
CLS- .
CLS- , System.
Exception. C#
CLS- .
System.Exception ,
.20.1. ,
.
- .
20.1. System.Exception

Message

String

.
,
.
, ,

Data

IDictionary

. , ,
.


Source

String

StackTrace

String

, .

TargetSite

MethodBase

506

20.

20.1 ()

HelpLink

String


(, file://C:\
MyApp\Help.htm#MyExceptionHelp).
,

InnerException

Exception

, .

null. Exception GetBaseException,

HResult

Int32

32- ,
. , COM
API HRESULT,
CLR , Exception, HRESULT

StackTrace System.Exception. catch -

, .
,
, .
CLR,
. , Exception, StackTrace
null. ,
, null.
CLR . catch , CLR ,
. catch StackTrace
, , CLR, ,
, , ,
.

System.Exception

507

CLR . CLR .

, , CLR :
private void SomeMethod() {
try { ... }
catch (Exception e) {
...
throw e; // CLR ,
// FxCop
}
}

,
throw
. :
private void SomeMethod() {
try { ... }
catch (Exception e) {
...
throw; // CLR .
// FxCop
}
}

, , CLR,
. , Windows .
Windows
, CLR ,
.
. , ,
:
private void SomeMethod() {
Boolean trySucceeds = false;
try {
...
trySucceeds = true;
}
finally {
if (!trySucceeds) { /* */ }
}
}

508

20.

, StackTrace, ,
catch.

System.Diagnostics.StackTrace. ,
.
, StackTrace.

StackTrace. StackTrace,
, Exception.
CLR
( pdb), ,
StackTrace System.Exception ToString System.
Diagnostics.StackTrace, .
.
,
.
. -, ,
, . -, JIT-
(inline) , ,
. ( C#)
/debug. , JIT-
.
.

JIT- System.Diagnostics.
DebuggableAttribute. C# . DisableOptimizations JIT-
. C# .
/debug. System.Runtime.CompilerServices.
MethodImplAttribute, ,
. , :
using System;
using System.Runtime.CompilerServices;
internal sealed class SomeType {
[MethodImpl(MethodImplOptions.NoInlining)]
public void SomeMethod() {
...
}
}

, FCL

509

, FCL
Framework Class Library ( System.Exception). ,
MSCorLib.dll, ;
( , 23).
System.Exception
System.AggregateException
System.ApplicationException
System.Reflection.InvalidFilterCriteriaException
System.Reflection.TargetException
System.Reflection.TargetInvocationException
System.Reflection.TargetParameterCountException
System.Threading.WaitHandleCannotBeOpenedException
System.Diagnostics.Tracing.EventSourceException
System.InvalidTimeZoneException
System.IO.IsolatedStorage.IsolatedStorageException
System.Runtime.CompilerServices.RuntimeWrappedException
System.SystemException
System.Threading.AbandonedMutexException
System.AccessViolationException
System.Reflection.AmbiguousMatchException
System.AppDomainUnloadedException
System.ArgumentException
System.ArgumentNullException
System.ArgumentOutOfRangeException
System.Globalization.CultureNotFoundException
System.Text.DecoderFallbackException
System.DuplicateWaitObjectException
System.Text.EncoderFallbackException
System.ArithmeticException
System.DivideByZeroException
System.NotFiniteNumberException
System.OverflowException
System.ArrayTypeMismatchException
System.BadImageFormatException
System.CannotUnloadAppDomainException
System.ContextMarshalException
System.Security.Cryptography.CryptographicException
System.Security.Cryptography.CryptographicUnexpectedOperationException
System.DataMisalignedException
System.ExecutionEngineException
System.Runtime.InteropServices.ExternalException
System.Runtime.InteropServices.COMException
System.Runtime.InteropServices.SEHException
System.FormatException
System.Reflection.CustomAttributeFormatException
System.Security.HostProtectionException

510

20.
System.Security.Principal.IdentityNotMappedException
System.IndexOutOfRangeException
System.InsufficientExecutionStackException
System.InvalidCastException
System.Runtime.InteropServices.InvalidComObjectException
System.Runtime.InteropServices.InvalidOleVariantTypeException
System.InvalidOperationException
System.ObjectDisposedException
System.InvalidProgramException
System.IO.IOException
System.IO.DirectoryNotFoundException
System.IO.DriveNotFoundException
System.IO.EndOfStreamException
System.IO.FileLoadException
System.IO.FileNotFoundException
System.IO.PathTooLongException
System.Collections.Generic.KeyNotFoundException
System.Runtime.InteropServices.MarshalDirectiveException
System.MemberAccessException
System.FieldAccessException
System.MethodAccessException
System.MissingMemberException
System.MissingFieldException
System.MissingMethodException
System.Resources.MissingManifestResourceException
System.Resources.MissingSatelliteAssemblyException
System.MulticastNotSupportedException
System.NotImplementedException
System.NotSupportedException
System.PlatformNotSupportedException
System.NullReferenceException
System.OperationCanceledException
System.Threading.Tasks.TaskCanceledException
System.OutOfMemoryException
System.InsufficientMemoryException
System.Security.Policy.PolicyException
System.RankException
System.Reflection.ReflectionTypeLoadException
System.Runtime.Remoting.RemotingException
System.Runtime.Remoting.RemotingTimeoutException
System.Runtime.InteropServices.SafeArrayRankMismatchException
System.Runtime.InteropServices.SafeArrayTypeMismatchException
System.Security.SecurityException
System.Threading.SemaphoreFullException
System.Runtime.Serialization.SerializationException
System.Runtime.Remoting.ServerException
System.StackOverflowException
System.Threading.SynchronizationLockException
System.Threading.ThreadAbortException
System.Threading.ThreadInterruptedException
System.Threading.ThreadStartException
System.Threading.ThreadStateException

511

System.TimeoutException
System.TypeInitializationException
System.TypeLoadException
System.DllNotFoundException
System.EntryPointNotFoundException
System.TypeAccessException
System.TypeUnloadedException
System.UnauthorizedAccessException
System.Security.AccessControl.PrivilegeNotHeldException
System.Security.VerificationException
System.Security.XmlSyntaxException
System.Threading.Tasks.TaskSchedulerException
System.TimeZoneNotFoundException

Microsoft System.Exception
, , System.SystemException System.ApplicationException, . , , CLR, SystemException,
, ,
ApplicationException. catch, CLR-, .
; Exception (IsolatedStorage
Exception), CLR- ApplicationException
(TargetInvocationException),
SystemException (FormatException). - SystemException
ApplicationException .
Microsoft ,
, , .


,
.
.
-, , Exception
. .
, , ,
,
. ,
FCL, , . ,
System.Exception.

512

20.

, ,
. ,
,
. , System.Exception
1.

,
.
, , ,
. , .
, ,
, .
.
, .
.
, , .

-, ,
.
, . .
, ,
.
,
.
. , , ,
.
,
( , FCL- FCL-
), . ,
, ,
. Microsoft
, FCL.

System.Exception , , , .
1

513


, . , , Exception,
, ,
.
, 24, Exception<TExceptionArgs>:
[Serializable]
public sealed class Exception<TExceptionArgs> : Exception, ISerializable
where TExceptionArgs : ExceptionArgs {
private const String c_args = "Args"; // ()
private readonly TExceptionArgs m_args;
public TExceptionArgs Args { get { return m_args; } }
public Exception(String message = null, Exception innerException = null)
: this(null, message, innerException) { }
public Exception(TExceptionArgs args, String message = null,
Exception innerException = null): base(message, innerException) {
m_args = args; }
// ; ,
// .
[SecurityPermission(SecurityAction.LinkDemand,
Flags=SecurityPermissionFlag.SerializationFormatter)]
private Exception(SerializationInfo info, StreamingContext context)
: base(info, context) {
m_args = (TExceptionArgs)info.GetValue(
c_args, typeof(TExceptionArgs));
}
// ; - ISerializable
[SecurityPermission(SecurityAction.LinkDemand,
Flags=SecurityPermissionFlag.SerializationFormatter)]
public override void GetObjectData(
SerializationInfo info, StreamingContext context) {
info.AddValue(c_args, m_args);
base.GetObjectData(info, context);
}
public override String Message {
get {
String baseMsg = base.Message;
return (m_args == null) ? baseMsg : baseMsg + " (" + m_args.Message + ")";
}
}

514

20.

public override Boolean Equals(Object obj) {


Exception<TExceptionArgs> other = obj as Exception<TExceptionArgs>;
if (obj == null) return false;
return Object.Equals(m_args, other.m_args) && base.Equals(obj);
}
public override int GetHashCode() { return base.GetHashCode(); }
}

ExceptionArgs,
TExceptionArgs. :
[Serializable]
public abstract class ExceptionArgs {
public virtual String Message { get { return String.Empty; } }
}

, . , ,
, :
[Serializable]
public sealed class DiskFullExceptionArgs : ExceptionArgs {
private readonly String m_diskpath; // ,
//
public DiskFullExceptionArgs(String diskpath) { m_diskpath = diskpath; }
// ,
//
public String DiskPath { get { return m_diskpath; } }
// Message
public override String Message {
get {
return (m_diskpath == null) ? base.Message : "DiskPath=" + m_diskpath;
}
}
}

, :
[Serializable]
public sealed class DiskFullExceptionArgs : ExceptionArgs { }

, :
public static void TextException() {
try {
throw new Exception<DiskFullExceptionArgs>(
new DiskFullExceptionArgs(@"C:\"), "The disk is full");

515

}
catch (Exception<DiskFullExceptionArgs> e) {
Console.WriteLine(e.Message);
}
}

Exception<TExceptionArgs>.
-,
System.Exception. , ,
. -,
, Visual Studio ,
Exception<T>, .


1975 .
BASIC,
. C,
. , ,
.
,
,
.
.
( new C++ malloc, HeapAlloc, VirtualAlloc
..), , ,
. , ,

516

20.


.
- .NET Framework
.
,
catch OutOfMemoryException.
, , , CLR . , .
,
,
. .
, . ,
, ,
, .
- . , , .
, :
Boolean f = "Jeff".Substring(1, 1).ToUpper().EndsWith("E");

,
, . ,
. , Win32 COM,
true false .
, . ,
:
;
;
;
;
;
;
;
,
-;
(closure) -
;
, ;

517

LINQ (Language Integrated Queries).


CLR . , CLR
:
;
JIT- , FileLoadException , BadImageFormatException ,
InvalidProgramException, FieldAccessException, MethodAccessException,
MissingFieldException, MissingMethodException VerificationException;
, MarshalByRefObject,
AppDomainUnloadedException;

;
ThreadAbortException
Thread.Abort AppDomain.Unload;
Finalize,
;
;
, TypeInitializationException;
, OutOfMemoryException ,
DivideByZeroException, NullReferenceException, RuntimeWrappedException,
TargetInvocationException, OverflowException, NotFiniteNumberException,
ArrayTypeMismatchException, DataMisalignedException, IndexOutOfRange
Exception, InvalidCastException, RankException, SecurityException
.
, , .NET Framework , , ,
. -, -,
, ,
,
. . ,
. catch
, .
- , , CLR

518

20.

.NET Framework
1. ,
, .
, : , . , , ,
, . ,
:
private static Object OneStatement(Stream stream, Char charToFind) {
return (charToFind + ": " + stream.GetType() + String.Empty
+ (stream.Position + 512M))
.Where(c=>c == charToFind).ToArray();
}

C#,
. IL-,
C# ( ,
, ):
.method private hidebysig static object OneStatement(
class [mscorlib]System.IO.Stream stream, char charToFind) cil managed {
.maxstack 4
.locals init (
[0] class Program/<>c__DisplayClass1 V_0,
[1] object[] V_1)
IL_0000: newobj instance void Program/<>c__DisplayClass1::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldarg.1
IL_0008: stfld char Program/<>c__DisplayClass1::charToFind
IL_000d: ldc.i4.5
IL_000e: newarr [mscorlib]System.Object
IL_0013: stloc.1
IL_0014: ldloc.1
IL_0015: ldc.i4.0
IL_0016: ldloc.0
IL_0017: ldfld char Program/<>c__DisplayClass1::charToFind
IL_001c: box [mscorlib]System.Char
IL_0021: stelem.ref
IL_0022: ldloc.1
IL_0023: ldc.i4.1
IL_0024: ldstr ": "
IL_0029: stelem.ref
IL_002a: ldloc.1
IL_002b: ldc.i4.2

,
Visual Studio, IntelliSense, ,
, , .
, .
1

519

IL_002c: ldarg.0
IL_002d:
callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
IL_0032: stelem.ref
IL_0033: ldloc.1
IL_0034: ldc.i4.3
IL_0035: ldsfld string [mscorlib]System.String::Empty
IL_003a: stelem.ref
IL_003b: ldloc.1
IL_003c: ldc.i4.4
IL_003d: ldarg.0
IL_003e: callvirt
instance int64 [mscorlib]System.IO.Stream::get_Position()
IL_0043: call
valuetype [mscorlib]System.Decimal
[mscorlib]System.Decimal::op_Implicit(int64)
IL_0048: ldc.i4
0x200
IL_004d: newobj
instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0052: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::
op_Addition
(valuetype [mscorlib]System.Decimal,
valuetype [mscorlib]System.Decimal)
IL_0057: box [mscorlib]System.Decimal
IL_005c: stelem.ref
IL_005d: ldloc.1
IL_005e: call string [mscorlib]System.String::Concat(object[])
IL_0063: ldloc.0
IL_0064: ldftn instance bool Program/<>c__DisplayClass1::<OneStatement>b__0(char)
IL_006a: newobj instance
void [mscorlib]System.Func`2<char, bool>::.ctor(object, native int)
IL_006f: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>
[System.Core]System.Linq.Enumerable::Where<char>(
class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>,
class [mscorlib]System.Func`2<!!0, bool>)
IL_0074: call !!0[] [System.Core]System.Linq.Enumerable::ToArray<char>
(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
IL_0079: ret
}

, OutOfMemoryException
<>c__DisplayClass1 ( ),
Object[], Func, char Decimal. Concat, Where ToArray.
Decimal
, TypeInitializationException1.
op_Implicit op_Addition
Decimal, ,
OverflowException.
, System.Char, System.String, System.Type
System.IO.Stream
TypeInitializationException, .
1

520

20.

Position Stream.
, , OneStatement
, ,
. , Stream Marshal
ByRefObject, stream -,
.
,
AppDomainUnloadedException.
, ,
Microsoft. ,
Microsoft ,
, OneStatement . ?
, : catch , ,
.
, , , ,
, .
, . ,
.
.
,
. ,
. ,
( ),
. , , ,
,
, System.
Exception, . , ,
.
Account, Transfer
. ,
,
. System.Exception ,
: from, to ,
. , ,
. ,
, , .

521

, Transfer
System.Exception from.
- Transfer.

,
, . , , .

,
. , ,
, , Transfer - SecurityException
OutOfMemoryException. , Win32 : true false,
. ,
. , , GetLastError. System.Exception
Source, .
String, . ,
, Source , .
, StackTrace
Exception. - ,
.

,
:
CLR
catch finally. Transfer
:
public static void Transfer(Account from, Account to, Decimal amount) {
try { /* */ }
finally {
from -= amount;
// (- Thread.Abort/AppDomain.Unload)
//
to += amount;
}
}


finally!
.
System.Diagnostics.Contracts.Contract
. -

522

20.

/
. ( ). ,
. .
(CER) CLR . , try
catch finally . , CLR catch finally,
.
( FileLoadException ,
BadImageFormatException, InvalidProgramException, FieldAccessException,
MethodAccessException, MissingFieldException MissingMethodException),

( catch) ( finally).
OutOfMemoryException .
.
,
, ,
. ,
. Windows
( NTFS),
. , .NET
Framework .
P/Invoke. System.
Transactions.TransactionScope.
. , Monitor / :
public static class SomeType {
private static Object s_myLockObject = new Object();
public static void SomeMethod () {
Monitor.Enter(s_myLockObject); //
// ? ,
// !
try {
//
}
finally {
Monitor.Exit(s_myLockObject);
}
}
// ...
}

523

-
Enter Monitor. :
public static class SomeType {
private static Object s_myLockObject = new Object();
public static void SomeMethod () {
Boolean lockTaken = false; // ,
try {
// !
Monitor.Enter(s_myLockObject, ref lockTaken);
//
}
finally {
// ,
if (lockTaken) Monitor.Exit(s_myLockObject);
}
}
// ...
}

, .
30.
, , , , .
, .
, .
, ,
Unload AppDomain ( .22).
, , , FailFast
Environment:
public static void FailFast(String message);
public static void FailFast(String message, Exception exception);

try/finally
Finalize. .
FailFast ,
CriticalFinalizerObject, 21.
, .
Windows, ,
CLR . FailFast
Windows, .
.

524

20.

FCL- . ,
FCL-, FCL- .

, CLR.
,
.
, (, ),
. Microsoft Exchange Server
,
. Extensible Storage Engine,
Windows C:\Windows\System32\EseNT.dll.
.
,
.
.
,
,
.


,
. ,
.
, .

,
, . ,
. : ,
, .
, . , ,
. , ,
.

525

. , , (.
). ,
.
, ,

.
, ,
. , , .
,
. (,
) .

finally
-, finally ! ,

. finally , ,
, . finally
. ,
( ):
using System;
using System.IO;
public sealed class SomeType {
private void SomeMethod() {
//
FileStream fs = new FileStream(@"C:\Data.bin ", FileMode.Open);
try {
// 100
Console.WriteLine(100 / fs.ReadByte());
}
finally {
// finally ,
// ,
// (, 0)
fs.Close();
}
}
}

,
. , C# lock, using foreach

526

20.

try/finally .
( Finalize).
try,
finally. :
lock, finally
;
using, finally
Dispose;
foreach, finally
IEnumerator Dispose;
, finally
Finalize .
, C#

using. ,

:
using System;
using System.IO;
internal sealed class SomeType {
private void SomeMethod() {
using (FileStream fs =
new FileStream(@"C:\Data.bin", FileMode.Open)) {
// 100
Console.WriteLine(100 / fs.ReadByte());
}
}
}

using 21,

lock 30.


catch. , , ,
, . ,
.
.
:
try {
// , , ,
// ...
}

527

catch (Exception) {
...
}

,
.
? : , . ,
,
. , ,
, , .
,
.
, CLR . . .
, , ,
.
, , ,
.

, , , . ,
, .
, FailFast System.
Environment.

, System.Exception catch ,
. (
) System.Exception ,

, .
Microsoft FxCopCmd.exe catch (Exception),
throw.
.
, , ,
.

528

20.

(.28). ,
, , CLR
, .
EndXxx, .
EndXxx , ,
. ,
, EndXxx,
.


, . , ,

. ( ):
public String CalculateSpreadsheetCell(Int32 row, Int32 column) {
String result;
try {
result = /* */
}
catch (DivideByZeroException) {
result = " : ";
}
catch (OverflowException) {
result = " : ";
}
return result;
}

,
.
. 0, CLR
DivideByZeroException. , .
.
, CLR
OverflowException, ,
.
, , . System.Exception
( ),
, try (
OutOfMemoryException StackOverflowException).

529


, ,
. , .
10 (, -
- Serializable
). ,
? ,
. ,
,
.
:
public void SerializeObjectGraph(FileStream fs,
IFormatter formatter, Object rootObj) {
//
Int64 beforeSerialization = fs.Position;
try {
//
formatter.Serialize(fs, rootObj);
}
catch { //
//
fs.Position = beforeSerialization;
//
fs.SetLength(fs.Position);
// : finally,
//
// ,
//
throw;
}
}


. , ,
, .
, . . # :
throw , .

530

20.

,
catch, . , C# , throw
.


.
. (
).
PhoneBook, :
internal sealed class PhoneBook {
private String m_pathname; //
//
public String GetPhoneNumber(String name) {
String phone;
FileStream fs = null;
try {
fs = new FileStream(m_pathname, FileMode.Open);
// fs
phone = /* */
}
catch (FileNotFoundException e) {
// , ,
//
throw new NameNotFoundException(name, e);
}
catch (IOException e) {
// , ,
//
throw new NameNotFoundException(name, e);
}
finally {
if (fs != null) fs.Close();
}
return phone;
}
}

( ), PhoneBook ,
, . ,
- ,
FileNotFoundException IOException,
. ,
; , ,

531

, . GetPhoneNumber

NameNotFoundException.
, . ,
, .
,
, NameNotFoundException
.
FileNotFoundException IOException,
,
PhoneBook.

, .
-, , .
, . -, . FileNotFoundException
, StackTrace ,
FileStream. NameNotFoundException, ,
catch,
. ,
.

, PhoneBook .
PhoneBookPathname,
, . ,
, GetPhoneNumber ,
, . : GetPhoneNumber,
PhoneBook. ,
PhoneBook.

.
.
, Data :
private static void SomeMethod(String filename) {
try {
// - }
catch (IOException e) {

532

20.

// IOException
e.Data.Add("Filename", filename);
throw; //
}
}

: , , CLR,
TypeInitializationException. , CLR
1. DivideByZeroException,
. , . CLR DivideByZeroException
TypeInitializationException, ,
, .
, .
CLR
TargetInvocationException .
TargetInvocationException InnerException.
, , , :
private static void Reflection(Object o) {
try {
// DoSomething
var mi = o.GetType().GetMethod("DoSomething");
mi.Invoke(o, null); // DoSomething
}
catch (System.Reflection.TargetInvocationException e) {
// CLR TargetInvocationException
throw e.InnerException; //
}
}

, .
C# ( 5),
TargetInvocationException; .
.

8.
1

533


, CLR
catch, . catch
, (unhandled
exception). , CLR
.
, ,
.
, ,
.
. ,
,
. Microsoft
CLR, . Windows .
, Event Viewer
Windows LogsApplication, 20.1.

. 20.1. Windows Event ,.


-

Windows Reliability Monitor, Windows.

534

20.

, .20.2, , - .

. 20.2. Reliability Monitor ,.


-

. 20.3. Reliability Monitor .


535


Reliability Monitor. .20.3,
.20.2. ,
, CLR20r3.
20.2.

01

( 32 )

02

03

04

( 64 )

05

06

07

. MethodDef ( 0x06), , . ,
ILDasm.exe

08

IL- . ,
ILDasm.exe

09

( 32 )

Windows
,
Microsoft1. Windows
Error Reporting.
Windows Quality (http://WinQual.Microsoft.com).
Microsoft . ,
, VeriSignID (
Authenticode).
,
, . CLR,
, P/Invoke
Win32 SetErrorMode SEM_NOGPFAULTERRORBOX.
1

536

20.

, , -
.
, Microsoft
.
FCL ( . ):
UnhandledException System.App
Domain. Windows Store Microsoft Silverlight
.
Windows Store UnhandledException Windows.UI.Xaml.Application.
Windows Forms OnThreadException
System.Windows.Forms.NativeWindow,
System.Windows.Forms.Application ThreadException
System.Windows.Forms.Application.
Windows Presentation Foundation (WPF)
DispatcherUnhandledException System.Windows.Application,
UnhandledException UnhandledExceptionFilter System.
Windows.Threading.Dispatcher.
Silverlight UnhandledException System.
Windows.Application.
ASP.NET Web Form Error System.Web.
UI.TemplateControl. TemplateControl System.Web.
UI.Page System.Web.UI.UserControl. , Error System.Web.HTTPApplication.
Windows Communication Foundation ErrorHandlers
System.ServiceModel.Dispatcher.ChannelDispatcher.

, ,
- -. ,
,
, . ,
. ,
( , , Microsoft SQL Server),
.

, , . ,
,
.

537

CLR , ,
(Corrupted State Exceptions, CSE).
, CLR ,
. CLR
finally .
CSE- Win32.
EXCEPTION_ACCESS_VIOLATION

EXCEPTION_STACK_OVERFLOW

EXCEPTION_ILLEGAL_INSTRUCTION

EXCEPTION_IN_PAGE_ERROR

EXCEPTION_INVALID_DISPOSITION

EXCEPTION_NONCONTINUABLE_EXCEPTION

EXCEPTION_PRIV_INSTRUCTION

STATUS_UNWIND_CONSOLIDATE

,
, ,
System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions
Attribute. , System.Security.
SecurityCriticalAttribute. ,
, legacyCorruptedStateExceptionPolicy XML- true. CLR System.Runtime.InteropServices.SEHException.
EXCEPTION_ACCESS_VIOLATION System.
AccessViolationException, EXCEPTION_STACK_OVERFLOW
System.StackOverflowException.

EnsureSufficientExecutionStack
RuntimeHelper
( ).
, InsufficientExecutionStackException,
. EnsureSufficientExecutionStack
void. .


Microsoft Visual Studio :
Exceptions Debug , .20.4.

538

20.

. 20.4. Exceptions

, Visual Studio.
Common Language Runtime Exceptions, .20.5,
, Visual Studio.

. 20.5. CLR-, ,.
Exceptions Visual Studio

, .20.6, , System.Exception.
- Thrown,
. CLR
catch. , .
, ,
, ,
, .
Thrown , ,
-

539

. ,
, ,
.

. 20.6. Exceptions Visual Studio CLR-,


System

,
Add. ,
.20.7.

. 20.7. Visual Studio

Common Language Runtime Exceptions,


.
System.Exception, , CLS,
.
, , . ,
.
, . ,

Visual Studio , Exception.

.

540

20.


,
, . , .
, - . , ? ,
true false,
? enum?
. CLR
, .
.

( HRESULT,
..). ,
, ,
, , .
, .
.
++ , . ,

. , ,
, , ,
.
,
,
. , , , , ,
.
. ,
++ ,
,
.

, .
-,
. , , , ,
, , .

541

, ,
, .
, ,
.
, ,
.NET Framework. , , JIT-
x86, , JIT- IA64 JIT-
.NET Compact Framework.

JIT- Microsoft,
. .
, ,
, .
- . ,
.
, , Windows.
.20.8 , , .NET Framework.

. 20.8. .NET CLR

- ,
.

542

20.

- .
, Microsoft ,
Parse Int32 ,
, . Parse ,
.
,
, Microsoft Int32
TryParse, :
public static Boolean TryParse(String s, out Int32 result);
public static Boolean TryParse(String s, NumberStyles styles,
IFormatProvider, provider, out Int32 result);

, Boolean, ,
, Int32.
result. true, result
32- . 0,
.
: TryXxx
false .
. , TryParse Int32
ArgumentException. , OutOfMemoryException,
TryParse .
, - , . ,
, , . ,
.
, , , .
,
.
, -
,
TryXxx. , , , ,
TryXxx, . ,
,
, .

543


. , , , Notepad.exe Calc.exe. ,
Microsoft Office WinWord.exe, Excel.exe Outlook.
exe - .
(, -)
. , (, SQLServer)
.
CLR AppDomain (
22). .
,
, ( ),
1.
(Constrained Execution Region, CER) , . ,
,
. ,
, . (asynchronous exceptions). ,
CLR ,
, , IL- ..
, CLR .
catch finally, . ,
:
private static void Demo1() {
try {
Console.WriteLine("In try");
}
finally {
// Type1
Type1.M();
}
}

, AppDomain
( , ASP.NET SQL- ).
, ,
.
1

544

20.

private sealed class Type1 {


static Type1() {
// M
Console.WriteLine("Type1's static ctor called");
}
public static void M() { }
}

:
In try
Type1's static ctor called

, try
catch finally.
:
private static void Demo2() {
// finally
RuntimeHelpers.PrepareConstrainedRegions(); //
// System.Runtime.CompilerServices
try {
Console.WriteLine("In try");
}
finally {
// Type2
Type2.M();
}
}
public class Type2 {
static Type2() {
Console.WriteLine("Type2's static ctor called");
}
// ,
// System.Runtime.ConstrainedExecution
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static void M() { }
}

:
Type2's static ctor called
In try

PrepareConstrainedRegions .
try, JIT- catch finally. JIT- ,
,
. ,
try.

545

JIT- . ,
ReliabilityContractAttribute Consistency
WillNotCorruptState Consistency.MayCorruptInstance, ,
, CLR
. ,
PrepareConstrainedRegions catch finally
, ,
ReliabillityContractAttribute.
:
public sealed class ReliabilityContractAttribute : Attribute {
public ReliabilityContractAttribute(
Consistency consistencyGuarantee, Cer cer);
public Cer Cer { get; }
public Consistency ConsistencyGuarantee { get; }
}


1. Cer Consistency
:
enum Consistency {
MayCorruptProcess, MayCorruptAppDomain,
MayCorruptInstance, WillNotCorruptState
}
enum Cer { None, MayFail, Success }

,
Consistency.WillNotCorruptState.
.
Cer.Success.
Cer.MayFail. ,
ReliabilityContractAttribute,
:
[ReliabilityContract(Consistency.MayCorruptProcess, Cer.None)]

Cer.None , CER-
. ,
. ,
, . CLR JIT .
,
. ,
, , ,
.
1

546

20.

(, ), , , ,
JIT- ,
. RuntimeHelpers:
public static void PrepareMethod(RuntimeMethodHandle method)
public static void PrepareMethod(RuntimeMethodHandle method,
RuntimeTypeHandle[] instantiation)
public static void PrepareDelegate(Delegate d);
public static void PrepareContractedDelegate(Delegate d);

, , CLR ,
, ReliabiltyContractAttribute.
- , .


StackOverflowException. CLR (hosted)
, StackOverflowException
Environment.FailFast.
, PreparedConstrainedRegions ,
48 .
StackOverflowException try.

ExecuteCodeWithGuaranteedCleanup
RuntimeHelper,
:

public static void ExecuteCodeWithGuaranteedCleanup(


TryCode code, CleanupCode backoutCode, Object userData);

try finally
, :
public delegate void TryCode(Object userData);
public delegate void CleanupCode(Object userData, Boolean exceptionThrown);

CriticalFinalizerObject, .


(code contracts)
, , .
:

547

(preconditions) ;
(postconditions)
, ;
(object invariants) ,
.
, , , 1, . ,
.
, .
System.
Diagnostics.Contracts.Contract:
public static class Contract {
// : [Conditional("CONTRACTS_FULL")]
public static void Requires(Boolean condition);
public static void EndContractBlock();
// : Always
public static void Requires<TException>(
Boolean condition) where TException : Exception;
// : [Conditional("CONTRACTS_FULL")]
public static void Ensures(Boolean condition);
public static void EnsuresOnThrow<TException>(Boolean condition)
where TException : Exception;
// : Always
public static T Result<T>();
public static T OldValue<T>(T value);
public static T ValueAtReturn<T>(out T value);
// : [Conditional("CONTRACTS_FULL")]
public static void Invariant(Boolean condition);
// : Always
public static Boolean Exists<T>(
IEnumerable<T> collection, Predicate<T> predicate);
public static Boolean Exists(
Int32 fromInclusive, Int32 toExclusive, Predicate<Int32> predicate);
public static Boolean ForAll<T>(
IEnumerable<T> collection, Predicate<T> predicate);
public static Boolean ForAll(
Int32 fromInclusive, Int32 toExclusive,
Predicate<Int32> predicate);

Pex,
Microsoft Research: http://research.microsoft.com/en-us/projects/pex/.
1

548

20.

// :
// [Conditional("CONTRACTS_FULL")] [Conditional("DEBUG")]
public static void Assert(Boolean condition);
public static void Assume(Boolean condition);
// :
public static event EventHandler<ContractFailedEventArgs> ContractFailed;
}

[Conditional("CONTRACTS_FULL")], Helper
[Conditional("DEBUG")]. , -

, ,
. Always ,
. ,
Requires, Requires<TException>, Ensures, EnsuresOnThrow, Invariant, Assert
Assume ( ),
String.
, .
, CONTRACTS_FULL.

Visual Studio, http://msdn.microsoft.com/en-us/
devlabs/dd491992.aspx. Visual Studio ,
, . DevLabs
, Visual Studio.
(.20.9).
Perform Runtime Contract
Checking
Full. CONTRACTS_FULL
( )
.
ContractFailed Contract.
, ,
ContractFailedEventArgs, :
public sealed class ContractFailedEventArgs : EventArgs {
public ContractFailedEventArgs(ContractFailureKind failureKind,
String message, String condition, Exception originalException);
public
public
public
public

ContractFailureKind FailureKind
String Message
String Condition
Exception OriginalException

{
{
{
{

get;
get;
get;
get;

}
}
}
}

public Boolean Handled { get; } // ,

549

// SetHhandled
public void SetHandled(); // Handled true,
//
public Boolean Unwind { get; } //
//
public void SetUnwind(); //
//

,
SetUnwind threw
Unwind true,
ContractException

. 20.9. Code Contracts Visual Studio

.

. , ,
( SetHandled) .
SetHandled , ,
, , , SetUnwind.
,
System.Diagnostics.Contracts.ContractException.
MSCorLib.dll, , catch

550

20.

. -
, ,
ContractException.

SetHandled SetUnwind , .
CLR , .
CLR
( , , Windows service application),
Environment.FailFast, . Assert On Contract Failure,
, .
ContractException.
, .
public sealed class Item { /* ... */ }
public sealed class ShoppingCart {
private List<Item> m_cart
= new List<Item>();
private Decimal m_totalCost = 0;
public ShoppingCart() {
}
public void AddItem(Item item) {
AddItemHelper(m_cart, item, ref m_totalCost);
}
private static void AddItemHelper(
List<Item> m_cart, Item newItem, ref Decimal totalCost) {
// :
Contract.Requires(newItem != null);
Contract.Requires(Contract.ForAll(m_cart, s => s != newItem));
// :
Contract.Ensures(Contract.Exists(m_cart, s => s == newItem));
Contract.Ensures(totalCost >= Contract.OldValue(totalCost));
Contract.EnsuresOnThrow<IOException>(
totalCost == Contract.OldValue(totalCost));
// - ( IOException)
m_cart.Add(newItem);
totalCost += 1.00M;
}
//
[ContractInvariantMethod]
private void ObjectInvariant() {

551

Contract.Invariant(m_totalCost >= 0);

AddItemHelper .
, newItem null ,
. ,
,
. ,
AddItemHelper - IOException,
totalCost ,
. ObjectInvariant , m_totalCost .

, , , .
,
. , , ,
, ,
.
. ,
. ;
, . ,
.

,
, . ,
,
. , ,
, :
Contract.Requires(true);

( ), , .
,
, , //
, .

, , .
, . ,
. . ,

552

20.

.
C# Code Contract Rewriter
( CCRewrite.exe C:\Program Files (x86)\Microsoft\Contracts\
Bin) . Perform
Runtime Contract Checking Visual Studio
. IL-
, . , , CCRewrite.
exe IL-, .
CCRewrite.exe , [Contract
InvariantMethod]. ,
ObjectInvariant private ( ).
void. , CCRewrite.exe
IL- ObjectInvariant .

, , .
Finalize Dispose IDisposable CCRewrite.exe ,
. ,
[ContractInvariantMethod]; . CCRewrite.exe IL-
, ( )
.
Assert Assume . -,
.
:
. , , Code Contract
Checker (CCCheck.exe), C# IL-
.
, , Assert, .
, Assume.
. , :
internal sealed class SomeType {
private static String s_name = "Jeffrey";
public static void ShowFirstLetter() {
Console.WriteLine(s_name[0]); // :
// : index < this.Length
}
}

Perform Static Contract


Checking CCCheck.exe , -

. , s_name

553

, ,
s_name , .
, ShowFirstLetter :
public static void ShowFirstLetter() {
Contract.Assert(s_name.Length >= 1); // :
//
Console.WriteLine(s_name[0]);
}

, , CCCheck.exe , s_name , .
.
- ; ,
.
, Assert
Assume. , s_name,
ShowFirstLetter :
public static void ShowFirstLetter() {
Contract.Assume(s_name.Length >= 1); // !
Console.WriteLine(s_name[0]);
}

CCCheck.exe ,
s_name , .
ShowFirstLetter
.
Code Contract Reference Assembly Generator
(CCRefGen.exe). CCRewrite.exe ,
.
CCRefGen.exe,
. Visual Studio , Contract Reference Assembly Build.
.Contracts.dll (, MSCorLib.Contracts.dll) IL-.

System.Diagnostics.Contracts.ContractReferenceAssemblyAttribute.
CCRewrite.exe CCCheck.exe
.
Code Contract Document Generator (CCDocGen.
exe) XML-,
C# /doc:file. XML-, CCDocGen.exe, Sandcastle
MSDN .

21.

()

,
,
.
CLR , .
,
.


, ,
, , . . -
.
, .
:
1. , (
new C#).
2. ,
.
.
3. , ( ).
4. .
5. . .
, ,
C++. , , , ,
.

555

,
, .
, , .
, ( C# unsafe), .
, . , - ,
, , .
, , , 4 ( )
. , ,
, : ,
, .
, .
, ,
. ,
, . (
Dispose), .
, , ,
. .
, , ,
, .


CLR
(managed heap). CLR , ,
NextObjPtr. ,
,
.
CLR ,
. ,
. 32-
1,5 , 64- 8 .
C# new CLR:
1) ,
( , );
2) , . :

556

21. ()

- . 32 32,
8, 64-
64, 16;
3) , ( ).
, , ,
NextObjPtr, . ( NextObjPtr
this), new .
NextObjPtr ,
, .
. 21.1 : , .
, NextObjPtr (
).

. 21.1.


.
, ,
, . ,
FileStream BinaryWriter. BinaryWriter, FileStream.
, ,
,
. , , ,
, . , ,
, , . ,
-,
.
, , . ,
, CLR .
, ,
, .
(Garbage Collection, GC).

557


new , .
CLR .

.
0.
, ,
.


. , Microsoft COM
(Component Object Model).
, .
, ,
. 0, .
,
. ,
,
.
0, , .
- , , CLR
.
,
;
. : ,
, .
(roots).
CLR ,
.
CLR. CLR , (marking). CLR
, 0.
, . CLR
, . null,
CLR .
, .

558

21. ()

CLR ,
. , ,
.
.21.2 , , , D F. .
D ,
, H, H .
.

. 21.2.

. ,
; ,
. ,
, .
, CLR , , , , (compacting
phase). CLR ,
. .
-, ;
, ,
. -,
,
. ,
.

, ,
.
, , . , ,
CLR ,

559

. ,
, ; .
NextObjPtr
, .
. .21.3 . CLR , ,
.

. 21.3.

CLR , , ,
.
new OutOfMemoryException.
, ;
, Windows ,
, .
. -, , ,
, . -,

.

, ,
.
- ,
. , ,
, .
.

560

21. ()


,
.
. ,
:
using System;
using System.Threading;
public static class Program {
public static void Main() {
// Timer, TimerCallback
// 2000
Timer t = new Timer(TimerCallback, null, 0, 2000);
// , Enter
Console.ReadLine();
}
private static void TimerCallback(Object o) {
// /
Console.WriteLine("In TimerCallback: " + DateTime.Now);
//
GC.Collect();
}
}

, . , ,
, TimerCallback !
,
TimerCallback 2000. ,
Timer, t. , . , TimerCallback
GC.Collect().
, ( ), Timer.
, Main t
. ,
Timer, .
, TimerCallback .
, Main,
t Timer. ,
, t,
Quick Watch ? ,
.

561

, Microsoft
.
/debug C# System.Diagnostics.DebuggableAttribute
DisableOptimizations .
JIT- , ,
. JIT , t Main .
, , , t
, Timer, t, - .
Timer , TimerCallback
Main.
, ,
C# /debug.
TimerCallback ! , /optimize+ C# ,
.
JIT- , . ( ),
, JIT-
. , ,
.
, , , . ,
, . ,
.
Main :
public static void Main() {
// Timer, TimerCallback 2000
Timer t = new Timer(TimerCallback, null, 0, 2000);
// , Enter
Console.ReadLine();
// t ReadLine
// ( )
t = null;
}

( /debug+) ( ) , Timer_Callback
. , JIT- , - null
. , JIT-
t=null; , -

562

21. ()

, .
Main:
public static void Main() {
// Timer, TimerCallback 2000
Timer t = new Timer(TimerCallback, null, 0, 2000);
// , Enter
Console.ReadLine();
// t ReadLine
// (t
// Dispose)
t.Dispose();
}

, ( /debug+)
( ), , TimerCallback , . ,
, t, ,
Dispose (t Dispose
this). : ,
, .

,
. Timer -
. , Timer . .
, String .
. , ,
, Timer.
, .
.

(generational garbage collector),


(ephemeral garbage collector),
, :
, ;
, ;
, .

563

,
. .
. ,
0. ,
,
. 21.4 , ().
.

. 21.4. :
0,

CLR 0.
0 , . ,
0. F .
, E ,
D, B. ,
(, D), 1. 1
. ,
.21.5.

. 21.5. : 0
1, 0

0 . . .21.6,
FK.
B, H J, .

. 21.6. 0 , 1

564

21. ()

, L 0
, .
, . ,
CLR 0; CLR
1.
, , 1. 1 ,
0. , . ,
. 0, ,
, . 1,
.
, 1 .
.
, , . ,
, . ,
JIT-, .
, ( )
.
, ,
01.

, Microsoft, , 0 1. Microsoft ,
, .

JIT- ,
, (write barrier method). , , , 1 2.

(card table). 128- . ,
1 2 . -
0, .
.

( ).
, 1 2.
1

565

, ,
, . , 1 .
1,
. , 1,
, . 1 ,
. , .21.7.

. 21.7. :
0 1 ( ),.
0

, 0, ,
1. 1, , , , .
0 ,
. ,
LO. G,
L M, . , .21.8.

. 21.8. 0 , .
1

, P 0
, .
1 ,
0, 1 (B G). .21.9.

. 21.9. :
0 1 ( );.
0

566

21. ()

, 1 . , 1
, . (
) PS,
0 (.21.10).

. 21.10. 0,.
1

0 . ,
, , . 0 ,
1 ( ). 1 0.
, .21.11.

. 21.11. :
1 2, 0.
1, 0

0 1,
1 2. ,
0 : . 2 , .
, 1
,
0.
: 0, 1 2. 3
1. CLR
. CLR ,
.
,

MaxGeneration System.GC 2.

567

, 0 .
, 0 .
, 0
, 0.
, ,
. , 0
, NextObjPtr 0,
. !

,
, .
, , ,
.
. ,
. ( , ),
, .
, , .
,
.
. , ,
.

, 0
, , .
0.
,
. , , OutOfMemoryException .
, 0, 1 2.
,
.
,
.
, !
GCNotification
0 2.
, ,
. . ,
, :

568

21. ()

public static class GCNotification {


private static Action<Int32> s_gcDone = null; //
public static event Action<Int32> GCDone {
add {
// ,
if (s_gcDone == null) { new GenObject(0); new GenObject(2); }
s_gcDone += value;
}
remove { s_gcDone -= value; }
}
private sealed class GenObject {
private Int32 m_generation;
public GenObject(Int32 generation) { m_generation = generation; }
~GenObject() { //
// ( ),
//
Action<Int32> temp = Volatile.Read(ref s_gcDone);
if (temp != null) temp(m_generation);
}
// ,
// ,
if ((s_gcDone != null)
&& !AppDomain.CurrentDomain.IsFinalizingForUnload()
&& !Environment.HasShutdownStarted) {
// 0 ; 2
//
// 2
if (m_generation == 0) new GenObject(0);
else GC.ReRegisterForFinalize(this);
} else { /* */ }
}
}
}


, CLR , ,
0 . , :
Collect System.GC. ,
. Microsoft ,
.
.
Windows . CLR Win32 CreateMemoryResourceNotification QueryMemoryResourceNotification

569

. Windows
, CLR ,
.
. CLR . 22.
CLR. CLR ( , ,
). CLR ,
; ,
CLR ,
Windows
.


, .
CLR .
. 85000
1. CLR
:
.
,
.

OutOfMemoryException. CLR
.
2,
, .

2, .
(, XML JSON)
, / ,
.
.
, -
(, ).
, ,
. 85000 .
1

570

21. ()


CLR ,
.
:
. .
, .
, ,
.
.
. ,
( ), . .
.
.
.
;
.
. (,
ASP.NET SQL Server), CLR, . , CLR .
CLR
( , , 2 3), gcServer. :
<configuration>
<runtime>
<gcServer enabled="true"/>
</runtime>
</configuration>

, CLR GC-,
IsServerGC GCSettings,
:
using System;
using System.Runtime; // GCSettings

571

public static class Program {


public static void Main() {
Console.WriteLine(
"Application is running with server GC=" + GCSettings.IsServerGC);
}
}

, :
( ) .
,
. , 0,
, ,
. 0
1, , 2, 0 , ,
.
,
.
, ,
. ,
, ,
,
. , , , .
,
, .
, ,
.
CLR ,
, gcConcurrent
(. 2 3). :
<configuration>
<runtime>
<gcConcurrent enabled="false"/>
</runtime>
</configuration>

GC- ,
GCLatencyMode GCSettings.
GCLatencyMode. .21.1.

572

21. ()

21.1. , GCLatencyMode

Batch ( )

Interactive (

)

LowLatency

, (, ),
2 -

SustainedLowLatency


.
2 .

, .
,

LowLatency .
, , Batch Interactive. LowLatency
2,
. , GC.Collect(), 2
. , Windows
CLR ( ).
LowLatency OutOfMemory
Exception. , , ,
Batch Interactive
(.20). ,
LowLatency
. .
( Interlocked).
LowLatency:
private static void LowLatencyDemo() {
GCLatencyMode oldMode = GCSettings.LatencyMode;

573

System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
try {
GCSettings.LatencyMode = GCLatencyMode.LowLatency;
//
}
finally {
GCSettings.LatencyMode = oldMode;
}
}


System.GC .
, , , , GC.MaxGeneration.
2.
,
Collect GC. , , GCCollectionMode () () .
Collect :
void Collect(Int32 generation, GCCollectionMode mode, Boolean blocking)

GCCollectionMode .21.2.
21.2. GCCollectionMode

Default

GC.Collect .
Forced,
CLR

Forced

Optimized

,
, .

Collect: , .

CLR .

574

21. ()

.
GCCollectionMode Optimized.
Default Forced .
, Collect,
, .
Collect ,
, , .
,
. -
Windows Form, .
Collect, ; , .
( , ) ( ) . , , .
, GC RegisterForFullGCNotification.

(WaitForFullGCApproach, WaitForFullGCComplete CancelFullGCNotification)
,
. GC.Collect

, . .NET Framework
SDK. , WaitForFullGCApproach WaitForFullGCComplete
, CLR .


,
. , GC

, .
Int32 CollectionCount(Int32 generation);
Int64 GetTotalMemory(Boolean forceFullCollection);

,
, , . , , ,
. , ,
.

575

, . , , 22.
.NET Framework
,
CLR.
PerfMon.exe Windows.
, PerfMon.
exe + ;
Add Counters, .21.12.

. 21.12. .NET CLR PerfMon.exe

CLR

.NET CLR Memory, . , Add,


OK.

. , , Show Description.

PerfView.
ETW (Event Tracing for Windows) .
PerfView. ,
(SOS.dll), CLR. ,
, ,
, GCHandle

576

21. ()

, , ,
, .



, , ,
. ,
, , .
, System.IO.FileStream ( ) .
Read Write . , System.Threading.
Mutex , Windows ( ),
, Mutex.
, , , ;
, , . ,
, CLR (finalization),
,
. , (,
, , . .), .
CLR , ,
, .
System.Object
Finalize. ,
, Finalize ( ).
C# Microsoft ,
( , #
). #
(~):
internal sealed class SomeType {
//
~SomeType() {
//
}
}

ILDasm.exe, , # -

577

Finalize. IL- Finalize


, try,
base.Finalize finally.

C++ , , C# ,
C++. ,
# (destructor).
, C++,
, .
, ,
C# ,
C++. CLR ,
C# .

Finalize ,
. ,
, Finalize
.
, ,
, . ,
. , , ,
, . ,

.
, ,
Finalize, .
Finalize ,
, . , CLR
Finalize. ,
Finalize, ,
Finalize; ,
. ,
Finalize. ,
, ;
.
Finalize CLR . , -

578

21. ()

1. Finalize (,
, ),
Finalize.
, ,
. Finalize , ; .
, Finalize
.
.
, Finalize Object;
FCL. Object
, .
,
.
, , , System.Runtime.
InteropServices.SafeHandle, (
):
public abstract class SafeHandle : CriticalFinalizerObject, IDisposable {
//
protected IntPtr handle;
protected SafeHandle(IntPtr invalidHandleValue, Boolean ownsHandle) {
this.handle = invalidHandleValue;
// ownsHandle true,
// , SafeHandle,
//
}
protected void SetHandle(IntPtr handle) {
this.handle = handle;
}
// Dispose
public void Dispose() { Dispose(true); }
// Dispose
// !
protected virtual void Dispose(Boolean disposing) {
// ,
// Dispose,
// ,
// ownsHandle false,
// , ,

, CLR .
1


//
//
//
//
//
}

579

ReleaseHandle
GC.SuppressFinalize(this),
ReleaseHandle true,
,
ReleaseHandleFailed Managed Debugging Assistant (MDA)

//
// !
~SafeHandle() { Dispose(false); }
// ,
//
protected abstract Boolean ReleaseHandle();
public void SetHandleAsInvalid() {
// , ,
// GC.SuppressFinalize(this),
}
public Boolean IsClosed {
get {
// , ,
}
}
public abstract Boolean IsInvalid {
//
// true,
// ( ,
// 0 @1)
get
}
//
//
public void DangerousAddRef(ref Boolean success) {...}
public IntPtr DangerousGetHandle() {...}
public void DangerousRelease() {...}
}

SafeHandle, ,
CriticalFinalizerObject, System.
Runtime.ConstrainedExecution.
CLR , . , CLR :
, Critical
FinalizerObject, CLR JIT-, .
,

580

21. ()

, .
, ,
. CLR
; ,
. ,
,
CLR.
CLR , CriticalFinalizer
Object , ,
CriticalFinalizerObject. ,
, , CriticalFinalizerObject, . ,
FileStream
, .
CLR , CriticalFinalizer
Object, (, Microsoft SQL Server Microsoft ASP.NET). ,
.
, SafeHandle : , , SafeHandle,
, ReleaseHandle
IsInvalid get.
Windows (32- 32- , 64- 64-
). SafeHandle IntPtr
handle.
0 1. Microsoft.Win32.SafeHandles
SafeHandleZeroOrMinusOneIsInvald :
public abstract class SafeHandleZeroOrMinusOneIsInvalid : SafeHandle {
protected SafeHandleZeroOrMinusOneIsInvalid(Boolean ownsHandle)
: base(IntPtr.Zero, ownsHandle) {
}
public override Boolean IsInvalid {
get {
if (base.handle == IntPtr.Zero) return true;
if (base.handle == (IntPtr) (-1)) return true;
return false;
}
}
}

581

, SafeHandleZeroOrMinusOneIsInvalid , , ReleaseHandle . Microsoft .NET Framework ,


SafeHandleZeroOrMunusOneIsInvalid, SafeFileHandle,
SafeRegistryHandle, SafeWaitHandle SafeMemoryMappedViewHandle.
SafeFileHandle:
public sealed class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid {
public SafeFileHandle(IntPtr preexistingHandle, Boolean ownsHandle)
: base(ownsHandle) {
base.SetHandle(preexistingHandle);
}
protected override Boolean ReleaseHandle() {
// Windows,
return Win32Native.CloseHandle(base.handle);
}
}

SafeWaitHandle .

:
, , .
ReleaseHandle SafeRegistryHandle Win32-
RegCloseKey.
, .NET Framework , , ,
SafeProcessHandle, SafeThreadHandle, SafeTokenHandle, SafeLibraryHandle (
ReleaseHandle Win32- FreeLibrary), SafeLocalAllocHandle ( ReleaseHandle Win32- LocalFree)
..
( ) FCL.
,
, . Microsoft ,
.
,
ILDasm.exe IL-, .
.
, SafeHandle, . ,
SafeHandle . -,

582

21. ()

, CLR.
:
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
internal static class SomeType {
[DllImport("Kernel32", CharSet=CharSet.Unicode, EntryPoint="CreateEvent")]
//
private static extern IntPtr CreateEventBad(
IntPtr pSecurityAttributes, Boolean manualReset,
Boolean initialState, String name);
//
[DllImport("Kernel32", CharSet=CharSet.Unicode, EntryPoint="CreateEvent")]
private static extern SafeWaitHandle CreateEventGood(
IntPtr pSecurityAttributes, Boolean manualReset,
Boolean initialState, String name);
public static void SomeMethod() {
IntPtr handle = CreateEventBad(IntPtr.Zero, false, false, null);
SafeWaitHandle swh = CreateEventGood(IntPtr.Zero, false, false, null);
}
}

, CreateEventBad IntPtr,
.
. CreateEventBad
( ) ,
ThreadAbortException handle.
.
.
SafeHandle .
, CreateEventGood SafeWaitHandle,
IntPtr. CreateEventGood CLR Win32-
CreateEvent. , CLR
, SafeWaitHandle SafeHandle. CLR
SafeWaitHandle,
CreateEvent . SafeWaitHandle
,
ThreadAbortException.
.
SafeWaitHandle ,
.
, , SafeHandle, ,
.
, , -

583

.
. SafeHandle . , .
SafeHandle ,
1. , SafeHandle
, CLR
.
, CLR . , Win32- SetEvent:
[DllImport("Kernel32", ExactSpelling=true)]
private static extern Boolean SetEvent(SafeWaitHandle swh);

SafeWaitHandle CLR

. , ,
. ?
, SafeHandle, CLR , ,
. , 0 .
, (,
IntPtr), SafeHandle, DangerousAddRef DangerousRelease
SafeHandle.
DangerousGetHandle.
CriticalHandle, System.Runtime.InteropServices . ,
SafeHandle, . CriticalHandle ( ). SafeHandle, CriticalHandle
CriticalHandleMinusOneIsInvalid CriticalHand
leZeroOrMinusOneIsInvalid. Microsoft ,
, ,
. , CriticalHandle,

.

,
, , SafeHandle ,
. ,
. System.
IO.FileStream. FileStream ,

584

21. ()

, . FileStream
Win32- CreateFile,
SafeFileHandle,
FileStream. FileStream (, Length , Position , CanRead ) (Read ,
Write, Flush).
, , ,
, . :
using System;
using System.IO;
public static class Program {
public static void Main() {
//
Byte[] bytesToWrite = new Byte[] { 1, 2, 3, 4, 5 };
//
FileStream fs = new FileStream("Temp.dat", FileMode.Create);
//
fs.Write(bytesToWrite, 0, bytesToWrite.Length);
//
File.Delete("Temp.dat"); // IOException
}
}

, , , ,
. , Delete File
Windows , Delete
System.IO.IOException (
Temp.dat, ):
The process cannot access the file "Temp.dat" because it is being used by
another process

!
Write Delete, SafeFileHandle
FileStream ,
Delete.
, 99 100 .
, , IDisposable,
:
public interface IDisposable {
void Dispose();
}

585

, dispose,
. Dispose ,
. Dispose, ,
.

, FileStream IDisposable, Dispose SafeFileHandle FileStream.


,
( , - ).
:
using System;
using System.IO;
public static class Program {
public static void Main() {
//
Byte[] bytesToWrite = new Byte[] { 1, 2, 3, 4, 5 };
//
FileStream fs = new FileStream("Temp.dat", FileMode.Create);
//
fs.Write(bytesToWrite, 0, bytesToWrite.Length);
//
fs.Dispose();
//
File.Delete("Temp.dat"); //
//
}
}

Delete File Windows ,


, .
,
Dispose. ; Dispose
, . , Dispose
. . ,

, .
Write . , ,
Write System.

586

21. ()

ObjectDisposedException (

):

message: Cannot access a closed file.


using System;
using System.IO;
public static class Program {
public static void Main() {
//
Byte[] bytesToWrite = new Byte[] { 1, 2, 3, 4, 5 };
//
FileStream fs = new FileStream("Temp.dat", FileMode.Create);
//
fs.Write(bytesToWrite, 0, bytesToWrite.Length);
//
fs.Dispose();
//
fs.Write(bytesToWrite, 0, bytesToWrite.Length); //
ObjectDisposedException
//
File.Delete("Temp.dat");
}
}

, , FileStream, ;
.

, IDisposable,
, System.ObjectDisposedException.
Dispose ObjectDisposedException
.


Dispose. CLR ,
. , ,
. Dispose,
, , . .

587

, , . ,
( ), .
, Dispose, -
, ObjectDisposedException.
Dispose , ,
( ).
, Dispose
. , Dispose
. ,
Dispose , ,
.

Dispose. , finally,

.
:
using System;
using System.IO;
public static class Program {
public static void Main() {
//
Byte[] bytesToWrite = new Byte[] { 1, 2, 3, 4, 5 };
//
FileStream fs = new FileStream("Temp.dat", FileMode.Create);
try {
//
fs.Write(bytesToWrite, 0, bytesToWrite.Length);
}
finally {
//
if (fs != null)
fs.Dispose();
}
//
File.Delete("Temp.dat");
}
}


. , C# using,
, .
:

588

21. ()

using System;
using System.IO;
public static class Program {
public static void Main() {
//
Byte[] bytesToWrite = new Byte[] { 1, 2, 3, 4, 5 };
//
using (FileStream fs = new FileStream("Temp.dat", FileMode.Create)) {
//
fs.Write(bytesToWrite, 0, bytesToWrite.Length);
}
//
File.Delete("Temp.dat");
}
}

using
. , using.
try finally. finally ,
IDisposable,
Dispose. , using
, IDisposable.

using C#
, . Using statements
C# Programmers Reference.


System.IO.FileStream
.
. .
FileStream
System.IO.StreamWriter, :
FileStream fs = new FileStream("DataFile.dat", FileMode.Create);
StreamWriter sw = new StreamWriter(fs);
sw.Write("Hi there");
// Dispose
sw.Dispose();

589

// . StreamWriter.Dispose FileStream
// FileStream

: StreamWriter
Stream,
FileStream. StreamWriter
Stream. StreamWriter . StreamWriter
Stream.
BinaryWriter Dispose
( StreamWriter IDisposable, using C#). BinaryWriter
Stream 1.

Dispose FileStream : BinaryWriter


. - , FileStream ,
, .

, , , Dispose?
, , . . FileStream
, . StreamWriter
, .
, StreamWriter , .
Microsoft?
,
, . Microsoft : StreamWriter
,
FileStream. , StreamWriter, . Microsoft
,
, Dispose.

StreamWriter,
leaveOpen.
1

590

21. ()

.NET Framework (Managed


Debugging Assistants, MDA). , .NET Framework

. . MDA , StreamWriter
. Visual Studio,
DebugExceptions.
Exceptions Managed Debugging Assistants, StreamWriterBufferedDataLost Thrown,
Visual Studio
StreamWriter.



, , , .
.
, ,
4- 8- . CLR
(
). , .
GC
:
public static void AddMemoryPressure(Int64 bytesAllocated);
public static void RemoveMemoryPressure(Int64 bytesAllocated);

,
, . ,
, .
. Windows .
, . , CLR,
( ).
, ,
.
System.Runtime.InteropServices
HandleCollector:
public sealed class HandleCollector {
public HandleCollector(String name, Int32 initialThreshold);

591

public HandleCollector(
String name, Int32 initialThreshold, Int32 maximumThreshold);
public void Add();
public void Remove();

public
public
public
public

Int32 Count { get; }


Int32 InitialThreshold { get; }
Int32 MaximumThreshold { get; }
String Name { get; }

, ,
, . ,
, .

GC.AddMemoryPressure HandleCollector.Add GC.Collect


0 . ,
.

. ,
. ,
.


HandleCollector:
using System;
using System.Runtime.InteropServices;
public static class Program {
public static void Main() {
MemoryPressureDemo(0); // 0
MemoryPressureDemo(10 * 1024 * 1024); // 10 M
//
}

HandleCollectorDemo();

private static void MemoryPressureDemo(Int32 size) {


Console.WriteLine();
Console.WriteLine("MemoryPressureDemo, size={0}", size);
//
for (Int32 count = 0; count < 15; count++) {
new BigNativeResource(size);
}

592

21. ()
//
GC.Collect();

private sealed class BigNativeResource {


private Int32 m_size;
public BigNativeResource(Int32 size) {
m_size = size;
// ,
if (m_size > 0) GC.AddMemoryPressure(m_size);
Console.WriteLine("BigNativeResource create.");
}
~BigNativeResource() {
// ,
if (m_size > 0) GC.RemoveMemoryPressure(m_size);
Console.WriteLine("BigNativeResource destroy.");
}
}
private static void HandleCollectorDemo() {
Console.WriteLine();
Console.WriteLine("HandleCollectorDemo");
for (Int32 count = 0; count < 10; count++) new LimitedResource();
//
GC.Collect();
}
private sealed class LimitedResource {
// HandleCollector
// ,
// LimitedResource
private static HandleCollector s_hc =
new HandleCollector("LimitedResource", 2);
public LimitedResource() {
// HandleCollector,
// LimitedResource
s_hc.Add();
Console.WriteLine("LimitedResource create. Count={0}", s_hc.Count);
}
~LimitedResource() {
// HandleCollector, LimitedResource
//
s_hc.Remove();
Console.WriteLine("LimitedResource destroy. Count={0}", s_hc.Count);
}
}
}

593

:
MemoryPressureDemo, size=0
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
MemoryPressureDemo, size=10485760
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource create.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource destroy.
BigNativeResource create.
BigNativeResource create.
BigNativeResource destroy.
BigNativeResource destroy.

594

21. ()

BigNativeResource
BigNativeResource
BigNativeResource
BigNativeResource
BigNativeResource
BigNativeResource
BigNativeResource
BigNativeResource
BigNativeResource
BigNativeResource
BigNativeResource
BigNativeResource
BigNativeResource

destroy.
destroy.
create.
create.
create.
destroy.
destroy.
create.
create.
destroy.
destroy.
destroy.
destroy.

HandleCollectorDemo
LimitedResource create. Count=1
LimitedResource create. Count=2
LimitedResource create. Count=3
LimitedResource destroy. Count=3
LimitedResource destroy. Count=2
LimitedResource destroy. Count=1
LimitedResource create. Count=1
LimitedResource create. Count=2
LimitedResource destroy. Count=2
LimitedResource create. Count=2
LimitedResource create. Count=3
LimitedResource destroy. Count=3
LimitedResource destroy. Count=2
LimitedResource destroy. Count=1
LimitedResource create. Count=1
LimitedResource create. Count=2
LimitedResource destroy. Count=2
LimitedResource create. Count=2
LimitedResource destroy. Count=1
LimitedResource destroy. Count=0


, . ,
, .
.
, new
. ,

(finalization list) ,
. ,
,
.

595

.21.13 .
, . C, E, F, I J ,
,
.

. 21.13.

System.Object , CLR .

System.Object, .
Object .

, B, E, G, H, I J .
.
,
(freachable queue)
. , .
.21.14.
, B, G H ,
. , E, I
J, , .
CLR ,
. ,

. (
) .
, ,

596

21. ()

.
, , . ,
.
:


A

E I J

. 21.14. , .

, , CLR , ,
.
,
,
.

, ,
. , f finalization, :
,
. , reachable,
, .
, , .
, , . ,
.
, , . ,

, , ,
. ,
, , .

597

,
,
.
, , , .
,
, CLR ,
.
, ,
, ,
. , , .
, , , , .
, ( ). .21.15
.

. 21.15.

CLR GC-
(GChandle table),
. .
, .

System.Runtime.InteropServices.GCHandle.

598

21. ()

// System.Runtime.InteropServices
public struct GCHandle {
// ,
public static GCHandle Alloc(object value);
public static GCHandle Alloc(object value, GCHandleType type);
// , GCHandle IntPtr
public static explicit operator IntPtr(GCHandle value);
public static IntPtr ToIntPtr(GCHandle value);
// , IntPtr GCHandle
public static explicit operator GCHandle(IntPtr value);
public static GCHandle FromIntPtr(IntPtr value);
// , GCHandles
public static Boolean operator ==(GCHandle a, GCHandle b);
public static Boolean operator !=(GCHandle a, GCHandle b);
// , ( 0)
public void Free();
// , /
//
public object Target { get; set; }
// , true 0
public Boolean IsAllocated { get; }
// pinned
public IntPtr AddrOfPinnedObject();

public override Int32 GetHashCode();


public override Boolean Equals(object o);

,
Alloc GCHandle, ,
GCHandleType, , /
. GCHandleType :
public enum GCHandleType {
Weak = 0, //
WeakTrackResurrection = 1 //
Normal = 2, //
Pinned = 3 //
}

.
Weak . ,
, .
, , , - .

599

WeakTrackResurrection .
, ,
. , ( )
, , , .
Normal .
, (),
. , , (). Alloc,
GCHandleType, , GCHandleType.Normal.
Pinned .
, (),
. , ,
(). ,
. , ,
.
Alloc GCHandle GC ,
, . ,
GCHandleType. Alloc
GCHandle. GCHandle , IntPtr, .
GC-, GCHandle Free (
, IntPtr).
GC-.
1. (
). GC-,
Normal Pinned (
, ).
2. GC-
Weak. , () null.
3. .
, .
, .
4. GC-
WeakTrackResurrection. ( ,

600

21. ()

),
() null.
5. , ,
. ,
, ,
. Pinned ( ),
, , .
,
. Normal Pinned, .
.
Normal ,
, .
,
, . , Alloc
GCHandle Normal.
GCHandle IntPtr .
, IntPtr
GCHandle, Target, ( ).
, Free GCHandle,
( ,
).
, , .
, . Pinned
.
String Win32. String Pinned,
-
. , String , ,
String, .
P/Invoke CLR
Pinned ,
. GCHandle
Pinned -
. GCHandle .

601

, .
-.
, , . Alloc
GCHandle, Pinned.
GCHandle AddrOfPinnedObject.
IntPtr Pinned
. ,
.
,
Pinned. -
Free GCHandle,
. -
, .
.
,
fixed C#. :
unsafe public static void Go() {
// ,
for (Int32 x = 0; x < 10000; x++) new Object();
IntPtr originalMemoryAddress;
Byte[] bytes = new Byte[1000]; //
//
// Byte[]
fixed (Byte* pbytes = bytes) { originalMemoryAddress = (IntPtr) pbytes; }
//
// , Byte[]
GC.Collect();
// Byte[]
//
fixed (Byte* pbytes = bytes) {
Console.WriteLine("The Byte[] did{0} move during the GC",
(originalMemoryAddress == (IntPtr) pbytes) ? " not" : null);
}
}

fixed C# ,
GC-.
pbytes.
, null , , ,
, . C# IL-,

602

21. ()

pbytes fixed.
IL-, pbytes
null. ,
.
Weak WeakTrackResurrection ,
. Weak , ,
.
WeakTrackResurrection .
Weak ,
WeakTrackResurrection .
, A B. B A ,
, . , , A B
, .
A Alloc GCHandle, B Weak. A
GCHandle, B.
, B, . A B,
Target GCHandle.
, null, , B
. A
B . Target
null, , B , A
B. , A Free
GCHandle, GCHandle.
- GCHandle ,
System WeakReference:
public sealed class WeakReference<T> : ISerializable where T : class {
public WeakReference(T target);
public WeakReference(T target, Boolean trackResurrection);
public void SetTarget(T target);
public Boolean TryGetTarget(out T target);
}

GCHandle: Alloc GCHandle,


TryGetTarget Target GCHandle ,
SetTarget Target GCHandle, Finalize (
, ) Free GCHandle.
WeakReference ,

603

; ,
GCHandle, Normal Pinned, . WeakReference<T>
. - WeakReference
GCHandle.

, ,
. : , ,
. ,
, , ,
, . . , ,
, , .
, . , , 0
. , ,
.
,
,
. , ,
, , ,
. CLR ,
. Win32- GlobalMemoryStatusEx dwMemoryLoad MEMORYSTATUSEX. , 80, ,

: , ,
.

-
. , .
System.Runtime.CompilerServices.ConditionalWeakTable<TKey,TValue>
. :
public sealed class ConditionalWeakTable<TKey, TValue>
where TKey : class where TValue : class {
public ConditionalWeakTable();
public void Add(TKey key, TValue value);
public TValue GetValue(
TKey key, CreateValueCallback<TKey, TValue> createValueCallback);
public Boolean TryGetValue(TKey key, out TValue value);
public TValue GetOrCreateValue(TKey key);
public Boolean Remove(TKey key);

604

21. ()

public delegate TValue CreateValueCallback(TKey key); //


//
}


.
Add, key , value ,
.
Add ArgumentException.
,
. ,
,
, . , ,
.
, WeakReference
, ; , .
ConditionalWeakTable ,
, .
WeakReference,
, . ConditionalWeakTable ,
XAML.
.
, ConditionalWeakTable.
GCWatch ,
String.
:
internal static class ConditionalWeakTableDemo {
public static void Main() {
Object o = new Object().GCWatch("My Object created at " + DateTime.Now);
GC.Collect(); //
GC.KeepAlive(o); // , o,
o = null; // , o,
GC.Collect(); //
Console.ReadLine();
}
}
internal static class GCWatcher {
// . String
// - - MarshalByRefObject
private readonly static ConditionalWeakTable<Object,
NotifyWhenGCd<String>> s_cwt =
new ConditionalWeakTable<Object, NotifyWhenGCd<String>>();


private sealed class NotifyWhenGCd<T> {
private readonly T m_value;
internal NotifyWhenGCd(T value) { m_value = value; }
public override string ToString() { return m_value.ToString(); }
~NotifyWhenGCd() { Console.WriteLine("GC'd: " + m_value); }
}
public static T GCWatch<T>(this T @object, String tag) where T : class {
s_cwt.Add(@object, new NotifyWhenGCd<String>(tag));
return @object;
}
}

605

22. CLR

, - Microsoft .NET Framework, (hosting)


(AppDomains). CLR, ,
, , . ,
.

. Microsoft Windows DLL-
.
, , .
,
, .
. , CLR
, .

. CLR
. ,
. , , ,
.NET Framework, .

CLR
.NET Framework Microsoft Windows. ,
, Windows .
PE (portable executable), Windows (EXE)
(DLL).
Microsoft CLR COM-, DLL.
CLR COM-
COM- (GUID).

CLR

607

.NET Framework COM-, CLR, Windows COM-. .


C++ MetaHost.h .NET FrameworkSDK
GUID- ICLRMetaHost.
Windows- ( )
CLR. COM-CLR
CoCreateInstance;
CLRCreateInstance, MetaHost.h.
MSCorEE.dll, C:\Windows\
System32. (shim)
COM-CLR, , CLR .
CLR,
MSCorEE.dll ( )1.
MSCorEE.dll CLR, MSCorEE.dll ,
CLR, .
CLR , .
1.0, 1.1 2.0 MSCorWks.dll, 4.0 Clr.dll.
CLR,
2:
1.0 C:\Windows\Microsoft.NET\Framework\v1.0.3705;
1.1 C:\Windows\Microsoft.NET\Framework\v1.0.4322;
2.0 C:\Windows\Microsoft.NET\Framework\v2.0.50727;
4.0 C:\Windows\Microsoft.NET\Framework\v4.0.21006.
CLRCreateInstance ICLRMetaHost. GetRuntime ,
CLR, .
.

CLR, .
, requiredRuntime supportedRuntime
XML- (.2 3).
64- Windows
MSCorEE.dll. 32- x86, C:\Windows\
SysWOW64, 64- x64 IA64 (
), C:\Windows\System32.
2
, .NET Framework 3.0 3.5 CLR2.0.
, .NET Framework3.0 3.5, DLL-
CLR v2.0.50727.
1

608

22. CLR

GetRuntime
ICLRRuntimeInfo, GetInterface ICLRRuntimeHost. , -
:

- (host managers), CLR,


, , , .. ,
,
.
CLR-, CLR
. ,
, ,
, , CLR
, .
CLR.
.
CLR,
Windows-.
CLR. ,
CLR , .
, ,
, .
:
;
( ) JIT-,
;
, ;
;

, : , , , , .
, CLR,
(Steven Pratschner) Customizing the Microsoft
.NET Framework Common Language Runtime (Microsoft Press, 2005),
, , 4.0, CLR.

609

, Windows- CLR.
. .NET Framework 4.0
Windows- CLR.
CLR - 1.0,
1.1 2.0. . , Microsoft Office Outlook
,
.NET Framework.
, .NET Framework 4.0,
2.0 4.0 Windows-, ,
.NET Framework2.0 4.0, , .
.NET Framework . ,
CLR , ClrVer.exe.
Windows- CLR . AddRef
Release ICLRRuntimeHost.
, Windows .


COM- CLR (AppDomain),
. (default AppDomain),
Windows-.
, , COM , CLR .
. .
, , . ,
. ,
.
, (marshalby-reference) (marshal-by-value).
,
, .
.
. CLR . CLR
.

610

22. CLR

.
,
. , ,
.
. . ,
CLR . ,
, ,
.

Windows
. ,
.
, , Windows . , Windows
. Win32- CreateProcess ,
.

, , Windows-.
, ,
.

.22.1 Windows-,
COM- CLR, (, ,
Windows-).
, (
4). , (
, JIT-).
, . (
) : MyApp.exe, TypeLib.dll System.dll,
: Wintellect.dll System.dll.
, System.dll .
System.dll,
; , ,
. ,
, IL- JIT-,
,
.

611

Windows-


MSCorEE.dll ( )

Clr.dll ( CLR)

. 22.1. Windows-, CLR.



, , ; CLR
, . CLR .
, ,
.
. MSCorLib.dll, Microsoft.
System.Object, System.Int32 ,
.NET Framework. CLR,
.
MSCorLib.dll , .
. ,
-
: , ,
. .

612

22. CLR


, ,
.
.
,
. ,
, ,
. , , ,
,
. , .
, CLR:
private static void Marshalling() {
// ,
AppDomain adCallingThreadDomain = Thread.GetDomain();
// ,
//
String callingDomainName = adCallingThreadDomain.FriendlyName;
Console.WriteLine(
"Default AppDomain's friendly name={0}", callingDomainName);
// , Main.
String exeAssembly = Assembly.GetEntryAssembly().FullName;
Console.WriteLine("Main assembly={0}", exeAssembly);
// ,
AppDomain ad2 = null;
// 1.
//
Console.WriteLine("{0}Demo #1", Environment.NewLine);
// ( )
ad2 = AppDomain.CreateDomain("AD #2", null, null);
MarshalByRefType mbrt = null;
// ,
//
// ( )
mbrt = (MarshalByRefType)
ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType");
Console.WriteLine("Type={0}", mbrt.GetType()); // CLR
//
// , -
Console.WriteLine(

613

"Is proxy={0}", RemotingServices.IsTransparentProxy(mbrt));


// ,
// MarshalByRefType,
// . ,
// ,
mbrt.SomeMethod();
//
AppDomain.Unload(ad2);
// mbrt -;
// -
try {
// ,
// ,
mbrt.SomeMethod();
Console.WriteLine("Successful call.");
}
catch (AppDomainUnloadedException) {
Console.WriteLine("Failed call.");
}
// 2.
//
Console.WriteLine("{0}Demo #2", Environment.NewLine);
// (
// , )
ad2 = AppDomain.CreateDomain("AD #2", null, null);
// ,
//
// ( )
mbrt = (MarshalByRefType)
ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType");
// ;
// ,
MarshalByValType mbvt = mbrt.MethodWithReturn();
// , -
Console.WriteLine(
"Is proxy={0}", RemotingServices.IsTransparentProxy(mbvt));
// , MarshalByRefType,
//
Console.WriteLine("Returned object created " + mbvt.ToString());
//
AppDomain.Unload(ad2);
// mbrt ;

614

22. CLR

//
try {
// ;
Console.WriteLine("Returned object created " + mbvt.ToString());
Console.WriteLine("Successful call.");
}
catch (AppDomainUnloadedException) {
Console.WriteLine("Failed call.");
}
// 3.
//
Console.WriteLine("{0}Demo #3", Environment.NewLine);
// (
// , )
ad2 = AppDomain.CreateDomain("AD #2", null, null);
// ,
//
// ( )
mbrt = (MarshalByRefType)
ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType");
// ,
//
NonMarshalableType nmt = mbrt.MethodArgAndReturn(callingDomainName);
// ...
}
//
public sealed class MarshalByRefType : MarshalByRefObject {
public MarshalByRefType() {
Console.WriteLine("{0} ctor running in {1}",
this.GetType().ToString(), Thread.GetDomain().FriendlyName);
}
public void SomeMethod() {
Console.WriteLine("Executing in " + Thread.GetDomain().FriendlyName);
}
public MarshalByValType MethodWithReturn() {
Console.WriteLine("Executing in " + Thread.GetDomain().FriendlyName);
MarshalByValType t = new MarshalByValType();
return t;
}
public NonMarshalableType MethodArgAndReturn(String callingDomainName) {
// : callingDomainName [Serializable]
Console.WriteLine("Calling from '{0}' to '{1}'.",
callingDomainName, Thread.GetDomain().FriendlyName);

615

NonMarshalableType t = new NonMarshalableType();


return t;

//
[Serializable]
public sealed class MarshalByValType : Object {
private DateTime m_creationTime = DateTime.Now;
// : DateTime [Serializable]
public MarshalByValType() {
Console.WriteLine("{0} ctor running in {1}, Created on {2:D}",
this.GetType().ToString(),
Thread.GetDomain().FriendlyName,
m_creationTime);
}

public override String ToString() {


return m_creationTime.ToLongDateString();
}

//
// [Serializable]
public sealed class NonMarshalableType : Object {
public NonMarshalableType() {
Console.WriteLine("Executing in " + Thread.GetDomain().FriendlyName);
}
}

, :
Default AppDomain's friendly name= Ch22-1-AppDomains.exe
Main assembly=Ch22-1-AppDomains, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
Demo #1
MarshalByRefType ctor running in AD #2
Type=MarshalByRefType
Is proxy=True
Executing in AD #2
Failed call.
Demo #2
MarshalByRefType ctor running in AD #2
Executing in AD #2
MarshalByValType ctor running in AD #2, Created on Friday, August 07, 2009
Is proxy=False
Returned object created Friday, August 07, 2009
Returned object created Friday, August 07, 2009
Successful call.
Demo #3
MarshalByRefType ctor running in AD #2

616

22. CLR

Calling from 'Ch22-1-AppDomains.exe' to 'AD #2'.


Executing in AD #2
Unhandled Exception: System.Runtime.Serialization.SerializationException:
Type 'NonMarshalableType' in assembly 'Ch22-1-AppDomains, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null' is not marked as serializable.
at MarshalByRefType.MethodArgAndReturn(String callingDomainName)
at Program.Marshalling()
at Program.Main()
is not marked as serializable.
at MarshalByRefType.MethodArgAndReturn(String callingDomainName)
at Program.Marshalling()
at Program.Main()

, CLR.
Marshalling AppDomain,
,
. Windows . .
CLR, Windows .
Windows- ,
. CLR .
CLR,
, GetDomain System.Threading.Thread
, CurrentDomain
System.AppDomain.
String,
.
. CLR -
, .
Marshalling
FriendlyName System.AppDomain.
, Marshalling (
), Main,
Marshalling . : Program ,
MarshalByRefType, MarshalByValType NonMarshalableType.
.
1.

CreateDomain System.AppDomain , CLR Windows. AppDomain

617

CreateDomain; ,

.
:
String . "AD #2".

System.Security.Policy.Evidence ,
CLR . null, , .

System.Security.PermissionSet,
( , IPermission),
PermissionSet CreateDomain, PermissionSet.
System.AppDomainSetup ,
CLR . null,
. , AppDomainSetup,
, CreateDomain
AppDomainSetup.
CreateDomain . , .
, ,
. CLR
; ,
.
, ,
, .
CreateInstanceAndUnwrap AppDomain. : String, ,
( ad2), String, ,
. CreateInstanceAndUnwrap
. (
CreateInstanceAndUnwrap)
,
(MarshalByRefType). ,
MarshalByRefType
, CreateInstanceAndUnwrap
MarshalByRefType.

618

22. CLR

CreateInstanceAndUnwrap,
.

, . CLR
(), , .
CreateInstanceAndUnwrap , , ! CreateInstanceAndUnwrap
.
, MarshalByRefType
System.MarshalByRefObject . , Create
InstanceAndUnwrap ,
MarshalB yR efO bject , CLR . ,
( ) (
CreateInstanceAndUnwrap).
-
, CLR
(proxy). , ,
(, ). ,
.
, .
,
-. ( - GCHandle, . GCHandle
21).
CreateInstanceAndUnwrap
, , - ,
-.
mbrt .
CreateInstanceAndUnwrap MarshalByRefType.
CLR , , . , -
GetType, ,
MarshalByRefType.
, , ,
CreateInstanceAndUnwrap, -.

619

IsTransparentProxy
System.Runtime.Remoting.RemotingService ,
, CreateInstanceAndUnwrap.
IsTransparentProxy true, , .
, SomeMethod.
mbrt -,
. -
.
. GCHandle
- ,
SomeMethod.
, . -, SomeMethod Thread.GetDomain().
FriendlyName. AD #2 (
), ,
AppDomain.CreateDomain AD #2 . , Call Stack
[AppDomain Transition]
(.22.2).

. 22.2. Call Stack

SomeMethod SomeMethod
, , .

620

22. CLR

,
. ,
. ,
.
.

Unload
AppDomain , CLR

.
. mbrt
-;
-
( ).
- SomeMethod,
, . ,
, , ,
SomeMethod AppDomainUnloadedException,
.
, CLR Microsoft ,
. ,
. , ,
.
.
, MarshalByRefObject, -. , , MarshalByRefObject,
JIT- , - (
), FieldGetter
FieldSetter System.Object. ;
, .
, MarshalByRefObject,
, CLR .
, , , 1.
CLR (
), FieldGetter FieldSetter .
,
.
1

621

, , :
private sealed class NonMBRO : Object
{ public Int32 x; }
private sealed class MBRO
: MarshalByRefObject { public Int32 x; }
private static void FieldAccessTiming(){
const Int32 count = 100000000;
NonMBRO nonMbro = new NonMBRO();
MBRO mbro = new MBRO();
Stopwatch sw = Stopwatch.StartNew();
for (Int32 c = 0; c < count; c++) nonMbro.x++;
Console.WriteLine("{0}", sw.Elapsed); // 00:00:00.4073560
sw = Stopwatch.StartNew();
for (Int32 c = 0; c < count; c++) mbro.x++;
Console.WriteLine("{0}", sw.Elapsed); // 00:00:02.5388665
}

NonMBRO, Object,
0,4 , MBRO,
MarshalByRefObject, 2,54 . ,
6 !

MarshalByRefObject - .

,
. ,
-,
. ,
, , .
, ,
, . ,
. ,
, .
CLR (lease manager).
, CLR 5.
, (deactivated) .
,
2 .
CLR
System.Runtime.Remoting.RemotingException.

622

22. CLR

5 2 InitializeLifetimeServices MarshalByRefObject. SDK-


.NET Framework.
2.

.
. CreateInstanceAndUnwrap
MarshalByRefType.
CLR , mbrt ( ) .
MethodWithReturn.
, ,
MarshalByValType.
MarshalByValType System.MarshalByRefObject,
, CLR ;
.
MarshalByValType
[Serializable] MethodWithReturn
. , () ().
24.

( ), CLR
, . CLR
. CLR
( ), . CLR
,
. , CLR
. MethodWithReturn ;
.

CLR
(, AppBase ). CLR
. , ,
.

623


, . ,
( ), .
, , MethodWithReturn,
-, IsTrasparentProxy System.Runtime.Remoting.
RemotingService, ,
MethodWithReturn. ,
IsTrasparentProxy false, ,
, .
, ToString.
mbvt ,

. , Call Stack
: [AppDomain Transition] .
, ,
, ToString. 1 ,
, ,
, .
3.
1 2. , CreateInstanceAndUnwrap

MarshalByValType. mbrt .
MethodArgAndReturn, . CLR
, . , , MarshalByRefObject,
CLR .
[Serializable], CLR (
) ,
, MethodArgAndReturn.
System.String .
System.String MarshalByRefObject, ,
CLR . , System.String
[Serializable], CLR ,
. , String CLR
. String , CLR

624

22. CLR

; .
String,
String . 141.
MethodArgAndReturn ,
.
NonMarshalableType .
NonMarshalableType System.MarshalByRefObject
[Serializable], MethodArgAndReturn . . , MethodArgAndReturn
SerializationException.
, .


CLR
. ,
. : Unload AppDomain (
). CLR
.
1. CLR , -
.
2. CLR , . CLR ,
, ThreadAbortException (
).
finally, .
, ThreadAbortException,
CLR; , .
,
CLR .

1
, System.String .
, , String,
. CLR .

625

CLR , finally catch,


, .
,
, , ,
CLR .
. , CLR
ThreadAbortException.

3. , , CLR
-,
, . , , ,
. AppDomainUnloadedException.
4. CLR , ,
.
, .
5. CLR . ,
AppDomain.Unload, ; AppDomain.Unload
.
. ,
AppDomain.Unload,
, CLR
ThreadAbortException ( ).
, AppDomain.Unload CLR 10,
. ,
AppDomain.Unload, ,
CannotUnloadAppDomainException, (
) .

, AppDomain.Unload, , CLR
, . ThreadAbortException
, .
, . CannotUnloadAppDomainException, ,
, .

626

22. CLR


- .
,

. .
,
MonitoringEnabled AppDomain true.
. ;
MonitoringEnabled false ArgumentException.

AppDomain:
MonitoringSurvivedProcessMemorySize. Int64
,
CLR.
.
MonitoringTotalAllocatedMemorySize. Int64
, .
.
MonitoringSurvivedMemorySize. Int64 ,
. .
MonitoringTotalProcessorTime. TimeSpan , .
,
:
private sealed class AppDomainMonitorDelta : IDisposable {
private AppDomain m_appDomain;
private TimeSpan m_thisADCpu;
private Int64 m_thisADMemoryInUse;
private Int64 m_thisADMemoryAllocated;
static AppDomainMonitorDelta() {
// ,
AppDomain.MonitoringIsEnabled = true;
}
public AppDomainMonitorDelta(AppDomain ad) {
m_appDomain = ad ?? AppDomain.CurrentDomain;
m_thisADCpu = m_appDomain.MonitoringTotalProcessorTime;
m_thisADMemoryInUse = m_appDomain.MonitoringSurvivedMemorySize;

627

m_thisADMemoryAllocated =
m_appDomain.MonitoringTotalAllocatedMemorySize;

public void Dispose() {


GC.Collect();
Console.WriteLine("FriendlyName={0}, CPU={1}ms",
m_appDomain.FriendlyName,
(m_appDomain.MonitoringTotalProcessorTime
m_thisADCpu).TotalMilliseconds);
Console.WriteLine(
" Allocated {0:N0} bytes of which {1:N0} survived GCs",
m_appDomain.MonitoringTotalAllocatedMemorySize
m_thisADMemoryAllocated,
m_appDomain.MonitoringSurvivedMemorySize - m_thisADMemoryInUse);
}
}

AppDomainMonitorDelta:
private static void AppDomainResourceMonitoring() {
using (new AppDomainMonitorDelta(null)) {
// 10 ,
//
var list = new List<Object>();
for (Int32 x = 0; x < 1000; x++) list.Add(new Byte[10000]);
// 20 ,
//
for (Int32 x = 0; x < 2000; x++) new Byte[10000].GetType();
// 5
Int64 stop = Environment.TickCount + 5000;
while (Environment.TickCount < stop) ;
}
}

:
FriendlyName=03-Ch22-1-AppDomains.exe, CPU=5031.25ms
Allocated 30,159,496 bytes of which 10,085,080 survived GCs



, ,
CLR catch. , ,

628

22. CLR

.
; .
FirstChanceException AppDomain.
CLR :
FirstChanceException, , . CLR
catch. - ,
. , CLR
( ).
, , CLR
FirstChanceException, .
, .
, CLR .

: CLR,
CLR . ,
, , . , ,
CLR .


, NT Service, Windows Forms
Windows Presentation Foundation (WPF) (self-hosted) EXE-.
, Windows ,
CLR, (EXE-). CLR, .
, CLR .
,
, , (Main).
CLR , .
. , , CLR .
, .

629

Main Windows-
( ).

, Windows- Exit System.Environment.


, ,
COM- CLR. Win32- ExitProcess.

CLR
. , ,
.

- Silverlight
CLR Microsoft Silverlight
.NET Framework . Silverlight , , Silverlight CLR (CoreClr.dll) (
Internet Explorer
Windows). Silverlight . ,
Silverlight .
Silverlight (sandbox)
- .

Microsoft ASP.NET - XML


ASP.NET ISAPI ( ASPNet_ISAPI.dll).
URL-, , ASP.
NET CLR. -,
ASP.NET , .
, CLR -
(
). ASP.NET CLR ,
, ,
.
CLR -
.
- ASP.NET
-

630

22. CLR

.
JIT- , .
-, ASP.NET CLR . , . ,
Windows- -,
. -

- -.
ASP.NET -
-. , ASP.NET
, , ( ), ,
. ASP.NET ,
(shadow copying).

Microsoft SQL Server


Microsoft SQL Server ,
SQL- C++. SQL- . SQL-
CLR.
, .
!
.
. ,
JIT- , . ,
FCL .
, .
?


, ,
. , CLR. , ,
, ,
.

631


CLR.
CLR.
, .


System.AppDomainManager
CLR . ,
. , System.
AppDomainManager, .

(GAC), .
CLR ,
AppDomainManager. , AppDomainSetup AppDomainManagerAssembly AppDomainManagerType
String. AppDomainManagerAssembly
, , AppDomainManager.
AppDomainManagerType .
, AppDomainManager appDomainManagerAssembly
appDomainManagerType XML- .
ICLRControl SetAppDomainManagerType ,
GAC ,
AppDomainManager1.
, AppDomainManager.
,
. , AppDomainManager,
. ,
. , CLR ,
AppDomainManager. ,
, .

-
CLR, . ( ):
1
AppDomainManager ,
.

632

22. CLR

CLR ,
( . ).
CLR . ,
.
CLR .
, .
CLR Windows-.
,
.
CLR , .
. ,
finally .
. , , catch
finally. , (Critical Execution Region, CER), .
(escalation policy),
CLR . , SQL , CLR
.
, CLR .
, CLR .
. (critical region) . , , , , , , Monitor.
Enter, WaitOne Mutex AcquireReaderLock
AcquireWriterLock ReaderWriterLock1. AutoResetEvent,
ManualResetEvent Semaphore
, .
, CLR ,
, .
.
,
. .
.
BeginCriticalRegion EndCriticalRegion
Thread, . .
.
1

633

,
, CLR
.
, CLR
.


- . .
,
. , ,
, . , ,
. ,
, .

, , , .
?
, . , . ,
. , ?
(, ),
, .
. .22.3 -,
- .
( ).
1. .
2. .
3. ,
, ,
-.
4. try (
, MarshalByRefObject). (, ), .
5. . ,

634

22. CLR

Abort Thread, CLR


ThreadAbortException.
6. , finally,
. . try, catch,
ThreadAbortException.
7. ThreadAbortException
ResetAbort Thread. , .
8. ,
.

. 22.3.

. -,

Abort Thread .
AbortRequested . -

, (safe
place). , ,
( ) . , ,
. (.21).
, , catch finally,
.
, AbortRequested
ThreadAbortException. , , finally . , , ThreadAbortException

635

. ,
, .
ThreadAbort
Exception,
. :
ThreadAbortException, ?
CLR . ThreadAbortException, CLR catch
.
CLR : CLR ThreadAbortException catch,
? catch
ResetAbort Thread. CLR
ThreadAbortException catch.
:
ThreadAbortException ResetAbort Thread?
, SecurityPermission ControlThread, true.
, ,
, , .
, - : ThreadAbortException,
catch finally, ,
. .
, CLR
, , CLR
. ,
ThreadAbortException catch - .
, catch CLR ThreadAbortException.

.
catch finally ,
- .
.
, Thread Abort: ,
Object, . ThreadAbortException,
ExceptionState, ,
. , Abort, , ThreadAbortException.

.

23.

, ,
, . , ,
, ,
-,
(add-ins), .
, , , ,
-. .
CLR
, 22.
. , , .
, , CLR,
, , ,
, , .

.NET Framework 4.5 Microsoft API . API . , LINQ,


,
,
, . API . , .NET 4.5 API
, API. API ( System.Reflection.RuntimeReflectionExtensions)
. .NET Framework API
.
, API ,
.
, ,
API, . Windows Store ( )
API .

637


, JIT- IL- , ,
IL-. JIT-
TypeRef AssemblyRef , . AssemblyRef
. JIT- (
), , ,
(
). ,
( ,
).
CLR , Load
System.Reflection.Assembly. ,
.
CLR- Win32- LoadLibrary. Load Assembly
. :
public class Assembly {
public static Assembly Load(AssemblyName assemblyRef);
public static Assembly Load(String assemblyString);
//
}

Load CLR

(GAC), ,
, codeBase
. Load ,
, CLR GAC. , Load
Assembly, .
, System.IO.FileNotFoundException.

, Microsoft Windows.

. , GAC (x86)
, CLR (.3).
CLR , Load
Assembly :
"SomeAssembly, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=01234567890abcde, ProcessorArchitecture=MSIL"

CLR
ProcessorArchitecture: MSIL (Microsoft IL), x86, IA64 AMD64.

638

23.

Load System.AppDomain.
Assembly, ,
. ,
. , . Load
AppDomain , . :
. ,
, CLR. ,
CLR ,
.
Load AppDomain . ,
System.Assembly System.MarshalByRefObject,
. CLR .
,
FileNotFoundException. ,
Load System.AppDomain.

Load
AppDomain -

, , .
(, ILDasm.exe, PEVerify.
exe, CorFlags.exe, GACUtil.exe, SGen.exe, SN.exe XSD.exe),
. ,
( ) .
, LoadFrom
Assembly:
public class Assembly {
public static Assembly LoadFrom(String path);
//
}

LoadFrom GetAssemblyName System.


Reflection.AssemblyName, ,
AssemblyRef,
System.Reflection.AssemblyName (
). LoadFrom Load Assembly,
AssemblyName. CLR

. ,
Load Assembly,
; LoadFrom. Load ,
LoadFrom , LoadFrom.

639

, ,
LoadFrom Assembly,
.
, LoadFrom URL-:
Assembly a = Assembly.LoadFrom(@"http://Wintellect.com/SomeAssembly.dll");

URL- CLR ,
.
, .
, Internet Explorer ( Work Offline ( ) File ()),
, .
UnsafeLoadFrom, -,
.


. LoadFrom Load, , CLR
, , .

, , LoadFrom .

Microsoft Visual
Studio LoadFile Assembly.

.
,
,
. LoadFile CLR ,
AssemblyResolve
.
,
( ), , ReflectionOnlyLoadFrom
, , ReflectionOnlyLoad Assembly.
:
public class Assembly {
public static Assembly ReflectionOnlyLoadFrom(String assemblyFile);
public static Assembly ReflectionOnlyLoad(String assemblyString);
//
}

640

23.

ReflectionOnlyLoadFrom , GAC -
. ReflectionOnlyLoad GAC, , ,
codeBase. Load ,
, ,
. ,
AppDomain
ApplyPolicy.
ReflectionOnlyLoadFrom ReflectionOnlyLoad
CLR - , InvalidOperationException.
,
, ,
.
,
,
ReflectionOnlyAssemblyResolve AppDomain, , (
ApplyPolicy AppDomain); CLR .
, ReflectionOnlyLoadFrom
ReflectionOnlyLoad Assembly,
.

. , CLR
. , ,
,
. CLR
,
. , ,
. . 22.
, , ReflectionOnlyLoadFrom
ReflectionOnlyLoad, . ,
. CLR , , ,
,
, .
- ,
.

EXE-, DLL-.
. EXE-.

641

DLL-,
EXE- Microsoft .NET Framework.
DLL- Visual Studio
DLL- Build Action
Embedded Resource. C# DLL EXE-, .
CLR ,
.
ResolveAssembly
. :
private static Assembly ResolveEventHandler(Object sender, ResolveEventArgs args) {
String dllName = new AssemblyName(args.Name).Name + ".dll";
var assem = Assembly.GetExecutingAssembly();
String resourceName = assem.GetManifestResourceNames().FirstOrDefault(rn =>
rn.EndsWith(dllName));
if (resourceName == null) return null;
// Not found, maybe another handler will find it
using (var stream = assem.GetManifestResourceStream(resourceName)) {
Byte[] assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
}

, ,
DLL-, AssemblyResolve,
DLL-
Load,
Byte[]. DLL ,
, ,
.



, . , , .. System.Reflection ,
.
.
, ,
,

642

23.

, .
System.Reflection , ,
. ,
(.18) .
,
IL-. ,
, ILDasm.exe Microsoft.

, , CLR.
. FCL
, ,
, ,
, .

. ,
. ,
FCL (.24) , ,
.

, .
Microsoft Visual Studio , ,

- Windows Forms .
,
.
,
, ,
.
Win32- LoadLibrary GetProcAddress. , ,
(late binding) (early binding), ,
.


, ,
. .

643


. ,
. ,
int Type.GetType("int"); , null,
CLR int System.Int32.
.
,
. ,
System.Reflection.
, .

.

,
. , CLR
, . , CLR
.

/. ,
, .
, .
, ,
( )
.
, . ,
,
, ( ), , .
, , .
,
,

, , .
.
.
.

644

23.

,
, , .
FCL .
ExportedTypes Assembly. ,
:
using System;
using System.Reflection;
public static class Program {
public static void Main() {
String dataAssembly = "System.Data, version=4.0.0.0, " +
"culture=neutral, PublicKeyToken=b77a5c561934e089";
LoadAssemAndShowPublicTypes(dataAssembly);
}
private static void LoadAssemAndShowPublicTypes(String assemId) {
//
Assembly a = Assembly.Load(assemId);
// ,
//
foreach (Type t in a.ExportedTypes) {
//
Console.WriteLine(t.FullName);
}
}
}

Type
System.Type. System.
Type .
( ).
, System.Object
GetType. CLR
Type.
Type, , ,
:
private static Boolean AreObjectsTheSameType(Object o1, Object o2) {
return o1.GetType() == o2.GetType();
}

GetType Object FCL


Type:
System.Type
GetType. String.

645

( ). , (, int, string, bool


C#), , CLR. , ,
. ,
Type.
, ,
MSCorLib.dll.
, null System.
TypeLoadException ,
GetType .
FCL .
GetType , :
"System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"

GetType ( ).
System.Type ReflectionOnlyGetType.
, GetType, ,
, .
System.TypeInfo DeclaredNestedTypes
GetDeclaredNestedTypes.
System.Reflection.Assembly GetType, DefinedTypes ExportedTypes.

Microsoft , ,
.
, ,
. FCL Backus-Naur
Form Grammar for Type Names. MakeArrayType,
MakeByRefType, MakeGenericType MakePointerType Type TypeInfo.

,
Type . Type
, ,
. C# typeof,
,
, :

646

23.

private static void SomeMethod(Object o) {


// GetType
// ( )
// typeof
// ( )
if (o.GetType() == typeof(FileInfo)) { ... }
if (o.GetType() == typeof(DirectoryInfo)) { ... }
}

if , o FileInfo,
, FileInfo. , ,
.
is as C#.

, Type , .
TypeInfo, .
Type TypeInfo GetTypeInfo
System.Reflection.IntrospectionExtensions:
Type typeReference = ...; // : o.GetType() typeof(Object)
TypeInfo typeDefinition = typeReference.GetTypeInfo();

, TypeInfo
Type AsType TypeInfo.
TypeInfo typeDefinition = ...;
Type typeReference = typeDefinition.AsType();

TypeInfo CLR , , , . ,
, ( Type). TypeInfo
. , IsPublic, IsSealed, IsAbstract,
IsClass, IsValueType .., , . ( Assembly, AssemblyQualifiedName, FullName, Module .)
, , .
BaseType . ,
TypeInfo, FCL.

, Exception
- ExceptionTree ( . )
,
,
System.Exception. , , ,
, 20.

647

public static void Go() {


//
LoadAssemblies();
//
var allTypes =
(from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.ExportedTypes
where typeof(Exception).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())
orderby t.Name
select t).ToArray();
//
Console.WriteLine(WalkInheritanceHierarchy(new StringBuilder(), 0,
typeof(Exception),
allTypes));
}
private static StringBuilder WalkInheritanceHierarchy(
StringBuilder sb, Int32 indent, Type baseType, IEnumerable<Type> allTypes) {
String spaces = new String(' ', indent * 3);
sb.AppendLine(spaces + baseType.FullName);
foreach (var t in allTypes) {
if (t.GetTypeInfo().BaseType != baseType) continue;
WalkInheritanceHierarchy(sb, indent + 1, t, allTypes);

}
return sb;

private static void LoadAssemblies() {


String[] assemblies = {
"System, PublicKeyToken={0}",
"System.Core, PublicKeyToken={0}",
"System.Data, PublicKeyToken={0}",
"System.Design, PublicKeyToken={1}",
"System.DirectoryServices, PublicKeyToken={1}",
"System.Drawing, PublicKeyToken={1}",
"System.Drawing.Design, PublicKeyToken={1}",
"System.Management, PublicKeyToken={1}",
"System.Messaging, PublicKeyToken={1}",
"System.Runtime.Remoting, PublicKeyToken={0}",
"System.Security, PublicKeyToken={1}",
"System.ServiceProcess, PublicKeyToken={1}",
"System.Web, PublicKeyToken={1}",
"System.Web.RegularExpressions, PublicKeyToken={1}",
"System.Web.Services, PublicKeyToken={1}",
"System.Xml, PublicKeyToken={0}",
};
String EcmaPublicKeyToken = "b77a5c561934e089";
String MSPublicKeyToken = "b03f5f7f11d50a3a";
// , System.Object.

648

23.

// .
Version version = typeof(System.Object).Assembly.GetName().Version;
//
foreach (String a in assemblies) {
String AssemblyIdentity =
String.Format(a, EcmaPublicKeyToken, MSPublicKeyToken) +
", Culture=neutral, Version=" + version;
Assembly.Load(AssemblyIdentity);
}
}


, Type,
. FCL .
CreateInstance System.Activator.
CreateInstance.
Type String,
, . , Type, : ,
.
CreateInstance, ,
. -, , ,
. -, , .
-,
System.Runtime.Remoting.ObjectHandle ( System.
MarshalByRefObject).
ObjectHandle , ,
, ,
, .
, Unwrap ObjectHandle.
, .
, -
-. .
CreateInstanceFrom System.Activator. Activator
CreateInstanceFrom. CreateInstance , , .
LoadFrom (
Load) Assembly. CreateInstanceFrom
Type, ObjectHandle,
.

649

System.AppDomain. AppDomain
( ), : CreateInstance, CreateInstanceAndUnwrap, Create
IntanceFrom CreateInstanceFromAndUnwrap.
Activator , ,
, . ,
Unwrap, , .
Invoke System.Reflection.ConstructorInfo.
TypeInfo
ConstructorInfo, Invoke.
, .
.

CLR , . , . CreateInstance Activator


.
, , CreateInstance,
Type, ,
Type Boolean.

,
( , System.Array) ( System.
MulticastDelegate ). ,
CreateInstance Array (
). CreateInstance Type, . CreateInstance
. CreateDelegate Delegate (
).
CreateDelegate Type, .
,
.

, MakeGenericType
Type, , . Type
. :
using System;
using System.Reflection;

650

23.

internal sealed class Dictionary<TKey, TValue> { }


public static class Program {
public static void Main() {
// Type
Type openType = typeof(Dictionary<,>);
// , TKey=String, TValue=Int32
Type closedType = openType.MakeGenericType(
new Type[] { typeof(String), typeof(Int32) });
//
Object o = Activator.CreateInstance(closedType);
// ,
Console.WriteLine(o.GetType());
}
}

, :
Dictionary`2[System.String,System.Int32]




. ,
, (add-in) . ,
, ,
.
.
, , .
,
,
MSCorLib.dll. ,
. ,
(.3), .
,
. ,
. , ,
. - ,
(.3).

651

, MSCorLib.dll: CLR
MSCorLib.dll, CLR. ,
MSCorLib.dll. ,
MSCorLib.dll (.3). , .

, ,
. , .
, :
.
, . ,
, .
. ,
, .
.
, .
, . .
,
.
,
, . -, :
using System;
namespace Wintellect.HostSDK {
public interface IAddIn {
String DoSomething(Int32 x);
}
}

AddInTypes.dll,
, HostSDK.
HostSDK.dll:
using System;
using Wintellect.HostSDK;
public sealed class AddIn_A : IAddIn {
public AddIn_A() {
}
public String DoSomething(Int32 x) {
return "AddIn_A: " + x.ToString();

652

23.

public sealed class AddIn_B : IAddIn {


public AddIn_B() {
}
public String DoSomething(Int32 x) {
return "AddIn_B: " + (x * 2).ToString();
}
}

( )
Host.exe. HostSDK.dll.
, ,
, dll,
, EXE- . Microsoft
MEF (Managed Extensibility Framework) ,
,
.
, MEF, .
using
using
using
using
using

System;
System.IO;
System.Reflection;
System.Collections.Generic;
Wintellect.HostSDK;

public static class Program {


public static void Main() {
// , Host.exe
String AddInDir =
Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
// ,
// EXE-
var AddInAssemblies = Directory.EnumerateFiles(AddInDir, "*.dll");
// Type,
//
var AddInTypes =
from file in AddInAssemblies
let assembly = Assembly.Load(file)
from t in assembly.ExportedTypes //
// , , IAddIn
where t.IsClass &&
typeof(IAddIn).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())
select t;
// : ,
//
//

653

foreach (Type t in AddInTypes) {


IAddIn ai = (IAddIn) Activator.CreateInstance(t);
Console.WriteLine(ai.DoSomething(5));
}

.
. , ,
,
. ,
, MarshalByRefObject.

MarshalByRefObject . ( ) ( ),
,
.



, ,
. ,
,
.
( ) , ;

.
,
.
,
.
ILDasm, FxCop
Windows Forms Web Forms, Visual Studio.

.
, ,
.

654

23.


, , , , . FCL System.Reflection.MemberInfo
, , . MemberInfo
,
(.23.1).

. 23.1.

,
.
, . DeclaredMembers, ,
MemberInfo;
. (, , ,
..) ( ToString).
using System;
using System.Reflection;
public static class Program {
public static void Main() {
// ,
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly a in assemblies) {

655

Show(0, "Assembly: {0}", a);


//
foreach (Type t in a.ExportedTypes) {
Show(1, "Type: {0}", t);
//
foreach (MemberInfo mi in t.GetTypeInfo().DeclaredMembers) {
String typeName = String.Empty;
if (mi is Type) typeName = "(Nested) Type";
if (mi is FieldInfo) typeName = "FieldInfo";
if (mi is MethodInfo) typeName = "MethodInfo";
if (mi is ConstructorInfo) typeName = "ConstructoInfo";
if (mi is PropertyInfo) typeName = "PropertyInfo";
if (mi is EventInfo) typeName = "EventInfo";
Show(2, "{0}: {1}", typeName, mi);
}
}
}
}
private static void Show(Int32 indent, String format, params Object[] args) {
Console.WriteLine(new String(' ', 3 * indent) + format, args);
}
}

.
:
Assembly: mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
Type: System.Object
MethodInfo: System.String ToString()
MethodInfo: Boolean Equals(System.Object)
MethodInfo: Boolean Equals(System.Object, System.Object)
MethodInfo: Boolean ReferenceEquals(System.Object, System.Object)
MethodInfo: Int32 GetHashCode()
MethodInfo: System.Type GetType()
MethodInfo: Void Finalize()
MethodInfo: System.Object MemberwiseClone()
MethodInfo: Void FieldSetter(System.String, System.String, System.Object)
MethodInfo: Void FieldGetter(System.String, System.String,
System.Object ByRef)
MethodInfo: System.Reflection.FieldInfo GetFieldInfo(System.String,
System.String)
ConstructoInfo: Void .ctor()
Type: System.Collections.Generic.IComparer`1[T]
MethodInfo: Int32 Compare(T, T)
Type: System.Collections.IEnumerator
MethodInfo: Boolean MoveNext()
MethodInfo: System.Object get_Current()
MethodInfo: Void Reset()
PropertyInfo: System.Object Current
Type: System.IDisposable

656

23.

MethodInfo: Void Dispose()


Type: System.Collections.Generic.IEnumerator`1[T]
MethodInfo: T get_Current()
PropertyInfo: T Current
Type: System.ArraySegment`1[T]
MethodInfo: T[] get_Array()
MethodInfo: Int32 get_Offset()
MethodInfo: Int32 get_Count()
MethodInfo: Int32 GetHashCode()
MethodInfo: Boolean Equals(System.Object)
MethodInfo: Boolean Equals(System.ArraySegment`1[T])
MethodInfo: Boolean op_Equality(System.ArraySegment`1[T],
System.ArraySegment`1[T])
MethodInfo: Boolean op_Inequality(System.ArraySegment`1[T],
System.ArraySegment`1[T])
ConstructoInfo: Void .ctor(T[])
ConstructoInfo: Void .ctor(T[], Int32, Int32)
PropertyInfo: T[] Array
PropertyInfo: Int32 Offset
PropertyInfo: Int32 Count
FieldInfo: T[] _array
FieldInfo: Int32 _offset

MemberInfo , . .23.1 ( )
MemberInfo, . , System.
Type MemberInfo, Type .
23.1. , ,
MemberInfo

Name

String

DeclaringType

Type

Module

Module

CustomAttributes

, IEnumer
able<CustomAttri
buteData>

, , .
.
Assembly MemberInfo, ,

, DeclaredMembers,
. DeclaredMembers, -

657

, TypeInfo ,
: GetDeclaredNestedType, GetDeclaredField,
GetDeclaredMethod, GetDeclaredPropert GetDeclaredEvent.
TypeInfo, FieldInfo, MethodInfo, PropertyInfo
EventInfo . GetDeclaredMethods, MethodInfo ,
.
.23.2 ,
. (AppDomain)
, , (Assembly)
, (Assembly) (Module) .
, (Type)
( , , , , ).
,
. , ,
Namespace.
FieldInfo #1

AppDomain

Assembly #1
Assembly #2

FieldInfo #2

Module #1
Module #2

Type #1
Type #2

ConstructorInfo #1
ConstructorInfo #2

MethodInfo #1
MethodInfo #2

PropertyInfo #1
PropertyInfo #2

EventInfo #1
EventInfo #2

. 23.2. ,

( ,
). , , -
/ GetParameters, ParameterInfo,

658

23.

. ReturnParameter,
ParameterInfo .
, GetGenericArguments. ,
, ,
GetCustomAttributes.


, , .
.
. .23.2 ,
.
23.2.

FieldInfo

GetValue , SetValue

ConstructorInfo

Invoke

MethodInfo

Invoke

PropertyInfo

GetValue get, SetValue


set

EventInfo

AddEventHandler add,
RemoveEventHandler remove

PropertyInfo (.10), CanRead, CanWrite


PropertyType. , ,
. PropertyInfo GetMethod SetMethod,
MethodInfo . GetValue SetValue PropertyInfo ,
MethodInfo
. (#) SetValue
GetValue index Object [].
EventInfo (.11).
EventHandlerType,
Type . EventInfo
AddMethod RemoveMethod, MethodInfo
. ,

659

MethodInfo
AddEventHandler RemoveEventHandler EventInfo.
-
. SomeType
: (m_someField), (SomeType), Int32 ,
(ToString), (SomeProp) (SomeEvent).
SomeType
SomeType.
-.
BindToMemberThenInvokeTheMember .
BindToMemberCreateDelegateToMemberThenInvokeTheMember ,
. ,

.
UseDynamicToBindAndInvokeTheMember
# dynamic (.5) .
,
,
.
.
using
using
using
using

System;
System.Reflection;
Microsoft.CSharp.RuntimeBinder;
System.Linq;

// .
// , , ,
internal sealed class SomeType {
private Int32 m_someField;
public SomeType(ref Int32 x) { x *= 2; }
public override String ToString() { return m_someField.ToString(); }
public Int32 SomeProp {
get { return m_someField; }
set {
if (value < 1)
throw new ArgumentOutOfRangeException("value");
m_someField = value;
}
public event EventHandler SomeEvent;

660

23.

private void NoCompilerWarnings() { SomeEvent.ToString();}

public static class Program {


public static void Main() {
Type t = typeof(SomeType);
BindToMemberThenInvokeTheMember(t);
Console.WriteLine();
BindToMemberCreateDelegateToMemberThenInvokeTheMember(t);
Console.WriteLine();

UseDynamicToBindAndInvokeTheMember(t);
Console.WriteLine();

private static void BindToMemberThenInvokeTheMember(Type t) {


Console.WriteLine("BindToMemberThenInvokeTheMember");
//
Type ctorArgument = Type.GetType("System.Int32&");
// typeof(Int32).MakeByRefType();
ConstructorInfo ctor = t.GetTypeInfo().DeclaredConstructors.First(
c => c.GetParameters()[0].ParameterType == ctorArgument);
Object[] args = new Object[] { 12 }; //
Console.WriteLine("x before constructor called: " + args[0]);
Object obj = ctor.Invoke(args);
Console.WriteLine("Type: " + obj.GetType());
Console.WriteLine("x after constructor returns: " + args[0]);
//
FieldInfo fi = obj.GetType().GetTypeInfo().GetDeclaredField("m_someField");
fi.SetValue(obj, 33);
Console.WriteLine("someField: " + fi.GetValue(obj));
//
MethodInfo mi = obj.GetType().GetTypeInfo().GetDeclaredMethod("ToString");
String s = (String)mi.Invoke(obj, null);
Console.WriteLine("ToString: " + s);
//
PropertyInfo pi = obj.GetType().GetTypeInfo().GetDeclaredProperty("SomeProp");
try {
pi.SetValue(obj, 0, null);
}
catch (TargetInvocationException e) {
if (e.InnerException.GetType() != typeof(ArgumentOutOfRangeException)) throw;
Console.WriteLine("Property set catch.");
}
pi.SetValue(obj, 2, null);
Console.WriteLine("SomeProp: " + pi.GetValue(obj, null));

661

//
EventInfo ei = obj.GetType().GetTypeInfo().GetDeclaredEvent("SomeEvent");
EventHandler eh = new EventHandler(EventCallback); // . ei.EventHandlerType
ei.AddEventHandler(obj, eh);
ei.RemoveEventHandler(obj, eh);
}
//
private static void EventCallback(Object sender, EventArgs e) { }
private static void BindToMemberCreateDelegateToMemberThenInvokeTheMember(Type t) {
Console.WriteLine("BindToMemberCreateDelegateToMemberThenInvokeTheMember");
// ( )
Object[] args = new Object[] { 12 }; //
Console.WriteLine("x before constructor called: " + args[0]);
Object obj = Activator.CreateInstance(t, args);
Console.WriteLine("Type: " + obj.GetType().ToString());
Console.WriteLine("x after constructor returns: " + args[0]);
// : .
//
MethodInfo mi = obj.GetType().GetTypeInfo().GetDeclaredMethod("ToString");
var toString = mi.CreateDelegate<Func<String>>(obj);
String s = toString();
Console.WriteLine("ToString: " + s);
//
PropertyInfo pi = obj.GetType().GetTypeInfo().GetDeclaredProperty("SomeProp");
var setSomeProp = pi.SetMethod.CreateDelegate<Action<Int32>>(obj);
try {
setSomeProp(0);
}
catch (ArgumentOutOfRangeException) {
Console.WriteLine("Property set catch.");
}
setSomeProp(2);
var getSomeProp = pi.GetMethod.CreateDelegate<Func<Int32>>(obj);
Console.WriteLine("SomeProp: " + getSomeProp());
//
EventInfo ei = obj.GetType().GetTypeInfo().GetDeclaredEvent("SomeEvent");
var addSomeEvent = ei.AddMethod.CreateDelegate<Action<EventHandler>>(obj);
addSomeEvent(EventCallback);
var removeSomeEvent =
ei.RemoveMethod.CreateDelegate<Action<EventHandler>>(obj);
removeSomeEvent(EventCallback);
}
private static void UseDynamicToBindAndInvokeTheMember(Type t) {
Console.WriteLine("UseDynamicToBindAndInvokeTheMember");

662

23.

// (dynamic )
Object[] args = new Object[] { 12 }; //
Console.WriteLine("x before constructor called: " + args[0]);
dynamic obj = Activator.CreateInstance(t, args);
Console.WriteLine("Type: " + obj.GetType().ToString());
Console.WriteLine("x after constructor returns: " + args[0]);
//
try {
obj.m_someField = 5;
Int32 v = (Int32)obj.m_someField;
Console.WriteLine("someField: " + v);
}
catch (RuntimeBinderException e) {
// ,
Console.WriteLine("Failed to access field: " + e.Message);
}
//
String s = (String)obj.ToString();
Console.WriteLine("ToString: " + s);
//
try {
obj.SomeProp = 0;
}
catch (ArgumentOutOfRangeException) {
Console.WriteLine("Property set catch.");
}
obj.SomeProp = 2;
Int32 val = (Int32)obj.SomeProp;
Console.WriteLine("SomeProp: " + val);
//
obj.SomeEvent += new EventHandler(EventCallback);
new EventHandler(EventCallback);
obj.SomeEvent =
}
}
internal static class ReflectionExtensions {
// ,
public static TDelegate CreateDelegate<TDelegate>(this MethodInfo mi,
Object target = null) {
return (TDelegate)(Object)mi.CreateDelegate(typeof(TDelegate), target);
}
}

, :
BindToMemberThenInvokeTheMember
x before constructor called: 12
Type: SomeType
x after constructor returns: 24

663

someField: 33
ToString: 33
Property set catch.
SomeProp: 2
BindToMemberCreateDelegateToMemberThenInvokeTheMember
x before constructor called: 12
Type: SomeType
x after constructor returns: 24
ToString: 0
Property set catch.
SomeProp: 2
UseDynamicToBindAndInvokeTheMember
x before constructor called: 12
Type: SomeType
x after constructor returns: 24
Failed to access field: 'SomeType.m_someField' is inaccessible due to
its protection level
ToString: 0
Property set catch.
SomeProp: 2

: SomeType
Int32. ,
Int32.
BindToMemberThenInvokeTheMember GetType Type, "System.Int32&".
(&) , .
( .
FCL). ,
MakeByRefType Type.



(
Type) (, MemberInfo), .
. , :
Type , MemberInfo, . ,
,
.
CLR
. CLR ,
. CLR

664

23.

. ,
Type - MemberInfo, ,
, . FCL
( System): RuntimeTypeHandle,
RuntimeFieldHandle RuntimeMethodHandle. IntPtr; ( ).
IntPtr , ,
.
Type MemberInfo
, . ,
.
Type RuntimeTypeHandle,
GetTypeHandle Type, Type.
RuntimeTypeHandle Type,
GetTypeFromHandle Type, RuntimeTypeHandle.
FieldInfo RuntimeFieldHandle, FieldHandle FieldInfo.
RuntimeTypeHandle FieldInfo, GetTypeFromHandle FieldInfo.
MethodInfo RuntimeMethodHandle,
MethodHandle MethodInfo.
RuntimeTypeHandle MethodInfo, GetMethodFromHandle MethodInfo.
MethodInfo,
RuntimeMethodHandle,
:
using System;
using System.Reflection;
using System.Collections.Generic;
public sealed class Program {
private const BindingFlags c_bf = BindingFlags.FlattenHierarchy |
BindingFlags.Instance |
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
public static void Main() {
//
Show("Before doing anything");
// MethodInfo MSCorlib.dll
List<MethodBase> methodInfos = new List<MethodBase>();
foreach (Type t in typeof(Object).Assembly.GetExportedTypes()) {

665

//
if (t.IsGenericTypeDefinition) continue;

MethodBase[] mb = t.GetMethods(c_bf);
methodInfos.AddRange(mb);

//
Console.WriteLine("# of methods={0:N0}", methodInfos.Count);
Show("After building cache of MethodInfo objects");
// RuntimeMethodHandles
// MethodInfo
List<RuntimeMethodHandle> methodHandles =
methodInfos.ConvertAll<RuntimeMethodHandle>(mb => mb.MethodHandle);
Show("Holding MethodInfo and RuntimeMethodHandle cache");
GC.KeepAlive(methodInfos); //
methodInfos = null; //
Show("After freeing MethodInfo objects");
methodInfos = methodHandles.ConvertAll<MethodBase>(
rmh=> MethodBase.GetMethodFromHandle(rmh));
Show("Size of heap after re-creating MethodInfo objects");
GC.KeepAlive(methodHandles); //
GC.KeepAlive(methodInfos); //
methodHandles = null; //
methodInfos = null; //
Show("After freeing MethodInfos and RuntimeMethodHandles");
}
}

:
Heap
# of
Heap
Heap
Heap
Heap
Heap

size= 85,000 - Before doing anything


methods=48,467
size= 7,065,632 - After building cache of MethodInfo objects
size= 7,453,496 - Holding MethodInfo and RuntimeMethodHandle cache
size= 6,732,704 - After freeing MethodInfo objects
size= 7,372,704 - Size of heap after re-creating MethodInfo objects
size= 192,232 - After freeing MethodInfos and RuntimeMethodHandles

24.

(serialization)
. , (deserialization).
:
( )
.
ASP.NET
.
. Windows Forms Windows
Presentation Foundation (WPF).
,
.
,
. .NET Framework , . (.22).
, , .
, , .
, .
,
(, ), , , in out,
.
, .NET Framework
. , .NET Framework.
, ,
, .NET Framework.
, .NET Framework.
, , ,
. , , -

667

. , .NET Framework ,
,
. , ,
, .

CLR,
CLR ,
public, protected, internal private,
. CLR XML System.Runtime.Serialization.
NetDataContractSerializer. .NET Framework , CLR-
CLR- . System.Xml.
Serialization.XmlSerializer System.Runtime.Serialization.DataContractSerializer.

:
using
using
using
using

System;
System.Collections.Generic;
System.IO;
System.Runtime.Serialization.Formatters.Binary;

internal static class QuickStart {


public static void Main() {
//
var objectGraph = new List<String> {
"Jeff", "Kristin", "Aidan", "Grant" };
Stream stream = SerializeToMemory(objectGraph);
//
stream.Position = 0;
objectGraph = null;
//
objectGraph = (List<String>) DeserializeFromMemory(stream);
foreach (var s in objectGraph) Console.WriteLine(s);
}
private static MemoryStream SerializeToMemory(Object objectGraph) {
// ,

668

24.

//
MemoryStream stream = new MemoryStream();
//
BinaryFormatter formatter = new BinaryFormatter();
//
formatter.Serialize(stream, objectGraph);
//
return stream;
}
private static Object DeserializeFromMemory(Stream stream) {
//
BinaryFormatter formatter = new BinaryFormatter();
//
return formatter.Deserialize(stream);
}
}

, ! SerializeToMemory System.
IO.MemoryStream. ,
. BinaryFormatter (
System.Runtime.Serialization.Formatters.Binary). (formatter) ( System.
Runtime.Serialization.IFormatter), . FCL :
BinaryFormatter ( ) SoapFormatter
( System.Runtime.Serialization.Formatters.
Soap System.Runtime.Serialization.Formatters.
Soap.dll).

3.5, .NET Framework SoapFormatter


.
, XML.
XML-
XML-, XmlSerializer DataContractSerializer.

Serialize
, -, -, -, . - ,
.
, System.IO.Stream.
, MemoryStream, FileStream,
NetworkStream ..

669

Serialize :
Int32, String, DateTime, Exception, List<String>, Dictionary<Int32, DateTime>
.. , objectGraph, , ,
. , objectGraph -

, , ,
. Serialize .
, ,
.

Serialize . -
, .
. , ,
. .
SerializeToMemory
Serialize MemoryStream .
, . ,
, , ..
DeserializeFromStream -
. .
BinaryFormatter, Deserialize.
-
.
Deserialize ,
, , .
Deserialize ,
.

, () :
private static Object DeepClone(Object original) {
//
using (MemoryStream stream = new MemoryStream()) {
//
BinaryFormatter formatter = new BinaryFormatter();
// " -"
formatter.Context = new StreamingContext(StreamingContextStates.Clone);
//

670

24.
formatter.Serialize(stream, original);
//
stream.Position = 0;
//
// ( )
return formatter.Deserialize(stream);
}
}

. -,
,
. , ,
SoapFormatter, BinaryFormatter. Deserialize
, System.Runtime.Serialization.
SerializationException.
-,
. , :
[Serializable] internal sealed class Customer { /* ... */ }
[Serializable] internal sealed class Order { /* ... */ }


:
private static List<Customer> s_customers = new List<Customer>();
private static List<Order> s_pendingOrders = new List<Order>();
private static List<Order> s_processedOrders = new List<Order>();


:
private static void SaveApplicationState(Stream stream) {
//
BinaryFormatter formatter = new BinaryFormatter();
//
formatter.Serialize(stream, s_customers);
formatter.Serialize(stream, s_pendingOrders);
formatter.Serialize(stream, s_processedOrders);
}

, ,
:
private static void RestoreApplicationState(Stream stream) {
//

671

BinaryFormatter formatter = new BinaryFormatter();


//
// ,
s_customers
s_pendingOrders
s_processedOrders
}

(
)
= (List<Customer>) formatter.Deserialize(stream);
= (List<Order>)
formatter.Deserialize(stream);
= (List<Order>)
formatter.Deserialize(stream);

, , .

. BinaryFormatter ,
( ), , , . ,

Load System.Reflection.Assembly (
23).
,
. , , .
,
, . ,
, , SerializationException
. , ,
.


Assembly.LoadFrom,
. .
,
Load Assembly LoadFrom. CLR
SerializationException. .
.
, ,
Assembly.LoadFrom,
, System.ResolveEventHandler,
Deserialize
AssemblyResolve System.AppDomain. ( Deserialize
, .) ,
, CLR ResolveEventHandler.
.
.
Assembly.LoadFrom,
ResolveEventHandler.

672

24.

, .
,
, ,
.


, . . , :
internal struct Point { public Int32 x, y; }
private
Point
using
new
}

static void OptInSerialization() {


pt = new Point { x = 1, y = 2 };
(var stream = new MemoryStream()) {
BinaryFormatter().Serialize(stream, pt); //
// SerializationException

, Serialize System.Runtime.
Serialization.SerializationException. , Point

, . System.SerializableAttribute,
( ,
System, System.Runtime.Serialization):
[Serializable]
internal struct Point { public Int32 x, y; }

, , Point .
,
. ,
Serialize SerializationException.

, . , ,

. , ,
SerializationException.
- . , .
, , MemoryStream.
, MemoryStream
- ( ).

673

SerializableAttribute
(), (),
() ( , ,
SerializableAttribute). .
, Person ,
Employee :
[Serializable]
internal class Person { ... }
internal class Employee : Person { ... }

SerializableAttribute
Employee:
[Serializable]
internal class Person { ... }
[Serializable]
internal class Employee : Person { ... }

.
,
SerializableAttribute , ;
,
,
. System.Object
SerializableAttribute.

. ,
. ,
, public, protected, internal private.
(, ),
.
, ,
, . , .

SerializableAttribute (, , ..) -

674

24.

1. ,
. :
, . , , Windows (, , , , , ,
..).
, Windows
.
. , , ,
.
System.
NonSerializedAttribute , ( , System, System.
Runtime.Serialization):
[Serializable]
internal class Circle {
private Double m_radius;
[NonSerialized]
private Double m_area;

public Circle(Double radius) {


m_radius = radius;
m_area = Math.PI * m_radius * m_radius;
}
...

Circle ,
m_radius. m_area , NonSerializedAttribute. ,
. ,
.
, Circle :
Circle c = new Circle(10);

C# , [Serializable], . , , ,
,
.
1

675

m_area , 314,159.
-
m_radius, 10. ,
Circle . m_radius 10,
m_area 0, 314,159!
, :
[Serializable]
internal class Circle {
private Double m_radius;
[NonSerialized]
private Double m_area;
public Circle(Double radius) {
m_radius = radius;
m_area = Math.PI * m_radius * m_radius;
}

[OnDeserialized]
private void OnDeserialized(StreamingContext context) {
m_area = Math.PI * m_radius * m_radius;
}

Circle System.
Runtime.Serialization.OnDeserializedAttribute1. -


. ,
.
Circle OnDeserialized
m_radius,
m_area. 314,159.
OnDeserializedAttribute
System.Runtime.Serialization
OnSerializingAttribute, OnSerializedAttribute OnDeserializingAttribute,

. ,
:
[Serializable]
public class MyType {
Int32 x, y; [NonSerialized] Int32 sum;

System.Runtime.Serialization.OnDeserialized
,
OnDeserialization System.Runtime.Serialization.
IDeserializationCallback.
1

676

24.

public MyType(Int32 x, Int32 y) {


this.x = x; this.y = y; sum = x + y;
}
[OnDeserializing]
private void OnDeserializing(StreamingContext context) {
// .
}
[OnDeserialized]
private void OnDeserialized(StreamingContext context) {
// .
sum = x + y;
}
[OnSerializing]
private void OnSerializing(StreamingContext context) {
// .
}
[OnSerialized]
private void OnSerialized(StreamingContext context) {
// .
}
}

, , StreamingContext ( )
void. . private,
; ,
private-.


, OnSerializing.
,
OnSerialized. , OnDeserializing,
,
OnDeserialized.
, , OnDeserialized ,
.
,
OnDeserialized .

.
,
.

677

, (Hashtable Dictionary), -.
OnDeserialized. (
), (
). ,
, -.
-
. Dictionary .

,
,
SerializationException , .
,
. , System.
Runtime.Serialization.OptionalFieldAttribute.
OptionalFieldAttribute , . ,
SerializationException,
.


.
,
.
FCL
FormatterServices System.Runtime.Serialization.
.
,
SerializableAttribute:
1. GetSerializableMembers
FormatterServices:
public static MemberInfo[] GetSerializableMembers(
Type type, StreamingContext context);

(
NonSerializedAttribute) .
MemberInfo .
2. System.Reflection.MemberInfo GetObjectData FormatterServices:
public static Object[] GetObjectData(Object obj, MemberInfo[] members);

678

24.

Object,
. Object MemberInfo . Object
, MemberInfo .
3.
.
4. ,
- .
,
SerializableAttribute:
1. - . ,
( ).
SerializationException, .
,
GetTypeFromAssembly FormatterServices
:
public static Type GetTypeFromAssembly(Assembly assem, String name);

System.Type,
.
2. GetUninitializedObject
FormatterServices:
public static Object GetUninitializedObject(Type type);

, . null 0.
1. , , MemberInfo, GetSerializableMembers
FormatterServices. ,
.
2. - Object.
3. , MemberInfo, Object
PopulateObjectMembers FormatterServices:
public static Object PopulateObjectMembers(
Object obj, MemberInfo[] members, Object[] data);

,
. .

679



, OnSerializing, OnSerialized,
OnDeserializing, OnDeserialized, NonSerialized OptionalField.
, . ,
, , .
,
System.Runtime.Serialization.ISerializable,
:
public interface ISerializable {
void GetObjectData(SerializationInfo info, StreamingContext context);
}

GetObjectData .
,
.

ISerializable , , GetObjectData
. , ,
. ,
ISerializable . ,
, ,
.

ISerializable
. GetObjectData
.
, . GetObjectData
:
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter =
true)]

.
ISerializable,
System.
Runtime.Serialization.SerializationInfo,
.

680

24.

SerializationInfo : Type System.Runtime.Serialization.IFormatterConverter.


. : ( , ,
). SerializationInfo
( FullName), . FullTypeName SerializationInfo.
( Module Type, Assembly
Module , , FullName Assembly),
.
AssemblyName SerializationInfo.

FullTypeName AssemblyName SerializationInfo


.
SetType SerializationInfo Type.
.
.

SerializationInfo GetObjectData .
GetObjectData ,
, SerializationInfo.

AddValue SerializationInfo.
, ,
AddValue.
, Dictionary<TKey,
TValue> ISerializable IDeserializationCallback, :
[Serializable]
public class Dictionary<TKey, TValue>: ISerializable,
IDeserializationCallback {
// ( )
private SerializationInfo m_siInfo; //
// ( ISerializable)
//
[SecurityPermissionAttribute(
SecurityAction.Demand, SerializationFormatter = true)]
protected Dictionary(SerializationInfo info, StreamingContext context) {

681

//
// SerializationInfo OnDeserialization
m_siInfo = info;
}
//
[SecurityCritical]
public virtual void GetObjectData(
SerializationInfo info, StreamingContext context) {
info.AddValue("Version", m_version);
info.AddValue("Comparer", m_comparer, typeof(IEqualityComparer<TKey>));
info.AddValue("HashSize", (m_ buckets == null) ? 0 : m_buckets.Length);
if (m_buckets != null) {
KeyValuePair<TKey, TValue>[] array =
new KeyValuePair<TKey, TValue>[Count];
CopyTo(array, 0);
info.AddValue(
"KeyValuePairs", array, typeof(KeyValuePair<TKey, TValue>[]));
}
}
// , /
public virtual void IDeserializationCallback.OnDeserialization(
Object sender) {
if (m_siInfo == null) return; // ,
//
Int32 num = m_siInfo.GetInt32("Version");
Int32 num2 = m_siInfo.GetInt32("HashSize");
m_comparer = (IEqualityComparer<TKey>)
m_siInfo.GetValue("Comparer", typeof(IEqualityComparer<TKey>));
if (num2 != 0) {
m_buckets = new Int32[num2];
for (Int32 i = 0; i < m_buckets.Length; i++) m_buckets[i] = -1;
m_entries = new Entry<TKey, TValue>[num2];
m_freeList = -1;
KeyValuePair<TKey, TValue>[] pairArray = (
KeyValuePair<TKey, TValue>[]) m_siInfo.GetValue(
"KeyValuePairs", typeof(KeyValuePair<TKey, TValue>[]));
if (pairArray == null)
ThrowHelper.ThrowSerializationException(
ExceptionResource.Serialization_MissingKeys);
for (Int32 j = 0; j < pairArray.Length; j++) {
if (pairArray[j].Key == null)
ThrowHelper.ThrowSerializationException(
ExceptionResource.Serialization_NullKey);
Insert(pairArray[j].Key, pairArray[j].Value, true);
}
} else { m_buckets = null; }

682

24.
m_version = num;
m_siInfo = null;

AddValue String . ,
Boolean, Char, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single,
Double, Decimal DateTime. , AddValue
Object, , String. GetObjectData
,
.


AddValue. ,
ISerializable, GetObjectData. , AddValue; ,
ISerializable, GetObjectData.
, -
, .

SerializationInfo -.
, GetObjectData :
System.Runtime.Serialization.StreamingContext. GetObjectData ,

, .
, , . .
-,
( GetUninitializedObject System.Runtime.
Serialize.FormatterServices).
0 null. ,
ISerializable.
, GetObjectData.
, sealed, private.
. protected, .
, ,
.
SerializationInfo,
, .

683

GetBoolean, GetChar, GetByte, GetSByte, GetInt16, GetUInt16, GetInt32, GetUInt32,


GetInt64, GetUInt64, GetSingle, GetDouble, GetDecimal, GetDateTime, GetString
GetValue, , -

. , ,
.
Get
, AddValue .
, GetObjectData AddValue
Int32, GetInt32 .
- , ,
IFormatterConvert
-.
SerializationInfo ,
IFormatterConverter. , IFormatterConverter.
BinaryFormatter SoapFormatter Microsoft System.Runtime.Serialization.FormatterConverter.
IFormatterConverter .
FormatterConverter System.
Convert , Int32
Int64.
FormatterConverter ChangeType Convert
( ) IConvertible. . ,
, ,
IConvertible. ,
FormatterConverter
Get,
-.
Get
GetEnumerator, System.Runtime.
Serialization.SerializationInfoEnumerator ,
SerializationInfo. System.Runtime.Serialization.
SerializationEntry.
, ,
, GetObjectData ISerializable, . ISerializable,

GetObjectData
. , ISerializable,
.

684

24.

, ,
,
ISerializable . GetObjectData, , .
, . ,
.
,
, .


SerializationInfo.
, , .
(,
), OnDeserialized
OnDeserialization IDeserializationCallback ( Dictionary). .
OnDeserialized OnDeserialization
. , , ,
, OnDeserialized
IDeserializationCallback, .

,
ISerializable,
, ISerializable ,
.
.
ISerializable,
GetObjectData .
, ,
, ISerializable.
,
SerializationInfo.
.
public protected, , .
, GetObjectData
ISerializable ,
:

685

[Serializable]
internal class Base {
protected String m_name = "Jeff";
public Base() { /* */ }
}
[Serializable]
internal class Derived : Base, ISerializable {
private DateTime m_date = DateTime.Now;
public Derived() { /* */ }
// , SerializationException.
// , .
[SecurityPermissionAttribute(
SecurityAction.Demand, SerializationFormatter = true)]
private Derived(SerializationInfo info, StreamingContext context) {
//
Type baseType = this.GetType().BaseType;
MemberInfo[] mi = FormatterServices.GetSerializableMembers(
baseType, context);
//
for (Int32 i = 0; i < mi.Length; i++) {
//
FieldInfo fi = (FieldInfo)mi[i];
fi.SetValue(this, info.GetValue(
baseType.FullName + "+" + fi.Name, fi.FieldType));
}
// ,
m_date = info.GetDateTime("Date");
}
[SecurityPermissionAttribute(
SecurityAction.Demand, SerializationFormatter = true)]
public virtual void GetObjectData(
SerializationInfo info, StreamingContext context) {
//
info.AddValue("Date", m_date);
//
Type baseType = this.GetType().BaseType;
MemberInfo[] mi = FormatterServices.GetSerializableMembers(
baseType, context);
//
for (Int32 i = 0; i < mi.Length; i++) {
//
info.AddValue(baseType.FullName + "+" + mi[i].Name,
((FieldInfo)mi[i]).GetValue(this));
}
}

686

24.

public override String ToString() {


return String.Format("Name={0}, Date={1}", m_name, m_date);
}
}

Base , SerializableAttribute .
Derived,
ISerializable. ,
String m_name. AddValue SerializationInfo
.
.
, GetObjectData AddValue
m_name Base, "Base+m_name".

-
, :
, ,
.. , , , . , ,
Windows-, ,
.
,
. ,
, ,
.
StreamingContext. ,
, (.24.1).
24.1. StreamingContext

State

StreamingContextStates

,
/

Context

Object

687

StreamingContext
State / . .24.2.
24.2. StreamingContextStates

CrossProcess

0x0001

CrossMachines

0x0002

File

0x0004

.
,

Persistence

0x0008


, .
,

Remoting

0x0010

.
,

Other

0x0020

Clone

0x0040

. ,
, ,

CrossAppDomain

0x0080

All

0x00FF

, , , ,
. IFormatter ( BinaryFormatter,
SoapFormatter)
StreamingContext Context. Context, StreamingContextStates
All, null.

688

24.

Streaming
Context, StreamingContextStates, -

,
. Context
StreamingContext Serialize Deserialize.
DeepClone , ,
/
.



.NET Framework
. , , .
, :
(, System.DBNull System.Reflection.Missing)
.
(singleton).
DBNull,
.
DBNull.
(, System.Type, System.Reflection.Assembly
, MemberInfo)
, , ..
MemberInfo. ,
. . , MemberInfo,
.

.
, , CLR , CLR
, (proxy) .
,
. - , ,
.

:

689

//
[Serializable]
public sealed class Singleton : ISerializable {
//
private static readonly Singleton theOneObject = new Singleton();
//
public String Name = "Jeff";
public DateTime Date = DateTime.Now;
//
private Singleton() { }
// ,
public static Singleton GetSingleton() { return theOneObject; }
// , Singleton
// .
[SecurityPermissionAttribute(
SecurityAction.Demand, SerializationFormatter = true)]
void ISerializable.GetObjectData(
SerializationInfo info, StreamingContext context) {
info.SetType(typeof(SingletonSerializationHelper));
//
}
[Serializable]
private sealed class SingletonSerializationHelper : IObjectReference {
// , ( )
public Object GetRealObject(StreamingContext context) {
return Singleton.GetSingleton();
}
}
// . ,
//
}

Singleton ,
. ,
:
private static void SingletonSerializationTest() {
// Singleton
Singleton[] a1 = { Singleton.GetSingleton(), Singleton.GetSingleton() };
Console.WriteLine("Do both elements refer to the same object? "
+ (a1[0] == a1[1])); // "True"
using (var stream = new MemoryStream()) {
BinaryFormatter formatter = new BinaryFormatter();
//

690

24.

formatter.Serialize(stream, a1);
stream.Position = 0;
Singleton[] a2 = (Singleton[])formatter.Deserialize(stream);
// , , :
Console.WriteLine("Do both elements refer to the same object? "
+ (a2[0] == a2[1])); // "True"
Console.WriteLine("Do all elements refer to the same object? "
+ (a1[0] == a2[0])); // "True"
}
}

, .

Singleton CLR , Singleton


s_theOneObject. Singleton

, .
SingletonSerializationTest ,
Singleton. GetSingleton Singleton. Singleton. WriteLine
"True", , .
SingletonSerializationTest Serialize . ,
Singleton ISerializable , GetObjectData, SetType
SingletonSerializationHelper.
Singleton SingletonSerializationHelper.
AddValue , -
. , , , ,
.
SingletonSerializationTest
Deserialize . -
SingletonSerializationHelper,
( ,
Singleton , ISerializable ).
SingletonSerializationHelper, , System.Runtime.Serialization.IObjectReference.
FCL :
public interface IObjectReference {
Object GetRealObject(StreamingContext context);
}

691


GetRealObject, , .
SingletonSerializationHelper GetRealObject
Singleton.
Deserialize a2 ,
Singleton . SingletonSerializationHelper,
,
.
WriteLine "True", ,
a2 .
,
.


, . ,
. ?
,
.
.
, ,
.
,
, .
,
. , .
System.Runtime.
Serialization.ISerializationSurrogate, FCL :
public interface ISerializationSurrogate {
void GetObjectData(Object obj, SerializationInfo info,
StreamingContext context);
Object SetObjectData(Object obj, SerializationInfo info,
StreamingContext context, ISurrogateSelector selector);
}

692

24.

. ,
DateTime,
. -,
, ? , ,
.
DateTime, FCL,
, DateTime.
:
internal sealed class UniversalToLocalTimeSerializationSurrogate :
ISerializationSurrogate {
public void GetObjectData(
Object obj, SerializationInfo info, StreamingContext context) {
//
info.AddValue("Date", ((DateTime)obj).ToUniversalTime().ToString("u"));
}
public Object SetObjectData(Object obj, SerializationInfo info,
StreamingContext context, ISurrogateSelector selector) {
//
return DateTime.ParseExact(
info.GetString("Date"), "u", null).ToLocalTime();
}
}

GetObjectData
ISerializable. : , . GetObjectData
DateTime, -

, (
/)
SerializationInfo.
DateTime SetObjectData.
SerializationInfo.
,
/ DateTime
.
SetObjectData, Object, .
( GetUninitializedObject FormatterServices)
, .
0 null, .
SetObjectData ,
SerializationInfo, null.
SetObjectData

693

.
,
, SetObjectData.
UniversalToLocalTimeSerializationSurrogate
DateTime. obj
DateTime.
( ),
SetObjectData obj DateTime
.
/ DateTime ISerializationSurrogate? UniversalToLocalTimeSerializationSurrogate:
private static void SerializationSurrogateDemo() {
using (var stream = new MemoryStream()) {
// 1.
IFormatter formatter = new SoapFormatter();
// 2. SurrogateSelector
SurrogateSelector ss = new SurrogateSelector();
// 3. DateTime
ss.AddSurrogate(typeof(DateTime), formatter.Context,
new UniversalToLocalTimeSerializationSurrogate());
// . AddSurrogate
//
// 4.
formatter.SurrogateSelector = ss;
// DateTime
//
DateTime localTimeBeforeSerialize = DateTime.Now;
formatter.Serialize(stream, localTimeBeforeSerialize);
// ,
// ,
stream.Position = 0;
Console.WriteLine(new StreamReader(stream).ReadToEnd());
//
// DateTime
stream.Position = 0;
DateTime localTimeAfterDeserialize =
(DateTime)formatter.Deserialize(stream);
//
Console.WriteLine(
"LocalTimeBeforeSerialize ={0}", localTimeBeforeSerialize);

694

24.

Console.WriteLine(
"LocalTimeAfterDeserialize={0}", localTimeAfterDeserialize);
}
}


. Serialize
, SurrogateSelector. GetObjectData ISerializationSurrogate,
-.
Deserialize
SurrogateSelector, SetObjectData ISerializationSurrogate,
.
SurrogateSelector -. AddSurrogate Type StreamingContext ,
ISerializationSurrogate .
Type/StreamingContext ,
AddSurrogate ArgumentException.
StreamingContext
: DateTime, /
DateTime .

BinaryFormatter , -
.
ISerializationSurrogate GetSurrog
ateForCyclicalReference FormatterServices.
ISerializationSurrogate, AddSurrogate
SurrogateSelector. GetSurrogateForCyclicalReference
SetObjectData ,
obj,
null obj. ( ) , UniversalToLocalTimeSeriali
zationSurrogate SerializationSurrogateDemo,
.


SurrogateSelector . ,
SurrogateSelector ,
. SurrogateSelector ,
1 2.

695

, . SurrogateSelector ISurrogateSelector,
. .
ISurrogateSelector:
public interface ISurrogateSelector {
void ChainSelector(ISurrogateSelector selector);
ISurrogateSelector GetNextSelector();
ISerializationSurrogate GetSurrogate(
Type type, StreamingContext context, out ISurrogateSelector selector);
}

ChainSelector ISurrogateSelector ISurrogateSelector, (


this). GetNextSelector
ISurrogateSelector , null, .
GetSurrogate Type/StreamingContext ISurrogate
Selector, this. ,
ISurrogateSelector .. GetSurrogate ISerializationSurrogate,
/ . ,
ISurrogateSelector;
, .
ISurrogateSelector Type/
StreamingContext, GetSurrogate null.

FCL ISurrogateSelector Surroga


teSelector. ,
.
,
, .
System.Runtime.Remoting.Messaging.RemotingSurrogateSelector.
, CLR
RemotingSurrogateSelector.
System.MarshalByRefObject ,
- .

/


.

696

24.

. ISerializationSurrogate ,
. , ISerializationSurrogate,
.
,
. , :
. ,
, .
, .

, ,
.
.

System.Runtime.Serialization.SerializationBinder.
, SerializationBinder.
, 1.0.0.0 Ver1.
Ver1ToVer2SerializationBinder
Ver2:
internal sealed class Ver1ToVer2SerializationBinder : SerializationBinder {
public override Type BindToType(String assemblyName, String typeName) {
// Ver1 1.0.0.0 Ver2
// , Ver1
AssemblyName assemVer1 = Assembly.GetExecutingAssembly().GetName();
assemVer1.Version = new Version(1, 0, 0, 0);
// Ver1 v1.0.0.0 Ver2
if (assemblyName == assemVer1.ToString() && typeName == "Ver1")
return typeof(Ver2);
//
return Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));
}
}

Ver1
ToVer2SerializationBinder
Binder . Deserialize.


BindToType,

697

, . BindToType
, , .

SerializationBinder / BindToName.
:
public virtual void BindToName(Type serializedType,
out string assemblyName, out string typeName)

, , .
( out) , .
null null (
), .

25.
WinRT

Windows 8 , . Windows Runtime (WinRT),


WinRT. ,
WinRT, CLR
, , .
Microsoft WinRT
C/C++, JavaScript ( JavaScript
Chakra Microsoft), C# Visual Basic.
.25.1 , WinRT, , Microsoft .
, C/C++,
(x86, x64 ARM).
Microsoft .NET Framework IL-,
CLR .
JavaScript ,
Chakra . ,
WinRT.
Windows Store
WinRT .
WinRT, Windows,
.NET
Framework. , , ,
:
. ,
WinRT , ,
, , , , . .
(, ) (, LiNQ) ,
, WinRT
.

WinRT

DirectX XAML
C/C++

CRT

HTML & CSS

XAML
C#/VB

699

FCL

JS

WinJS
Chakra

CLR

Windows 8
WinRT

XAML

. 25.1. WinRT ,.
Microsoft

WinRT COM (Component Object Model) ,


Microsoft 1993 . COM .
COM ,
Microsoft .
WinRT Microsoft :
API COM
. , APO WinRT .NET
(ECMA-335), ECMA
, .
,
, CLR. , CLR
COM RCW (Runtime
Callable Wrappers) CCW (COM Callable Wrappers). (, C#), CLR,
WinRT.
C# WinRT
RCW, WinRT. CLR WinRT API
CCW, CCW CLR.
WinRT .winmd.
WinRT, Windows, -

700

25. WinRT

Windows.*.winmd, %WinDir%\System32\WinMetadata.
Windows.winmd,
Windows SDK:
%ProgramFiles(x86)%\Windows Kits\8.0\References\CommonConiguration\Neutral\Windows.
winmd

Windows Runtime , , ,

, , .
WinRT . .NET Framework :
CLR CLR ( , ).
WinRT , CLR
.NET Framework.
.NET Framework API, FCL. .NET
Framework ,
WinRT CLR
CLR. .NET Framework .

CLR
WinRT
WinRT , CLR.
CLR WinRT,
CLR.
CLR WinRT .
CLR ( ),
FCL. WinRT, CLR
FCL, http://msdn.microsoft.com/
en-us/library/windows/apps/hh995050.aspx.

WinRT
WinRT CLR.
WinRT CLR.
. .winmd , WinRT. -

CLR WinRT

701

, Wintellect.WindowsStore.winmd
WinRT, Wintellect.WindowsStore
. Windows , , ,
. , WinRT
.
. WinRT .
CLR WinRT, , WinRT
System.Object; WinRT
, ToString, GetHashCode, Equals GetType.
WinRT C# System.Object,
WinRT . , ToString.
. WinRT
: , , 16-, 32 64-
, , 16-
, void1. , CLR,
.
. WinRT -; , WinRT ,
2. (, JavaScript)
, WinRT , , .

WinRT, , JavaScript.
WinRT, Windows, XAML ( ).
, JavaScript,
HTML CSS.
. WinRT ( ),
(interoperability
boundary) COM. CLR, WinRT
,
( WinRT)3. , WinRT
. CLR
WinRT
CLR, .
WinRT .
, WinRT
.
3
, 32-
.
1
2

702

25. WinRT

CLR.
Point, Rect, Size TimeSpan,
Windows.Foundation.
Null- . WinRT API
null- ( ). CLR WinRT
Windows.Foundation.IReference<T> CLR System.Nullable<T>.
.
32- . C#, int uint. , 32- ,
.
.
WinRT WinRT- .
. WinRT . ,
JavaScript , , . , JavaScript
, .
JavaScript .
, WinRT
.
. WinRT
WinRT- . WinRT
, .
. WinRT
WinRT- .
WinRT CCW
, CCW WinRT. WinRT BeginInvoke
EndInvoke.
. WinRT ,
WinRT. WinRT (
), WinRT TypedEventHandler, sender ( System.Object).
public delegate void TypedEventHandler<TSender, TResult>(TSender sender,
TResult args);

Windows.Foundation.EventHandler<T>, CLR .NET Framework System.


EventHandler<T>.
. WinRT,
COM, HRESULT (32- ). CLR WinRT
Windows.Foundation.HResult . WinRT API

CLR WinRT

703

HRESULT, , CLR , Exception. , HRESULT


0x8007000e (E_OUTOFMEMORY) System.OutOfMemoryException.
HRESULT CLR System.Exception,
HResult HRESULT. WinRT, C#,
, CLR HRESULT. HRESULT,
, HRESULT
HResult , .
. ,
WinRT CLR. WinRT null. null WinRT
API, CLR ArgumentNullException;
null WinRT API String.Empty. ;
WinRT API .
CLR (String[]) WinRT API , .
. WinRT Windows.Foundation.DateTime / UTC. CLR WinRT DateTime
.NET Framework System.DateTimeOffset, .NET Framework System.DateTime.
DateTimeOffset CLR UTC, WinRT, . CLR WinRT API DateTimeOffet
UTC.
URI. CLR WinRT Windows.Foundation.Uri .NET
Framework System.Uri. .NET Framework Uri
WinRT API URI-, CLR
ArgumentException; WinRT URI.
URI.
IClosable/IDisposable CLR WinRT Windows.Foundation.
IClosable ( Close ) .NET
Framework System.IDisposable ( Dispose). ,
WinRT API, -,
. IClosable Close, CloseAsync,
Close -. Dispose .NET Framework.
, .NET Framework, Dispose
-; ,
. C# Dispose
WinRT, - ( , )
, .
,

704

25. WinRT

, WinRT, . ,
DataWriter StoreAsync.
. WinRT API . WinRT ,
.
WinRT API, ,
API1. ,
, . ,
.
.
. WinRT API CLR CCW CCW WinRT API.
CCW ,
. ,
, WinRT API
. .25.1
WinRT .NET.
25.1. WinRT CLR
WinRT (
(Windows.Foundation.
Collections)

CLR
( System.Collections.
Generic)

IIterable<T>

IEnumerable<T>

IVector<T>

IList<T>

IVectorView<T>

IReadOnlyList<T>

IMap<K, V>

IDictionary<TKey, TValue>

IMapView<K, V>

IReadOnlyDictionary<TKey, TValue>

IKeyValuePair<K, V>

KeyValuePair<TKey, TValue>

, CLR
,

, , API , Sort
System.Array. , (C, C++, C#, Visual Basic JavaScript)
, WinRT .
1

.NET Framework

705

WinRT CLR, WinRT 1.

.NET Framework
CLR WinRT .NET
Framework, . ,
: ,
WinRT .NET Framework,
CLR WinRT API.
.

WinRT API .NET


-
. /,

( , ),
. , WinRT,
-, . ,
WinRT, ,
, 50 . , ,
V .
WinRT
API, , C#.
:
public void WinRTAsyncIntro() {
IAsyncOperation<StorageFile> asyncOp =
KnownFolders.MusicLibrary.GetFileAsync("Song.mp3");
asyncOp.Completed = OpCompleted;
// , asyncOp.Cancel()
}
// :
// :

, http://
msdn.microsoft.com/en-us/library/windows/apps/hh995050.aspx
CLRandtheWindowsRuntime.docx.
1

706

25. WinRT

private void OpCompleted(IAsyncOperation<StorageFile> asyncOp, AsyncStatus status)


{
switch (status) {
case AsyncStatus.Completed: //
StorageFile file = asyncOp.GetResults(); /* ... */ break;
case AsyncStatus.Canceled: //
/* Canceled... */ break;
case AsyncStatus.Error: //
Exception exception = asyncOp.ErrorCode; /* ... */ break;
}
asyncOp.Close();
}

WinRTAsyncIntro WinRT GetFileAsync


. WinRT API,
, Async , WinRT IAsyncXxx; IAsyncOperation<TResult>,
TResult WinRT StorageFile. ,
asyncOp, .
- .
(OpCompleted
), Completed
asyncOp. - ( ).
OnCompleted,
. ,
, , IAsyncXxx,
, .
WinRTAsyncIntro,
Cancel, IAsyncXxx.
: , .
,
XxxAsync, AsyncStatus. OnCompleted status
, ,
1. ,
IAsyncXxx Close.
IAsyncInfo Status, , status . ,
( Status) , WinRT API
RCW.
1

.NET Framework

707

.25.2 WinRT IAsyncXxx. IAsyncInfo.


IAsyncAction ,
( GetResults void). IAsyncOperation , ( GetResults
TResult).
IAsyncXxxWithProgress .
, (, , )
.
, Progress
IAsyncXxxWithProgress. , TProgress.

IAsyncInfo
Id (UInt32)
Status (AsyncStatus)
ErrorCode (Exception)
Cancel()
Close()
AsyncStatus
Started
Completed, Canceled, Error

IAsyncAction
Completed (delegate)
GetResults
(void)
IAsyncActionWithProgress<TProgress>
Completed (delegate)
GetResults
(void)
Progress
(delegate)
IAsyncOperation<TResult>
Completed (delegate)
GetResults
(TResult)
IAsyncOperationWithProgress<TResult, TProgress>
Completed (delegate)
GetResults
(TResult)
Progress
(delegate)

. 25.2. WinRT, .
-

.NET Framework
System.Threading.Tasks. 27,
- 28. , C#
async await, ,
.

WinRTAsyncIntro.

708

25. WinRT

.NET Framework, WinRT C#.


using System; //
// WindowsRuntimeSystemExtensions
...
public async void WinRTAsyncIntro() {
try {
StorageFile file = await KnownFolders.MusicLibrary.GetFileAsync("Song.mp3");
/* ... */
}
catch (OperationCanceledException) { /* ... */ }
catch (SomeOtherException ex) { /* ... */ }
}

C# await GetAwaiter
IAsyncOperation<StorageFile>, GetFileAsync.
GetAwaiter,
. , .NET Framework
System.Runtime.WindowsRuntime.dll , WinRT IAsyncXxx.
namespace System {
public static class WindowsRuntimeSystemExtensions {
public static TaskAwaiter GetAwaiter(this IAsyncAction source);
public static TaskAwaiter GetAwaiter<TProgress>(this
IAsyncActionWithProgress<TProgress> source);
public static TaskAwaiter<TResult> GetAwaiter<TResult>(this
IAsyncOperation<TResult> source);
public static TaskAwaiter<TResult> GetAwaiter<TResult, TProgress>(
this IAsyncOperationWithProgress<TResult, TProgress> source);
}
}

TaskCompletionSource
IAsyncXxx ,
TaskCompletionSource
. TaskAwaiter, ,
C#.
TaskAwaiter ,
SynchronizationContext (. 28), .
, C#, Result TaskCompletionSource.Task;
(StorageFile ),
OperationCanceledException
. .

WinRT API . ,
, , .

.NET Framework

709

. ,
GetAwaiter
AsTask,
WindowsRuntimeSystemExtensions.
namespace System {
public static class WindowsRuntimeSystemExtensions {
public static Task AsTask<TProgress>(this
IAsyncActionWithProgress<TProgress> source,
CancellationToken cancellationToken, IProgress<TProgress> progress);
public static Task<TResult> AsTask<TResult, TProgress>(
this IAsyncOperationWithProgress<TResult, TProgress> source,
CancellationToken cancellationToken, IProgress<TProgress> progress);
//
}
}

, .
WinRT API
, :
using System; // AsTask WindowsRuntimeSystemExtensions
using System.Threading; // CancellationTokenSource
internal sealed class MyClass {
private CancellationTokenSource m_cts = new CancellationTokenSource();
// :
// :
private async void MappingWinRTAsyncToDotNet(WinRTType someWinRTObj) {
try {
// , XxxAsync
// IAsyncOperationWithProgress<IBuffer, UInt32>
IBuffer result = await someWinRTObj.XxxAsync(...)
.AsTask(m_cts.Token, new Progress<UInt32>(ProgressReport));
/* ... */
}
catch (OperationCanceledException) { /* ... */ }
catch (SomeOtherException) { /* ... */ }
}
private void ProgressReport(UInt32 progress) { /* ... */ }
public void Cancel() { m_cts.Cancel(); } //
}

, , AsTask
WinRT IAsyncXxx .NET Framework Task,
await.

710

25. WinRT

AsTask. ,
.
public static Task<TResult> AsTask<TResult, TProgress>(
this IAsyncOperationWithProgress<TResult, TProgress> asyncOp,
CancellationToken ct = default(CancellationToken),
IProgress<TProgress> progress = null) {
// CancellationTokenSource
ct.Register(() => asyncOp.Cancel());
// ,
//
asyncOp.Progress = (asyncInfo, p) => progress.Report(p);
// TaskCompletionSource
//
var tcs = new TaskCompletionSource<TResult>();
// TaskCompletionSource.
// , ,
// TaskCompletionSource.
asyncOp.Completed = (asyncOp2, asyncStatus) => {
switch (asyncStatus) {
case AsyncStatus.Completed: tcs.SetResult(asyncOp2.GetResults()); break;
case AsyncStatus.Canceled: tcs.SetCanceled(); break;
case AsyncStatus.Error: tcs.SetException(asyncOp2.ErrorCode); break;
}
};
}

return tcs.Task;

WinRT .NET
.NET Framework , System.
IO.Stream , , LINQ. WinRT, WinRT IStorageFile IStorageFolder,
.NET Framework, , Stream,
, System.IO.Wi
ndowsRuntimeStorageExtensions.
namespace System.IO { // System.Runtime.WindowsRuntime.dll
public static class WindowsRuntimeStorageExtensions {
public static Task<Stream> OpenStreamForReadAsync(this IStorageFile file);
public static Task<Stream> OpenStreamForWriteAsync(this IStorageFile file);
public static Task<Stream> OpenStreamForReadAsync(this
IStorageFolder rootDirectory,
String relativePath);
public static Task<Stream> OpenStreamForWriteAsync(this

.NET Framework

711

IStorageFolder rootDirectory,
String relativePath, CreationCollisionOption creationCollisionOption);
}
}


WinRT StorageFile .NET Framework
XElement.
async Task<XElement> FromStorageFileToXElement(StorageFile file) {
using (Stream stream = await file.OpenStreamForReadAsync()) {
return XElement.Load(stream);
}
}

, System.IO.WindowsRuntimeStreamExtensions
, WinRT (,
IRandomAccessStream, IInputStream IOutputStream) .NET Framework
Stream, .
namespace System.IO { // System.Runtime.WindowsRuntime.dll
public static class WindowsRuntimeStreamExtensions {
public static Stream AsStream(this IRandomAccessStream winRTStream);
public static Stream AsStream(this IRandomAccessStream winRTStream,
Int32 bufferSize);
public static Stream AsStreamForRead(this IInputStream winRTStream);
public static Stream AsStreamForRead(this IInputStream winRTStream,
Int32 bufferSize);
public static Stream AsStreamForWrite(this IOutputStream winRTStream);
public static Stream AsStreamForWrite(this IOutputStream winRTStream,
Int32 bufferSize);

public static IInputStream AsInputStream (this Stream clrStream);


public static IOutputStream AsOutputStream(this Stream clrStream);

WinRT IInputStream .NET Framework Stream.


XElement FromWinRTStreamToXElement(IInputStream winRTStream) {
Stream netStream = winRTStream.AsStreamForRead();
return XElement.Load(netStream);
}

: , .NET
Framework, . , WinRT .NET Framework,
WinRT .
,
- (,
XML).

712

25. WinRT

.NET Framework , AsStreamXxx


WinRT, , ,
, . .NET Framework API ,
,
.

,
16- , .
AsStreamXxx . , ,
, ,
, . ,
, ,
; .
AsStreamXxx , .

CLR WinRT
, , ,
. CLR
WinRT . ,
WinRT
. ,
WinRT , .
.NET Framework
(Byte[]) (, MemoryStream).
, MemoryStream WinRT , WinRT IBuffer; ,
, ,
WinRT API. WinRT IBuffer :
namespace Windows.Storage.Streams {
public interface IBuffer {
UInt32 Capacity { get; } // ( )
UInt32 Length { get; set; } //
} //
}

.NET Framework

713

, IBuffer ;
,
. , , , WinRT
, (, JavaScript C#).
, IBuffer CLR
WinRT API. COM IBufferByteAccess. :
COM ( ), WinRT. .NET
Framework COM RCW,
:
namespaceSystem.Runtime.InteropServices.WindowsRuntime {
[Guid("905a0fefbc5311df8c49001e4fc686da")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
internalinterfaceIBufferByteAccess {
unsafeByte*Buffer { get; }
}
}

CLR IBuffer, IBufferByteAccess, Buffer


, .
.
,
, FCL WindowsRuntimeBufferExtensions.
, CLR
WinRT IBuffer.
using System.Runtime.InteropServices.
WindowsRuntime;:
namespaceSystem.Runtime.InteropServices.WindowsRuntime {
public static class WindowsRuntimeBufferExtensions {
public static IBuffer AsBuffer(this Byte[] source);
public static IBuffer AsBuffer(this Byte[] source, Int32 offset,
Int32 length);
public static IBuffer AsBuffer(this Byte[] source, Int32 offset,
Int32 length, Int32 capacity);
public static IBuffer GetWindowsRuntimeBuffer(this MemoryStream stream);
public static IBuffer GetWindowsRuntimeBuffer(this MemoryStream stream,
Int32 position, Int32 length);
}
}

, Byte[]
WinRT, IBuffer , AsBuffer Byte[] .

714

25. WinRT

, Byte[] ,
IBuffer; Byte[] ,
. ,
MemoryStream, Byte[],
GetWindowsRuntimeBuffer, MemoryStream , IBuffer.
, .
:
private async Task ByteArrayAndStreamToIBuffer(IRandomAccessStream winRTStream,
Int32 count) {
Byte[] bytes = new Byte[count];
await winRTStream.ReadAsync(bytes.AsBuffer(), (UInt32)bytes.Length,
InputStreamOptions.None);
Int32 sum = bytes.Sum(b => b); //
// Byte[]
using (var ms = new MemoryStream())
using (var sw = new StreamWriter(ms)) {
sw.Write("This string represents data in a stream");
sw.Flush();
UInt32 bytesWritten = await
winRTStream.WriteAsync(ms.GetWindowsRuntimeBuffer());
}
}

WinRT IRandomAccessStream WinRT IInput


Stream, :
namespace Windows.Storage.Streams {
public interface IOutputStream : IDisposable {
IAsyncOperationWithProgress<UInt32, UInt32> WriteAsync(IBuffer buffer);
}
}

AsBuffer GetWindowsRuntimeBuffer
, ,
IBuffer. CLR CCW
WinRT API. WinRT API Buffer IBufferByteAccess
, , WinRT API
. , WinRT API COM
Release IBufferByteAccess.
WinRT API, IBuffer, , , , . ,
WindowsRuntimeBufferExtensions.
namespaceSystem.Runtime.InteropServices.WindowsRuntime {
public static class WindowsRuntimeBufferExtensions {

WinRT C#

715

public static Stream AsStream(this IBuffer source);


public static Byte[] ToArray(this IBuffer source);
public static Byte[] ToArray(this IBuffer source, UInt32 sourceIndex,
Int32 count);
// : CopyTo IBuffer Byte[]
// : GetByte, IsSameData
}
}

AsStream , Stream, IBuffer.


IBuffer, Read, Write Stream.
ToArray Byte[],
IBuffer Byte[]; ,
.
WindowsRuntimeBufferExtensions CopyTo, IBuffer
Byte[]; GetByte, IBuffer ;
IsSameData, IBuffer.
.
, .NET Framework System.
Runtime.InteropServices.WindowsRuntimeBuffer IBuffer,
.
WinRT Windows.Storage.Streams.Buffer IBuffer,
. ,
.NET Framework .

WinRT C#

WinRT C#. WinRT C#
C/C++, C#/Visual Basic, JavaScript
. , ,
. , WinRT C#,
,
CLR. , WinRT
,
CLR.
, C#
WinRT, C/C++. , , C/C++,
/ .

716

25. WinRT

WinRT,
, CLR , ,
-
JIT- . WinRT (
, Windows) .
, C++ ,
,
.NET Framework . , Bing Maps C++
DirectX, - C#.
, , WinRT, C#,
Windows Store, HTML CSS, JavaScript
-, WinRT.

FCL HTML/JavaScript.
, HTML JavaScript,
,
. , - CLR .
WinRT C# Microsoft Visual
Studio Windows Runtime Component.
, C#
/t:winmdobj .winmdobj.
IL- ,
. , WinRT , CLR,
add remove . ,
add remove .
.winmdobj, WinMD
(WinMDExp.exe), .winmdobj,
.pdb .xml (doc). WinMDExp.exe , WinRT (.
). , .winmdobj; IL-
. , CLR WinRT. , .NET Framework
IList<String> WinRT IVector<String>.
WinMDExp.exe .winmd, .
.winmd ILDasm.exe. ILDasm.exe , -

WinRT C#

717

/project ,
WinRT .NET Framework.

WinRT C#. , , .
WinRT C#, .

WinRT, , CLR WinRT ,


CLR CCW RCW, ,
WinRT API.
. API , (, C/C++
JavaScript). , , null WinRT API,
String ArgumentNullException. ,
WinRT API, , ,
; WinRT ,
API. ,
.
/******************************************************************************
: WinRTComponents.cs
: Copyright (c) 2012 by Jeffrey Richter
******************************************************************************/
using
using
using
using
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Runtime.InteropServices.WindowsRuntime;
System.Threading;
System.Threading.Tasks;
Windows.Foundation;
Windows.Foundation.Metadata;

//
// "Windows"
namespace Wintellect.WinRTComponents {
// [Flags] // int; uint
public enum WinRTEnum : int { //
None, // int uint
NotNone
}
// ,

718

25. WinRT

// String .
// .
public struct WinRTStruct {
public Int32 ANumber;
public String AString;
public WinRTEnum AEnum; //
} // 32-
// WinRT-
// ( BeginInvoke/EndInvoke)
public delegate String WinRTDelegate(Int32 x);
// , ,
// .
public interface IWinRTInterface {
// Nullable<T> IReference<T>
Int32? InterfaceProperty { get; set; }
}
// [Version(#)]
// (1) COM,
// WinMDExp.exe.
[Version(1)]
// Object, ,
// , WinRT,
// WinRT
public sealed class WinRTClass : IWinRTInterface {
//
#region ,
public static String StaticMethod(String s) { return "Returning " + s; }
public static WinRTStruct StaticProperty { get; set; }
// JavaScript 'out' ;
//
public static String OutParameters(out WinRTStruct x, out Int32 year) {
x = new WinRTStruct { AEnum = WinRTEnum.NotNone, ANumber = 333,
AString = "Jeff" };
year = DateTimeOffset.Now.Year;
return "Grant";
}
#endregion
// , out/ref
public WinRTClass(Int32? number) { InterfaceProperty = number; }
public Int32? InterfaceProperty { get; set; }
// ToString
public override String ToString() {
return String.Format("InterfaceProperty={0}",
InterfaceProperty.HasValue ? InterfaceProperty.Value.ToString() :

WinRT C#

719

"(not set)");

public void ThrowingMethod() {


throw new InvalidOperationException("My exception message");
// HRESULT,
// COMException
//const Int32 COR_E_INVALIDOPERATION = unchecked((Int32)0x80131509);
//throw new COMException("Invalid Operation", COR_E_INVALIDOPERATION);
}
#region , ;
public Int32 PassArray([ReadOnlyArray] /* [In] */
Int32[] data) {
return data.Sum();
}
public Int32 FillArray([WriteOnlyArray] /* [Out] */
Int32[] data) {
for (Int32 n = 0; n < data.Length; n++) data[n] = n;
return data.Length;
}
public Int32[] ReturnArray() {
return new Int32[] { 1, 2, 3 };
}
#endregion
//
public void PassAndModifyCollection(IDictionary<String, Object> collection) {
collection["Key2"] = "Value2"; // " "
}
#region
//
// JavaScript
public void SomeMethod(Int32 x) { }
[Windows.Foundation.Metadata.DefaultOverload] //
public void SomeMethod(String s) { } //
#endregion
#region
public event WinRTDelegate AutoEvent;
public String RaiseAutoEvent(Int32 number) {
WinRTDelegate d = AutoEvent;
return (d == null) ? "No callbacks registered" : d(number);
}
#endregion
#region

720

25. WinRT

//
private EventRegistrationTokenTable<WinRTDelegate> m_manualEvent = null;
// add remove
public event WinRTDelegate ManualEvent {
add {
// ( ,
// )
return EventRegistrationTokenTable<WinRTDelegate>
.GetOrCreateEventRegistrationTokenTable(ref m_manualEvent)
.AddEventHandler(value);
}
remove {
EventRegistrationTokenTable<WinRTDelegate>
.GetOrCreateEventRegistrationTokenTable(ref m_manualEvent)
.RemoveEventHandler(value);
}
}
public String RaiseManualEvent(Int32 number) {
WinRTDelegate d = EventRegistrationTokenTable<WinRTDelegate>
.GetOrCreateEventRegistrationTokenTable(ref
m_manualEvent).InvocationList;
return (d == null) ? "No callbacks registered" : d(number);
}
#endregion
#region Asynchronous methods
//
// IAsync[Action|Operation](WithProgress)
// : DataTimeOffset
// Windows.Foundation.DateTime
public IAsyncOperationWithProgress<DateTimeOffset, Int32>
DoSomethingAsync() {
// Run
// System.Runtime.InteropServices.WindowsRuntime.AsyncInfo
// ,
// .
return AsyncInfo.Run<DateTimeOffset, Int32>(DoSomethingAsyncInternal);
}
//
// .NET
private async Task<DateTimeOffset> DoSomethingAsyncInternal(
CancellationToken ct, IProgress<Int32> progress) {
for (Int32 x = 0; x < 10; x++) {
//
ct.ThrowIfCancellationRequested();
if (progress != null) progress.Report(x * 10);
await Task.Delay(1000); //
}

WinRT C#

721

return DateTimeOffset.Now; //
}
public IAsyncOperation<DateTimeOffset> DoSomethingAsync2() {
// ,
// AsAsync[Action|Operation]
// System.WindowsRuntimeSystemExtensions
// ( AsyncInfo.Run )
return DoSomethingAsyncInternal(default(CancellationToken),
null).AsAsyncOperation();
}
#endregion
//
// [Version(#)], WinMDExp.exe
// COM. ,
// COM .
[Version(2)]
public void NewMethodAddedInV2() {}
}
}

JavaScript
WinRT.
function () {
//
var WinRTComps = Wintellect.WinRTComponents;
// WinRT
var s = WinRTComps.WinRTClass.staticMethod(null); // JavaScript "null"!
var struct = { anumber: 123, astring: "Jeff", aenum:
WinRTComps.WinRTEnum.notNone };
WinRTComps.WinRTClass.staticProperty = struct;
s = WinRTComps.WinRTClass.staticProperty; //
// ,
//
var s = WinRTComps.WinRTClass.outParameters();
var name = s.value; //
var struct = s.x; // 'out'
var year = s.year; // 'out'
// WinRT
var winRTClass = new WinRTComps.WinRTClass(null);
s = winRTClass.toString(); // ToString()
//
try { winRTClass.throwingMethod(); }
catch (err) { }
//
var a = [1, 2, 3, 4, 5];

722

25. WinRT

var sum = winRTClass.passArray(a);


//
var arrayOut = [7, 7, 7]; // : fillArray !
var length = winRTClass.fillArray(arrayOut); //
// arrayOut = [0, 1, 2]
//
a = winRTClass.returnArray(); // a = [ 1, 2, 3]
//
var localSettings = Windows.Storage.ApplicationData.current.localSettings;
localSettings.values["Key1"] = "Value1";
winRTClass.passAndModifyCollection(localSettings.values);
// localSettings.values 2 "/"
//
winRTClass.someMethod(5); // SomeMethod(String), "5"
//
var f = function (v) { return v.target; };
winRTClass.addEventListener("autoevent", f, false);
s = winRTClass.raiseAutoEvent(7);
//
winRTClass.addEventListener("manualevent", f, false);
s = winRTClass.raiseManualEvent(8);
// ,
//
var promise = winRTClass.doSomethingAsync();
promise.then(
function (result) { console.log("Async op complete: " + result); },
function (error) { console.log("Async op error: " + error); },
function (progress) {
console.log("Async op progress: " + progress);
//if (progress == 30) promise.cancel(); //
});
}

26. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. 724
27.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 747
28. -. .. ..787
29.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..820
30.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..854

26.

, (threads)1.
, Microsoft Windows ,
,
(CLR-) Windows-, ,
Windows, .NET Framework, , .
, Windows CLR . ,
, ,
.

Windows ?

. , ,
, . ,
, . , 16- Windows ,
.
.
, ,
.
, Reset
. ,
( ),
, .
Microsoft , 16 Windows ,

, , , .
, , ,

- (streams). . .

725

.
WindowsNT. .
Windows .

(process). , .
; , .
,
.
; ,
. .
,
, ,
,
.
?
? ,
.
( ),
, ,
. .
, Windows. Windows- ( ).
, , ( )
!


; Windows
, . ,
(, ) , .
, ,
() ( ).
. .

726

26.

(thread kernel object).


.
( ) . ,
. x86, x64
ARM 700, 1240 350 .
(Thread Environment Block, TEB). , (
, ).
(4 x86, x64 ARM).
. try,
, . try, . TEB
,
(GDI) OpenGL.
(user-mode stack).
.
, , ,
.
Windows 1 ( , 1 ).
(kernel-mode stack). ,
,
. Windows ,
,
. .
,
, . ,
,
.
32- Windows 12, 64- 24.
. Windows ,
,
DLL- DllMain DLL_THREAD_
ATTACH. ,
DLL_THREAD_DETACH. ,
DLL-
/ . ,
DLL- C-Runtime -

727

,
.
Windows 5 6 ,
.
, Microsoft Visual Studio
470DLL-! ,

470 DLL. Visual
Studio . ,
1.
, ,
. -
(context switching).
- . ,

( ).
Windows
. ,
(quantum). Windows .
:
1. , .
2. , . , Windows .
- - .
3.
.
,
,
. Windows 30. .

1
C#
DllMain, DLL-
DLL_THREAD_ATTACH DLL_THREAD_DETACH.
, Win32- DisableThreadLibraryCalls
. ,
, .

728

26.

,
.
- , Windows
. ,
, ,
. , ,
, . . ,
,
.
, . .
, ,
, ,
. , ,
, . ,
, , . 30
.
. ,
. , , . ,
.

Windows
( ), . .

, , , - (,
, , . .). , Notepad ,
. Windows
, . 5,
Win32-, Windows . , ( ).

. , ,
, .

729

CLR , , ,
( , )
. ,
. Windows

. ,
, .
,
,
, . . ,
, Windows
.
,
,
( ).
, . ,
, .
. Windows
,
.
.
Windows CLR,
,

.

!
,
.
,
.. :
, ,
.
, .
Windows Microsoft ,

730

26.

.
. , - Windows .NET Framework,
-
. Windows
, . , .26.1 , Performance
().

. 26.1.

,
55, , 55.
. , 864! , ,
4.
, 15,7,

.
,
, 5%. 95%
864 , , .
, ?
, . , -

731

, Details (), Threads


( )1 , .26.2.

. 26.2.

, 105 , 1% , Explorer 47 0% ,
Microsoft Visual Studio (Devenv.exe) 36, 0% , Outlook,
24 0% .. ?
Windows, ,
.
, , , EXE- DLL- ..
.
,
. .
, .
, . , .

Select Columns ( ).
1

732

26.

, .
,
, 1.
,
, 100. 100 Outlook, 24
. 2400, ,
TEB, , ..
. ,
Microsoft , Windows ,
1 .
.


,

. . , , ,
, .
. -
;
.
, . -
,
.
. -
, ,
. , . ,
,
, .
Notepad.exe
. File () Open (),
File Open ( ),
. 31 ! ,
. !
1

CLR- Windows-

733

. ? .
:
. . ,
, .
, , .
-
.
, -
.
. ( Intel)
. , ,
. Windows
,
, .
- ,
, .
, Windows .
.
,
.
.
Intel, 1030%.
. , .
, .
. , . Intel 80. ,
! , Intel
.

CLR- Windows-
CLR Windows ,
V ,
, CLR. -

734

26.

, Windows CLR.

, Windows via C/C++ (Microsoft
Press, 2007).
.NET Framework CLR
, CLR ,
Windows. 2005 CLR
, CLR-
Windows-, .NET Framework
. , System.Environment
CurrentManagedThreadId, CLR- ,
System.Diagnostics.ProcessThread Id Windows- . BeginThreadAffinity
EndThreadAffinity System.Thread
, CLR- Windows-.
Windows Store Microsoft
API, , (. ! ) , Microsoft Windows
Apps. , System.Thread Windows Store
- API (, Start, IsBackground, Sleep, Suspend,
Resume, Join, Interrupt, Abort, BeginThreadAffinity EndThreadAffinity).
, , , . 2630 APIs ,
, Windows Store.
, API Windows Store.

,
. ,
( Windows Store - System.Thread).
CLR (thread pool).
.
, .
, ,
. :

735

(
). ,
, ,
.
, ,
.
.
, ,
- , CLR .
, , ;

.
Abort Thread,
22.
System.
Threading.Thread,
. :

public sealed class Thread : CriticalFinalizerObject, ... {


public Thread(ParameterizedThreadStart start);
//
}

start , .
ParameterizedThreadStart:1
delegate void ParameterizedThreadStart(Object obj);

Thread ,
.
, ,
Start Thread, (),
.
,
:

Thread , ThreadStart,
.
- . Object
void,
, 27.
1

736

26.

using System;
using System.Threading;
public static class Program {
public static void Main() {
Console.WriteLine("Main thread: starting a dedicated thread " +
"to do an asynchronous operation");
Thread dedicatedThread = new Thread(ComputeBoundOp);
dedicatedThread.Start(5);
Console.WriteLine("Main thread: Doing other work here...");
Thread.Sleep(10000); // (10 )
dedicatedThread.Join(); //
Console.WriteLine("Hit <Enter> to end this program...");
Console.ReadLine();
}
//
// ParameterizedThreadStart
private static void ComputeBoundOp(Object state) {
// ,
Console.WriteLine("In ComputeBoundOp: state={0}", state);
Thread.Sleep(1000); // (1 )
//
}
}

:
Main thread: starting a dedicated thread to do an asynchronous operation
Main thread: Doing other work here...
In ComputeBoundOp: state=5


Windows, :
Main thread: starting a dedicated thread to do an asynchronous operation
In ComputeBoundOp: state=5
Main thread: Doing other work here...

, Main Join. , , dedicatedThread, .


:
( ). Windows

737

, .
,
. , ,
. ,
, .
( ).
Windows , ,
. ,
,
. ,
. , ,
27 28.
. , , .
, . , ,
100%. ,
. -, 100
. -,
, , , 100%. , , , .
,
, . ,
,

.
, , , . .
, , . ,
,
, , ,
.
. .
, , 5% -

738

26.

. , , .
80- , ,
. ,
!

.
, ,
.
, .
, , ,
. , ,
.
, Visual Studio .
,
.
-- , () .
.
.
, Visual Studio Build,
. ,
, .

. ,
. ,
. .
,
. .
:
, ,
-.
,
, ,
, .
.

739


,
. , Windows.
,
.
Windows ,
,
. ,
. .26.3
Microsoft Spy++, .
, 317681.
, . Windows .
.
Windows
, . ,
- , ,
.

. 26.3. Spy++

, 25,
. .
1

740

26.

:
- ? ,
1
? : .
, Windows
. , .
, . Windows Microsoft
: , , ..
.
, - CLR . ,
, JIT- , .

( )
31 ( ). , ,
. 31 .
,
.
31
.
(starvation), ,
. , 31 30 . ,
.

, .
5 ,
, ( )
.
(zero page thread),
. .
.
,
.

741

10, 23? Windows .


,
, . . Windows
: Idle ( ), Below Normal
( ), Normal (), Above Normal ( ), High () Realtime ( ). Normal,
.
,
, ( ,
).
( , )
. ,
, .
, . .
,
- .
, ,
, .
,
- .

,
.

.

, , ,
. Windows
: Idle ( ), Lowest ( ), Below Normal ( ), Normal (), Above Normal ( ), Highest ( )
Time-Critical ( ). .
, , .
, ,
. ,

742

26.

31. . .
,
.26.1.
26.1.

Time-Critical

15

15

15

15

15

31

Highest

10

12

15

26

Above Normal

11

14

25

Normal

10

13

24

Below Normal

12

23

Lowest

11

22

Idle

16

Idle

Below
Normal

Normal

Above
Normal

High

Realtime

, Normal Normal, 8. Normal


, ,
8.
Normal
13. Idle, 4. ,
.
, .
: ,
. ,
, . : 17, 18, 19,
20, 21, 27, 28, 29 30. ,
, . , Realtime
16.
15.

743

, Windows
- . .
,
; .

, .
, ,
, ,
.. , - , .
,
.
Windows (Windows Explorer), Windows
.
.
Windows ,
.

, .
Windows, Normal. , .
,
. , ASP.
NET ,
. Silverlight, -, ,
Microsoft SQL Server.

Priority Thread,
(Lowest, BelowNormal, Normal, AboveNormal Highest),
ThreadPriority . ,
Windows , CLR
Idle Time-Critical. CLR
Idle, . , 21,
Time-Critical. ,
: .26.1
(Highest) (Lowest).

744

26.

, . , ,
100%, ,
. ,
,
- . ,
, , . , 8 ,
. ,
.
.

System.Diagnostics Process
ProcessThread (, ,
Windows Store).
Windows. ,

, .
System.Diagnostics.
.
, , Silverlight ASP.NET.
, AppDomain
Thread, CLR .
,
.


CLR (foreground) (background).
CLR
.
.
,
, ,
.
,
. , , ,
.

745

CLR . ,
,
. ,
, CLR ,
.
, .
:
using System;
using System.Threading;
public static class Program {
public static void Main() {
// ( )
Thread t = new Thread(Worker);
//
t.IsBackground = true;
t.Start(); //
// 10
//
Console.WriteLine("Returning from Main");
}
private static void Worker() {
Thread.Sleep(10000); // 10
// ,
//
Console.WriteLine("Returning from Worker");
}
}

.
,
Thread, .
. ,
, .

.
, .
, ,
, .
, ,
.

746

26.

?
. , ,

. CLR,
.
, .
27 ,
. 28 ,
CLR -.
- , . ,
. , , 29 30.
, ,
- Windows NT 3.1, 1992.
- .NET ,
. (
Wintellect Power Threading Library) . CLR, Silverlight CLR Compact
Framework. ,
http://Wintellect.com/PowerThreading.aspx.
.

27.


, . , , , , ,
, - ,
. ,
.
. ,
Performance (). 100%
( ), , .
, ( ) . , ,
, ,
. -
Microsoft Windows ,
, .
.
, -, ,
.
. , , ,
.
,
. ,
, -,
, -,
.

CLR
,
. ,

748

27.

,
. ,
CLR ,
, .
CLR , , CLR.
CLR, .
CLR . .
,
.
. , . ,
.
,
. , .
,
.
, , .

.
,
, .
( CLR) , . ,
, , , .
,
,
, .
.
,
.
.



ThreadPool:
static Boolean QueueUserWorkItem(WaitCallback callBack);
static Boolean QueueUserWorkItem(WaitCallback callBack, Object state);

749


.
callback ,
.
state ( ).
QueueUserWorkItem null. , ,
.
System.Threading.WaitCallback, :
delegate void WaitCallback(Object state);

WaitCallback TimerCallback ( ),
ParameterizedThreadStart ( 25) .
, ,
ThreadPool.QueueUserWorkItem System.Threading.
Timer System.Threading.Thread.

:
using System;
using System.Threading;
public static class Program {
public static void Main() {
Console.WriteLine("Main thread: queuing an asynchronous operation");
ThreadPool.QueueUserWorkItem(ComputeBoundOp, 5);
Console.WriteLine("Main thread: Doing other work here...");
Thread.Sleep(10000); // (10 )
Console.WriteLine("Hit <Enter> to end this program...");
Console.ReadLine();
}
// WaitCallback
private static void ComputeBoundOp(Object state) {
//
Console.WriteLine("In ComputeBoundOp: state={0}", state);
Thread.Sleep(1000); // (1 )
//
//
}
}

:
Main thread: queuing an asynchronous operation
Main thread: Doing other work here...
In ComputeBoundOp: state=5

750

27.

, :
Main thread: queuing an asynchronous operation
In ComputeBoundOp: state=5
Main thread: Doing other work here...


. Windows , ,
.

, CLR ( ).
20.

Windows Store System.Threading.ThreadPool


. ,
System.Threading.Tasks (.
).


. ( , Principal
Thread Windows), (System.
Threading.HostExecutionContextManager)
(. LogicalSetData LogicalGetData System.Runtime.
Remoting.Messaging.CallContext). , .

.
, , .
CLR
. ,
,
.
. , ,

751

,
.
ExecutionContext System.Threading
. :
public sealed class ExecutionContext : IDisposable, ISerializable {
[SecurityCritical] public static AsyncFlowControl SuppressFlow();
public static void RestoreFlow();
public static Boolean IsFlowSuppressed();
//
}

,
. .
, , SuppressFlow [SecurityCritical],
(, Microsoft Silverlight). ,
, .
,
.
, (, Windows).
,
CLR-1:
public static void Main() {
// Main
CallContext.LogicalSetData("Name", "Jeffrey");
//
//
ThreadPool.QueueUserWorkItem(
state => Console.WriteLine("Name={0}",
CallContext.LogicalGetData("Name")));
// Main
ExecutionContext.SuppressFlow();
// .
//
ThreadPool.QueueUserWorkItem(


(.24). , , ,
.
1

752

27.

state => Console.WriteLine("Name={0}",


CallContext.LogicalGetData("Name")));
// Main
//
ExecutionContext.RestoreFlow();
...
Console.ReadLine();
}

:
Name=Jeffrey
Name=

ThreadPool.QueueUserWorkItem,
Task (. ), - ( 28).


.NET .
(cooperative), . , , ,
, , ,
.
, . , ,
.
FCL,
.
System.Threading.CancellationTokenSource.
:
public sealed class CancellationTokenSource : IDisposable { //
public CancellationTokenSource();
public Boolean IsCancellationRequested { get; }
public CancellationToken Token { get; }
public void Cancel(); // Cancel false
public void Cancel(Boolean throwOnFirstException);
...
}

, .
CancellationTokenSource ( )

753

CancellationToken ( )
Token. , .
CancellationToken:
public struct CancellationToken { //
public static CancellationToken None { get; } //
Boolean IsCancellationRequested { get; } //
//
public void ThrowIfCancellationRequested(); //
//

,
Task
,
Task

// WaitHandle CancellationTokenSource
public WaitHandle WaitHandle { get; }
// GetHashCode, Equals, == !=
public Boolean CanBeCanceled { get; } //
public CancellationTokenRegistration Register(
Action<Object> callback, Object state,
Boolean useSynchronizationContext); //
//
}

CancellationToken ,
: Cancellation
TokenSource.
IsCancellationRequested CancellationToken, ,
, . , .
:
internal static class CancellationDemo {
public static void Main() {
CancellationTokenSource cts = new CancellationTokenSource();
// CancellationToken
ThreadPool.QueueUserWorkItem(o => Count(cts.Token, 1000));
Console.WriteLine("Press <Enter> to cancel the operation.");
Console.ReadLine();
cts.Cancel(); // Count ,
// Cancel
// Cancel , ...
Console.ReadLine();
}
private static void Count(CancellationToken token, Int32 countTo) {
for (Int32 count = 0; count <countTo; count++) {
if (token.IsCancellationRequested) {

754

27.

Console.WriteLine("Count is cancelled");
break; //
}
Console.WriteLine(count);
Thread.Sleep(200); //
}
Console.WriteLine("Count is done");
}
}

,
CancellationToken, None
CancellationToken.
CancellationToken, - CancellationTokenSource (
null). CancellationTokenSource
, Cancel. ,
IsCancellationRequested CancellationToken false. CanBeCanceled.
true CancellationToken,
Token CancellationTokenSource.


, CancellationTokenSource.
Register
CancellationToken Action<Object> ,
,
Boolean, ,
SynchronizationContext . useSynchronizationContext false, ,
Cancel , . true
SynchronizationContext, ,
. SynchronizationContext 28.

,
CancellationTokenSource, , Register,
(, SynchronizationContext ,
useSynchronizationContext true).

Register
,

755

. Cancel CancellationTokenSource true, , , ,


Cancel.
false,
.
. , Cancel
AggregateException, InnerExceptions
. Cancel .

,
InnerExceptions AggregateException.
, ,
, . , StackTrace
.

Register CancellationToken Cancellation


TokenRegistration, :
public struct CancellationTokenRegistration :
IEquatable<CancellationTokenRegistration>, IDisposable {
public void Dispose();
// GetHashCode, Equals, == !=
}

Dispose CancellationTokenSource , . Cancel .


,
CancellationTokenSource:
varcts = new CancellationTokenSource();
cts.Token.Register(() => Console.WriteLine("Canceled 1"));
cts.Token.Register(() => Console.WriteLine("Canceled 2"));
//
cts.Cancel();

, Cancel:
Canceled 2
Canceled 1

756

27.

, CancellationTokenSource,
CancellationTokenSource.
. :
// CancellationTokenSource
var cts1 = new CancellationTokenSource();
cts1.Token.Register(() => Console.WriteLine("cts1 canceled"));
// CancellationTokenSource
var cts2 = new CancellationTokenSource();
cts2.Token.Register(() => Console.WriteLine("cts2 canceled"));
// CancellationTokenSource,
// cts1 ct2
var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
cts1.Token, cts2.Token);
linkedCts.Token.Register(() => Console.WriteLine("linkedCts canceled"));
// CancellationTokenSource ( cts2)
cts2.Cancel();
// , CancellationTokenSource
Console.WriteLine("cts1 canceled={0}, cts2 canceled={1}, linkedCts={2}",
cts1.IsCancellationRequested, cts2.IsCancellationRequested,
linkedCts.IsCancellationRequested);

:
linkedCts canceled
cts2 canceled
cts1 canceled=False, cts2 canceled=True, linkedCts=True

. , ,
. .
,
. , CancellationTokenSource
.
CancellationTokenSource , , CancelAfter
CancellationTokenSource.
public sealed class CancellationTokenSource : IDisposable { //
public CancellationTokenSource(Int32 millisecondsDelay);
public CancellationTokenSource(TimeSpan delay);

public void CancelAfter(Int32 millisecondsDelay);


public void CancelAfter(TimeSpan delay);
...

757

QueueUserWorkItem ThreadPool
.
. ,
. Microsoft
(tasks),
System.Threading.Tasks.
,
QueueUserWorkItem ThreadPool:
ThreadPool.QueueUserWorkItem(ComputeBoundOp, 5); // QueueUserWorkItem
new Task(ComputeBoundOp, 5).Start(); //
Task.Run(() => ComputeBoundOp(5)); //

Task
Start . , Task Start . ,
Task - ,
Start. Task
Start ,
Run Task, .
Task
Action Action<Object>, , . , Object, Task
, .
Run Func<TResult> Action,
.
CancellationToken, Task (
).

TaskCreationOptions, .
, . TaskCreationOptions
:
[Flags, Serializable]
public enumTaskCreationOptions {
None = 0x0000, //
// ,
//
PreferFairness = 0x0001,
// ,

758

27.

// .
LongRunning = 0x0002,
// :
AttachedToParent = 0x0004,
// ,
// , .
DenyChildAttach = 0x0008,
//
// .
HideScheduler
= 0x0010
}

, ,
TaskScheduler; AttachedToParent,
DenyChildAttach HideScheduler,
TaskScheduler. .


. Sum, n
:
private static Int32 Sum(Int32 n) {
Int32 sum = 0;
for (; n > 0; n--)
checked { sum += n; } // n System.OverflowException
return sum;
}

Task<TResult> ( Task) TResult ,


.
:
// Task ( )
Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000000000);
//
t.Start();
//
t.Wait(); // . ,
// -/CancellationToken
// ( Result Wait)
Console.WriteLine("The Sum is: " + t.Result); // Int32

759

Wait ,
Task, . ,
Wait, .
, ( TaskScheduler)
, Wait. . Task
. (
), (
).
. , Wait
,
, (deadlock)!

, , .
Wait Result
System.AggregateException.
AggregateException (
,
, ). InnerExceptions,
ReadOnlyCollection<Exception>.
InnerException, AggregateException
System.Exception. , 0
InnerExceptions AggregateException
System.OverflowException, (Sum).
AggregateException GetBaseException
Exception. , (,
). AggregateException
Flatten, AggregateException,
InnerExceptions ,
.
, Handle,
AggregateException .
.
true, , , false.
Handle ,
AggregateException. , Flatten Handle
.
,
Task. . WaitAny
Task. Int32 ,

760

27.

, . -, 1.
CancellationToken OperationCanceledException.

Wait Result
Exception Task, . ,
,
. UnobservedTaskException
TaskScheduler.
CLR.
UnobservedTaskExceptionEve
ntArgs, AggregateException.

WaitAll Task Task . true


false, . CancellationToken
OperationCanceledException.


CancellationTokenSource.
, Sum,
CancellationToken:
private static Int32 Sum(CancellationTokenct, Int32 n) {
Int32 sum = 0;
for (; n > 0; n--) {
// OperationCanceledException
// Cancel CancellationTokenSource,
//
ct.ThrowIfCancellationRequested();
checked { sum += n; } // n
// System.OverflowException
}
return sum;
}

ThrowIfCancellationRequested CancellationToken, ,

.
IsCancellationRequested CancellationToken , .

761

CancellationTokenSource OperationCanceledException. ,
, QueueUserWorkItem
ThreadPool,
. , , . .
CancellationTokenSource Task:
CancellationTokenSource cts = new CancellationTokenSource();
Task<Int32> t = new Task<Int32>(() => Sum(cts.Token, 10000), cts.Token);
t.Start();
// CancellationTokenSource, Task
cts.Cancel(); // ,
try {
// Result
// AggregateException
Console.WriteLine("The sum is: " + t.Result); // Int32
}
catch (AggregateException x) {
// OperationCanceledException
// AggregateException,
//
x.Handle(e => e is OperationCanceledException);
// ,
Console.WriteLine("Sum was canceled");
}

Task CancellationToken ,
Task ( ).
CancellationToken , 1.
( Start),
. ,
Task CancellationToken, .
- CancellationToken,
Task, .
-
CancellationToken (, ,
).

InvalidOperationException.
1

762

27.


. Wait Result , , ,
. ,
.
. ,
:
// Task
Task<Int32> t = Task.Run(() => Sum(CancellationToken.None, 10000));
// ContinueWith Task,
//
Task cwt = t.ContinueWith(task => Console.WriteLine(
"The sum is: " + task.Result));

, , Sum, ,
( ),
. , ; -
, , .
, Sum ContinueWith. , , ContinueWith
Sum ,
.
, ContinueWith
Task ( cwt).
(, Wait,
Result ContinueWith), ,
.
, Task
ContinueWith.
ContinueWith Task. , ContinueWith .
, ContinueWith TaskContinuationOptions. None, PreferFairness,
LongRunning, AttachedToParent,DenyChildAttach HideScheduler
TaskCreationOptions.
TaskContinuationOptions:
[Flags, Serializable]
public enumTaskContinuationOptions {
None = 0x0000, //
// ,

763

//
PreferFairness = 0x0001,
// ,
// .
LongRunning = 0x0002,
// :
AttachedToParent = 0x0004,
// ,
// , .
DenyChildAttach = 0x0008,
//
// .
HideScheduler = 0x0010,
// .
LazyCancellation = 0x0020,
// , , ,
// , ContinueWith.
// , , ContinueWith,
// ContinueWith
ExecuteSynchronously = 0x80000,
// , ContinueWith
NotOnRanToCompletion = 0x10000,
NotOnFaulted = 0x20000,
NotOnCanceled = 0x40000,
//
OnlyOnCanceled = NotOnRanToCompletion | NotOnFaulted,
OnlyOnFaulted = NotOnRanToCompletion | NotOnCanceld,
OnlyOnRanToCompletion = NotOnFaulted | NotOnCanceled,
}

ContinueWith TaskContinuationOptions.OnlyOn
Canceled , . , TaskContinuationOptions.OnlyOnFaulted

, ,
.
TaskContinuationOptions.OnlyOnRanToCompletion ,
,
. ,
. Task
. , :

764

27.

//
Task<Int32> t = Task.Run(() => Sum(10000));
// ContinueWith Task,
//
t.ContinueWith(task => Console.WriteLine("The sum is: " + task.Result),
TaskContinuationOptions.OnlyOnRanToCompletion);
t.ContinueWith(task => Console.WriteLine("Sum threw: " + task.Exception),
TaskContinuationOptions.OnlyOnFaulted);
t.ContinueWith(task => Console.WriteLine("Sum was canceled"),
TaskContinuationOptions.OnlyOnCanceled);


, -:
Task<Int32[]> parent = new Task<Int32[]>(() => {
var results = new Int32[3]; //
// 3
new Task(() => results[0] = Sum(10000),
TaskCreationOptions.AttachedToParent).Start();
new Task(() => results[1] = Sum(20000),
TaskCreationOptions.AttachedToParent).Start();
new Task(() => results[2] = Sum(30000),
TaskCreationOptions.AttachedToParent).Start();
//
// ( )
return results;
});
//
varcwt = parent.ContinueWith(
parentTask => Array.ForEach(parentTask.Result, Console.WriteLine));
// ,
parent.Start();

Task. - . TaskCreationOptions.AttachedToParent
. Task ContinueWith
TaskContinuationOptions.AttachedToParent, , , .

765


Task , .
: Int32 (
Id Task), Int32, , , TaskScheduler,
, ,
, ( AsyncState Task),
ExecutionContext ManualResetEventSlim.
, Task , .
CancellationToken, ContinueWithTask,
Task , ,
. ,
. ,
ThreadPool.QueueUserWorkItem.
Task Task<TResult> IDisposable,
Task Dispose.
ManualResetEventSlim,
, Task Task<TResult>, , Dispose. ,
Dispose Task;
.
, Task Int32,
. . Id ( )
Int32,
.
.
, Task Microsoft
Visual Studio.
, . Visual Studio
Parallel Tasks Parallel Stacks.
, ,
. CurrentId
Task, Int32,
null (Int32?). ,
, Visual Studio Watch Immediate.
Parallel Tasks Parallel Stacks.
CurrentId , , null.

766

27.

, ,
Status Task.
TaskStatus, :
public enum TaskStatus {
// , :
Created, //
//
WaitingForActivation, //
//
WaitingToRun, // ,
Running, //
// ,
WaitingForChildrenToComplete,
// :
RanToCompletion,
Canceled,
Faulted
}

Task Created. , , WaitingToRun. Running.


, ,
WaitingForChildrenToComplete.
: RanToCompletion, Canceled Faulted. Task<TResult> Result.
Task Task<TResult> , ,
, Exception Task; AggregateException,
.
Task
Boolean: IsCanceled, IsFaulted IsCompleted.
true , Task
RanToCompleted, Canceled Faulted. , , :
if (task.Status == TaskStatus.RanToCompletion) ...

Task WaitingForActivation, : ContinueWith, ContinueWhenAll,


ContinueWhenAny FromAsync. ,
TaskCompletionSource<TResult> ,
WaitingForActivation. , . ,

767

Task, ContinueWith.
.


Task,
.
,
(task factory), . System.
Threading.Tasks TaskFactory TaskFactory<TResult>.
System.Object;
.
, ,
TaskFactory. , TaskFactory<TResult>, TResult
.
,
. , CancellationToken, TaskScheduler,
TaskCreationOptions TaskContinuationOptions,
.
TaskFactory:
Task parent = new Task(() => {
varcts = new CancellationTokenSource();
vartf = new TaskFactory<Int32>(cts.Token,
TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
// 3
varchildTasks = new[] {
tf.StartNew(() => Sum(cts.Token, 10000)),
tf.StartNew(() => Sum(cts.Token, 20000)),
tf.StartNew(() => Sum(cts.Token, Int32.MaxValue)) //
// OverflowException
};
// ,
//
for (Int32 task = 0; task <childTasks.Length; task++)
childTasks[task].ContinueWith(
t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted);
//
//
//
tf.ContinueWhenAll(
childTasks,

768

27.

completedTasks => completedTasks.Where(


t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result),
CancellationToken.None)
.ContinueWith(t =>Console.WriteLine("The maximum is: " + t.Result),
TaskContinuationOptions.ExecuteSynchronously);
});
// ,
// ,
parent.ContinueWith(p => {
// StringBuilder
// Console.WriteLine ,
// ,
//
StringBuildersb = new StringBuilder(
"The following exception(s) occurred:" + Environment.NewLine);
foreach (var e in p.Exception.Flatten().InnerExceptions)
sb.AppendLine(" "+ e.GetType().ToString());
Console.WriteLine(sb.ToString());
}, TaskContinuationOptions.OnlyOnFaulted);
// ,
parent.Start();

TaskFactory<Int32>,
Task. , Task
CancellationTokenSource,
,
.
Task, StartNew TaskFactory,
.
. , , .
TaskFactory ContinueWhenAll,
, .
TaskFactory,
.
,
CancellationToken
CancellationToken.None. .
, ,
, .

769

ContinueWhenAll ContinueWhenAny
TaskFactory TaskFactory<TResult> TaskContinuationOption: NotOnRanToCompletion, NotOnFaulted NotOnCanceled.
, OnlyOnCanceled, OnlyOnFaulted
OnlyOnRanToCompletion. ContinueWhenAll ContinueWhenAny ,
.


,
TaskScheduler. TaskScheduler

Visual Studio. FCL TaskScheduler : . ,
( ).
Default
TaskScheduler.
Windows Forms, Windows Presentation Foundation (WPF), Silverlight
Windows Store. , ,
, ..
. From
CurrentSynchronizationContext TaskScheduler.
Windows Forms
:
internal sealed class MyForm : Form {
private readonly TaskScheduler m_syncContextTaskScheduler;
public MyForm() {
m_syncContextTaskScheduler =
TaskScheduler.FromCurrentSynchronizationContext();

Text = "Synchronization Context Task Scheduler Demo";


Visible = true; Width = 600; Height = 100;

//
private readonly TaskScheduler m_syncContextTaskScheduler =
TaskScheduler.FromCurrentSynchronizationContext();
private CancellationTokenSource m_cts;
protected override void OnMouseClick(MouseEventArgs e) {

770

27.

if (m_cts != null) { // ,
m_cts.Cancel();
m_cts = null;
} else { // ,
Text = "Operation running";
m_cts = new CancellationTokenSource();
//
//
Task<Int32> t = Task.Run(() => Sum(m_cts.Token, 20000), m_cts.Token);
//
//
t.ContinueWith(task => Text = "Result: " + task.Result,
CancellationToken.None,
TaskContinuationOptions.OnlyOnRanToCompletion,
m_syncContextTaskScheduler);
t.ContinueWith(task => Text = "Operation canceled",
CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled,
m_syncContextTaskScheduler);
t.ContinueWith(task => Text = "Operation faulted",
CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted,
m_syncContextTaskScheduler);
}
base.OnMouseClick(e);
}
}


. , , GUI
.
.
InvalidOperationException.
, ,
. ,
GUI-,
.
Text.
( Sum) , .
.
,
, TaskScheduler. Microsoft
Parallel

For, ForEach Invoke Parallel

771

Extensions Extras, http://code.msdn.microsoft.


com/ParExtSamples. , , :
IOTaskScheduler. - ,
.
LimitedConcurrencyLevelTaskScheduler.
n , n .
OrderedTaskScheduler. .
LimitedConcurrencyLevelTaskSched
uler n 1.
PrioritizingTaskScheduler. CLR.
Prioritize ,
( ).
Deprioritize, ,
.
ThreadPerTaskScheduler.
, .

For, ForEach Invoke Parallel


, , .
System.
Threading.Tasks.Parallel. :
//
for (Int32 i = 0; i < 1000; i++) DoWork(i);

For Parallel
:
//
Parallel.For(0, 1000, i => DoWork(i));

:
//
foreach (var item in collection) DoWork(item);

:
//
Parallel.ForEach(collection, item => DoWork(item));

772

27.

For ForEach, For,


.
, , :
//
Method1();
Method2();
Method3();

:
//
Parallel.Invoke(
() => Method1(),
() => Method2(),
() => Method3());

Parallel
. , , . ,
,
, ,
, ,
for foreach. ,
. - , Parallel
AggregateException.
, , for Parallel.For, foreach Parallel.ForEach.
Parallel ,
. , ,
, . , ,

.
, .
,
.
, Parallel
,
. , , .
, -
. ,

For, ForEach Invoke Parallel

773

Parallel
, .
, For, ForEach Invoke Parallel
, ParallelOptions.
:
public class ParallelOptions{
public ParallelOptions();
//
public CancellationTokenCancellationToken { get; set; }
// CancellationToken.None
//
// ,
public Int32MaxDegreeOfParallelism { get; set; }
// -1 ( )
//
public TaskSchedulerTaskScheduler { get; set; }
// TaskScheduler.Default
}

For ForEach,
:
(localInit)
.
body , .
(localFinally )
,
. , body .

, :
private static Int64 DirectoryBytes(String path, String searchPattern,
SearchOptionsearchOption) {
var files = Directory.EnumerateFiles(path, searchPattern, searchOption);
Int64 masterTotal = 0;
ParallelLoopResult result = Parallel.ForEach<String, Int64>(
files,
() => { // localInit:

774

27.

// : 0
return 0; // taskLocalTotal 0
},
(file, loopState, index, taskLocalTotal) => { // body:
//
//
Int64 fileLength = 0;
FileStreamfs = null;
try {
fs = File.OpenRead(file);
fileLength = fs.Length;
}
catch (IOException) { /* , */ }
finally { if (fs != null) fs.Dispose(); }
return taskLocalTotal + fileLength;
},
taskLocalTotal => { // localFinally:
//
Interlocked.Add(ref masterTotal, taskLocalTotal);
});
}

return masterTotal;

taskLocalTotal) . ,

.
Interlocked.Add ( 28).
, ,
.
Interlocked.Add.
, .
, , body
ParallelLoopState:
public class ParallelLoopState{
public void Stop();
public BooleanIsStopped { get; }
public void Break();
public Int64? LowestBreakIteration{ get; }

public BooleanIsExceptional { get; }


public BooleanShouldExitCurrentIteration { get; }

ParallelLoopState

775

. Stop ,
IsStopped true. Break
, . ,
ForEach 100, Break.
. ,
. LowestBreakIteration
, Break.
, null.
IsException true,
.
, ShouldExitCurrentIteration,
, . true, Stop Break,
CancellationTokenSource ( CancellationToken
ParallelOption)
.
For ForEach Parallel ParallelLoop
Result, :
public struct ParallelLoopResult{
// false
public Boolean IsCompleted { get; }
public Int64? LowestBreakIteration{ get; }
}

IsCompleted true, , ,
. IsCompleted false,
LowestBreakIteration null, , -
Stop. ,
LowestBreakIteration, null, , -
Break. LowestBreakIteration
Int64 .


AggregateException.


Microsoft (Language Integrated Query,
LINQ) . ,
. -

776

27.


(sequential query).
(Parallel LINQ),
(parallel query).
( , ),
.
Parallel,
.
Parallel LINQ System.
Linq.ParallelEnumerable ( System.Core.dll),
System.Linq. ,
LINQ-,
Where, Select, SelectMany, GroupBy, Join, OrderBy, Skip, Take ..
System.Linq.ParallelQuery<T>.

( IEnumerable IEnumerable<T>)
( ParallelQuery ParallelQuery<T>),
AsParallel ParallelEnumerable,
1:
public static ParallelQuery<TSource> AsParallel<TSource>(
this IEnumerable<TSource> source)
public static ParallelQuery AsParallel(this IEnumerablesource)

.
, :
private static void ObsoleteMethods(Assembly assembly) {
var query =
from type in assembly.GetExportedTypes().AsParallel()
from method in type.GetMethods(BindingFlags.Public |
BindingFlags.Instance | BindingFlags.Static)
let obsoleteAttrType = typeof(ObsoleteAttribute)
where Attribute.IsDefined(method, obsoleteAttrType)
orderbytype.FullName
let obsoleteAttrObj = (ObsoleteAttribute)
Attribute.GetCustomAttribute(method, obsoleteAttrType)
select String.Format("Type={0}\nMethod={1}\nMessage={2}\n",

ParallelQuery<T> ParallelQuery.

777

type.FullName, method.ToString(), obsoleteAttrObj.Message);


//
foreach (var result in query) Console.WriteLine(result);
}

, .
AsSequential ParallelEnumerable:
public static IEnumerable<TSource> AsSequential<TSource>(
this ParallelQuery<TSource> source)

ParallelQuery<T> IEnumerable<T>,
.
LINQ- , foreach ( ). ,
.
ForAll ParallelEnumerable:
static void ForAll<TSource>(
this ParallelQuery<TSource> source, Action<TSource> action)

.
:
//
query.ForAll(Console.WriteLine);

Console.WriteLine
, Console
, ,
. ,
- . ForAll
, .
LINQ- , .
AsOrdered
ParallelEnumerable. , .
. , : Distinct, Except, Intersect, Union, Join,
GroupBy, GroupJoin ToLookup.
AsOrdered, .
: OrderBy ,
OrderByDescending, ThenBy ThenByDescending.
, ,
AsUnordered.

778

27.

Parallel LINQ Parallel

Enumerable, :

public static ParallelQuery<TSource> WithCancellation<TSource>(


this ParallelQuery<TSource> source, CancellationToken cancellationToken)
public static ParallelQuery<TSource> WithDegreeOfParallelism<TSource>(
this ParallelQuery<TSource> source, Int32 degreeOfParallelism)
public static ParallelQuery<TSource> WithExecutionMode<TSource>(
this ParallelQuery<TSource> source, ParallelExecutionMode executionMode)
public static ParallelQuery<TSource> WithMergeOptions<TSource>(
this ParallelQuery<TSource> source, ParallelMergeOptions mergeOptions)

, WithCancellation Cancellation
Token, .
WithDegreeOfParallelism , -

; ,
, . ,
.
, , ,
. -, , ,
.
, .
,
- .
Parallel LINQ . . :
Concat, ElementAt(OrDefault), First(OrDefault), Last(OrDefault), Skip(While),
Take(While) Zip. , Select(Many) Where,
, .
,
WithExecutionMode ParallelExecutionMode:
public enum ParallelExecutionMode {
Default = 0, //
ForceParallelism = 1 //
}

, Parallel LINQ , , .
WithMergeOptions ,
ParallelMergeOptions:

779

public enum ParallelMergeOptions {


Default = 0, // AutoBuffered ( )
NotBuffered = 1, //
AutoBuffered = 2, //
//
FullyBuffered = 3 //
}

,
. NotBuffered ,
. FullyBuffered , .
AutoBuffered. ,
, .
, , . Parallel LINQ
:
http://blogs.msdn.com/pfxteam/archive/2009/05/28/9648672.aspx;
http://blogs.msdn.com/pfxteam/archive/2009/06/13/9741072.aspx.


System.Threading Timer,
. ,
, ,
. Timer
:
public sealed class Timer : MarshalByRefObject, IDisposable {
public Timer(TimerCallback callback, Object state,
Int32 dueTime, Int32 period);
public Timer(TimerCallback callback, Object state,
UInt32 dueTime, UInt32 period);
public Timer(TimerCallback callback, Object state,
Int64 dueTime, Int64 period);
public Timer(TimerCallback callback, Object state,
Timespan dueTime, TimeSpan period);
}

Timer. callback
, . ,
System.
Threading.TimerCallback, :
delegate void TimerCallback(Object state);

780

27.

state
; , null. dueTime
CLR ( ) . 32
, 64- TimeSpan.
, dueTime 0. period
() .
Timeout.Infinite(-1), .
Timer.
.
QueueUserWorkItem ThreadPool, , .
, .
. , period
Timeout.Infinite. .
Change , period Timeout.Infinite.
Change:
public sealed class Timer : MarshalByRefObject, IDisposable {
public Boolean Change(Int32 dueTime, Int32 period);
public Boolean Change(UInt32 dueTime, UInt32 period);
public Boolean Change(Int64 dueTime, Int64 period);
public Boolean Change(TimeSpan dueTime, TimeSpan period);
}

Timer Dispose,
notifyObject .
Dispose:
public sealed class Timer : MarshalByRefObject, IDisposable {
public Boolean Dispose();
public Boolean Dispose(WaitHandle notifyObject);
}

Timer ,
. , ,
.
21.

781

,
, .
internal static class TimerDemo {
private static Timer s_timer;
public static void Main() {
Console.WriteLine("Checking status every 2 seconds");
// , . ,
// s_timer,
// Status
s_timer = new Timer(Status, null, Timeout.Infinite, Timeout.Infinite);
// , s_timer ,
// ; , Change Status
// NullReferenceException
s_timer.Change(0, Timeout.Infinite);
Console.ReadLine(); //
}
//
// TimerCallback
private static void Status(Object state) {
//
Console.WriteLine("In Status at {0}", DateTime.Now);
Thread.Sleep(1000); // (1 )
// 2
s_timer.Change(2000, Timeout.Infinite);
// ,
//
}
}


Delay Task C# async await (. 28).
:
internal static class DelayDemo {
public static void Main() {
Console.WriteLine("Checking status every 2 seconds");
Status();
Console.ReadLine(); //
}
//
private static async void Status() {
while (true) {

782

27.

Console.WriteLine("Checking status at {0}", DateTime.Now);


// ...
// 2-
await Task.Delay(2000); // await
}
}
}


FCL ,
, .
Timer System.Threading. . .
Timer System.Windows.Forms. Windows
(.Win32- SetTimer).
Windows
(WM_TIMER).
. ,
, .
.
DispatcherTimer System.Windows.Threading.
Timer System.
Windows.Forms Silverlight WPF.
DispatcherTimer Windows.UI.XAML.
Timer System.Windows.
Forms Windows Store.
Timer System.Timers. ,
, Timer System.Threading.
CLR . System.Timers.Timer
Component System.ComponentModel, Visual Studio.
, ,
Visual Studio. FCL ,
Microsoft .
, , System.Threading.
Timer. System.Timers.Timer

783

(
).


, -.
,
CLR . .
- ,
. , .
, ,
.
, ,
CLR. , .


CLR , . ,
, .
1000 ,
1001. 1000, , ,
.
, .

.
? -
.
- , , CLR
. 1000,
32- , 2 ,
.
Win32 CLR,
1,5 .
(TEB) 1

784

27.

, 32- 1360. OutOfMemoryException.


64- 8 , . , ,
. CLR ,
, ,
.
System.Threading.ThreadPool : GetMaxThreads, SetMaxThreads,
GetMinThreads, SetMinThreads GetAvailableThreads. ,
.
. , , , -
. , , 28.


. 27.1 ,
. ThreadPool.QueueUserWorkItem Timer .
.

,
, ,
. ,
.

( Default
TaskScheduler)1. Task
.
, .
, ,
Task . ,
. .
, ,
, TaskScheduler,
.
1

785

. ,
, .

. 27.1. CLR


, ,
. ,

.

,
. , ,
, , , . ,
.
, ( )
. .
, , (,
, TEB).
, ,
SetMinThreads ThreadPool.
( ), , .
(affinity mask) . -

786

27.

, ,
.
, ,
( ), .
.

28.
-


, , , . -,

. , ,
, .
, ,
-.

- Windows
, Microsoft Windows -. .28.1
.
. ,
, ,
,
.
,
FileStream. Read . Read
FileStream / , Win32
ReadFile (1). ,
- (I/O Request Packet, IRP) (2). , ,
, Byte[], ,
, ..
ReadFile Windows, IRP- (3).
,
-, IRP-

788

28. -

(4).
- . IRP-
, , ,
- (5).

. 28.1. - Windows

:
- , , , Windows ,
(6).
, ,
(Thread Environment Block, TEB) , .

. , , .
- Windows
,
, (7, 8 9).
Read FileStream Int32,
.
, Byte[], Read.

- Windows

789

-,
. .

, .
, , .
, . , -
( ), !
, .
,
, ,
. , .
-
Windows (.28.2). ,
, CLR . - FileStream,
FileOptions.Asynchronous, Windows,
.
BeginRead,
Read. ReadAsync Task<Int32>,
, Win32- ReadFile (1),
IRP-, , (2), Windows (3). Windows IRP- IRP-
(4), ,
BeginRead (5, 6 7). , IRP-, ReadAsync ,
Byte[].
,
? ReadAsync Task<Int32>.
, ContinueWith , ,
. C#,
(
-).
IRP- (a),
CLR- (b). - IRP (c)1. IRP-
.
1

790

28. -

, Byte[]
.

. 28.2. - Windows

, ,
. , . ,
, .
, ,
.
,
. ,
, .
, ,
!
, ,
. . ,
( -

- Windows

791

) -
1.
( -, Thread.Sleep ,
) Windows ,
. . ,
,
.
, ,
,
. , . , ,
, .

. , ,
, ,
.
CLR-
Windows, - (I/OCompletion Port).
CLR. , ,
IRP-. Windows via
C/C++ (Microsoft Press, 2007).
- .
, CLR .
, , .
, CLR . , ,
. , ,

, .
, 100%.
,
. . ,
. , Windows
, ,
.
1

792

28. -

. ,
, .
Windows .
, ,
. -
, .
. , 10.
5. (
) 50.
10
5! -
, , -
.
:
. Silverlight Windows Store
- ,
- ;
.
,
.

C#

,
.
.
, CLR ,
1.
, Microsoft .NET Framework 4.5, AsyncEnumerator ( Power Threading . http://
Wintellect.com/) .NET
Framework 4.5. , AsnycEnumerator Microsoft
, .
, AsyncEnumerator,
.
1

C#

793

Task (. 27) C#.

.
private static async Task<String> IssueClientRequestAsync(String serverName,
String message)
{
using (var pipe = new NamedPipeClientStream(serverName, "PipeName",
PipeDirection.InOut, PipeOptions.Asynchronous | PipeOptions.WriteThrough))
{
pipe.Connect(); // ReadMode,
pipe.ReadMode = PipeTransmissionMode.Message; // Connect
//
Byte[] request = Encoding.UTF8.GetBytes(message);
await pipe.WriteAsync(request, 0, request.Length);
//
Byte[] response = new Byte[1000];
Int32 bytesRead = await pipe.ReadAsync(response, 0, response.Length);
return Encoding.UTF8.GetString(response, 0, bytesRead);
} //
}

, IssueClientRequestAsync , async
static. async,
, (
).
, . , IssueClientRequestAsync
NamedPipeClientStream, Connect, ReadMode, Byte[]
WriteAsync . WriteAsync Task IssueClientRequestAsync. C# await ContinueWith Task ,
,
IssueClientRequestAsync.
. Task,
ContinueWith,
. , IssueClientRequestAsync,
await. , Task.
. ,
await . WriteAsync Task
Task<TResult>, .

794

28. -

Byte[] ReadAsync NamedPipeClientStream.


ReadAsync Task<Int32> .
await ContinueWith Task<Int32> , ,
IssueClientRequestAsync.
, , Task<Int32> , . await
, Result
Task (Int32 ) bytesRead ,
.
IssueClientRequestAsync, .
,
.
, , , Issue
ClientRequestAsync, , IssueClientRequestAsync
await. ,
IssueClientRequestAsync ?
async,
, Task ;
Task . ,
IssueClientRequestAsync Task<String>.
Task<String>, , , Result Task
String. IssueClientRequestAsync .
, ,
Task<String> Result .
:
Main .
, ,
.
out ref.
await catch, finally unsafe.
, , await, await.
, await,
await. await
C# lock .
Enter Exit Monitor, -

795

, Monitor.Exit SynchronizationLockException
.
await
from
join.
. ,
.



, , .
, ,
.
internal sealed class Type1 { }
internal sealed class Type2 { }
private static async Task<Type1> Method1Async()
/* ,
}
private static async Task<Type2> Method2Async()
/* ,
}

{
Type1 */
{
Type2 */

,
.
private static async Task<String> MyMethodAsync(Int32 argument) {
Int32 local = argument;
try {
Type1 result1 = await Method1Async();
for (Int32 x = 0; x < 3; x++) {
Type2 result2 = await Method2Async();
}
}
catch (Exception) {
Console.WriteLine("Catch");
}
finally {
Console.WriteLine("Finally");
}
return "Done";
}

796

28. -

MyMethodAsync , . -,
Task<String>, String. -,
, ,
for. , .
MyMethodAsync
.
, , IL-
C#.
, ,
. , .
MyMethodAsync,
, .
// AsyncStateMachine
// ( , );
// , .
[DebuggerStepThrough, AsyncStateMachine(typeof(StateMachine))]
private static Task<String> MyMethodAsync(Int32 argument) {
//
StateMachine stateMachine = new StateMachine() {
// , Task<String>.
//
// .
m_builder = AsyncTaskMethodBuilder<String>.Create(),
m_state =
1, //
m_argument = argument //
}; //
// .
stateMachine.m_builder.Start(ref stateMachine);
return stateMachine.m_builder.Task; //
} //
//
[CompilerGenerated, StructLayout(LayoutKind.Auto)]
private struct StateMachine : IAsyncStateMachine {
// (Task)
public AsyncTaskMethodBuilder<String> m_builder;
public Int32 m_state;
// :
public Int32 m_argument, m_local, m_x;
public Type1 m_resultType1;
public Type2 m_resultType2;
//
//
//
//

Awaiter.
.
await,
:

797

private TaskAwaiter<Type1> m_awaiterType1;


private TaskAwaiter<Type2> m_awaiterType2;
//
void IAsyncStateMachine.MoveNext() {
String result = null; // Task
// try
//
try {
Boolean executeFinally = true; // 'try'
if (m_state ==
1) { //
//
m_local = m_argument; //
}
// try
try {
TaskAwaiter<Type1> awaiterType1;
TaskAwaiter<Type2> awaiterType2;
switch (m_state) {
case
1: // 'try'
// Method1Async
awaiterType1 = Method1Async().GetAwaiter();
if (!awaiterType1.IsCompleted) {
m_state = 0; // 'Method1Async'
//
m_awaiterType1 = awaiterType1; //
//
// MoveNext
//
m_builder.AwaitUnsafeOnCompleted(ref awaiterType1, ref this);
// OnCompleted
// awaiterType1,
// ContinueWith(t => MoveNext()) Task.
// Task ContinueWith MoveNext
executeFinally = false; //
// 'try'
return; //
} //
// 'Method1Async' .
break;
case 0: // 'Method1Async'
awaiterType1 = m_awaiterType1; //
break; //
case 1: // 'Method2Async'
awaiterType2 = m_awaiterType2; //
goto ForLoopEpilog; //
}
// await 'for'

798

28. -

m_resultType1 = awaiterType1.GetResult(); //
ForLoopPrologue:
m_x = 0; // 'for'
goto ForLoopBody; // 'for'
ForLoopEpilog:
m_resultType2 = awaiterType2.GetResult();
m_x++; // x
// 'for'
ForLoopBody:
if (m_x < 3) { // 'for'
// Method2Async
awaiterType2 = Method2Async().GetAwaiter();
if (!awaiterType2.IsCompleted) {
m_state = 1; // 'Method2Async'
//
m_awaiterType2 = awaiterType2; //
//
// MoveNext
m_builder.AwaitUnsafeOnCompleted(ref awaiterType2, ref this);
executeFinally = false; //
// 'try'
return; //
} //
// 'Method2Async'
goto ForLoopEpilog; // ,
}
}
catch (Exception) {
Console.WriteLine("Catch");
}
finally {
// , 'try',
// 'finally'.
//
// 'try'.
if (executeFinally) {
Console.WriteLine("Finally");
}
}
result = "Done"; // ,
} // .
catch (Exception exception) {
// :
// .
m_builder.SetException(exception);
return;
}
// :

799

m_builder.SetResult(result);

, ,
, . ,
. ,
await,
GetAwaiter. ,
. , GetAwaiter,
(awaiter).
,
IsCompleted. ,
true, . GetResult ,
, ,
.
.
, IsCompleted false.
OnCompleted , MoveNext .
, . ,
Task, ,
MoveNext.
, ,
. GetResult
.
, .


, Task ,
, await
. (Task ) ,
( WhenAll WhenAny Task)
. CancellationToken Task,
await - .
. TaskLogger,
-

800

28. -

. , -
.
public static class TaskLogger {
public enum TaskLogLevel { None, Pending }
public static TaskLogLevel LogLevel { get; set; }
public sealed class TaskLogEntry {
public Task Task { get; internal set; }
public String Tag { get; internal set; }
public DateTime LogTime { get; internal set; }
public String CallerMemberName { get; internal set; }
public String CallerFilePath { get; internal set; }
public Int32 CallerLineNumber { get; internal set; }
public override string ToString() {
return String.Format("LogTime={0}, Tag={1}, Member={2}, File={3}({4})",
LogTime, Tag ?? "(none)", CallerMemberName, CallerFilePath,
CallerLineNumber);
}
}
private static readonly ConcurrentDictionary<Task, TaskLogEntry> s_log =
new ConcurrentDictionary<Task, TaskLogEntry>();
public static IEnumerable<TaskLogEntry> GetLogEntries() { return s_log.Values; }
public static Task<TResult> Log<TResult>(this Task<TResult> task,
String tag = null,
[CallerMemberName] String callerMemberName = null,
[CallerFilePath] String callerFilePath = null,
[CallerLineNumber] Int32 callerLineNumber = 1
) {
return (Task<TResult>)
Log((Task)task, tag, callerMemberName, callerFilePath, callerLineNumber);
}
public static Task Log(this Task task, String tag = null,
[CallerMemberName] String callerMemberName = null,
[CallerFilePath] String callerFilePath = null,
[CallerLineNumber] Int32 callerLineNumber = 1
) {
if (LogLevel == TaskLogLevel.None) return task;
var logEntry = new TaskLogEntry {
Task = task,
LogTime = DateTime.Now,
Tag = tag,
CallerMemberName = callerMemberName,
CallerFilePath = callerFilePath,
CallerLineNumber = callerLineNumber
};
s_log[task] = logEntry;
task.ContinueWith(t => { TaskLogEntry entry;
s_log.TryRemove(t, out entry); },
TaskContinuationOptions.ExecuteSynchronously);
return task;
}
}

801

:
public static async Task Go() {
#if DEBUG
// TaskLogger
// ;
TaskLogger.LogLevel = TaskLogger.TaskLogLevel.Pending;
#endif
// 3 ; TaskLogger
// .
var tasks = new List<Task> {
Task.Delay(2000).Log("2s op"),
Task.Delay(5000).Log("5s op"),
Task.Delay(6000).Log("6s op")
};
try {
// 3 ;
// .
// : WithCancellation - ,
// .
await Task.WhenAll(tasks).
WithCancellation(new CancellationTokenSource(3000).Token);
}
catch (OperationCanceledException) { }
//
//
foreach (var op in TaskLogger.GetLogEntries().OrderBy(tle => tle.LogTime))
Console.WriteLine(op);
}

, :
LogTime=7/16/2012 6:44:31 AM, Tag=6s op, Member=Go,
File=C:\CLR via C#\Code\Ch28
1I
OOps.cs(332)
LogTime=7/16/2012 6:44:31 AM, Tag=5s op, Member=Go,
File=C:\CLR via C#\Code\Ch28
1I
OOps.cs(331)

, Task, : GetAwaiter
, await . ,
Task; ,
GetAwaiter. ,
async- .
public sealed class EventAwaiter<TEventArgs> : INotifyCompletion {
private ConcurrentQueue<TEventArgs> m_events = new ConcurrentQueue<TEventArgs>();
private Action m_continuation;
#region ,
//
// ;
public EventAwaiter<TEventArgs> GetAwaiter() { return this; }

802

28. -

// , -
public Boolean IsCompleted { get { return m_events.Count > 0; } }
// , ;
//
public void OnCompleted(Action continuation) {
Volatile.Write(ref m_continuation, continuation);
}
// ,
// await
public TEventArgs GetResult() {
TEventArgs e;
m_events.TryDequeue(out e);
return e;
}
#endregion
// ,
//
public void EventRaised(Object sender, TEventArgs eventArgs) {
m_events.Enqueue(eventArgs); // EventArgs
// GetResult/await
// ,
Action continuation = Interlocked.Exchange(ref m_continuation, null);
if (continuation != null) continuation(); //
} //
}

EventAwaiter
await .
.
private static async void ShowExceptions() {
var eventAwaiter = new EventAwaiter<FirstChanceExceptionEventArgs>();
AppDomain.CurrentDomain.FirstChanceException += eventAwaiter.EventRaised;
while (true) {
Console.WriteLine("AppDomain exception: {0}",
(await eventAwaiter).Exception.GetType());
}
}

, , , :
public static void Go() {
ShowExceptions();
for (Int32 x = 0; x < 3; x++) {
try {
switch (x) {

803

case 0: throw new InvalidOperationException();


case 1: throw new ObjectDisposedException("");
case 2: throw new ArgumentOutOfRangeException();

}
}
catch { }

Task
Task<Result>, .
void.
, C#
: .
:
void EventHandlerCallback(Object sender, EventArgs e);


- , , . , -
.
void C#
void, await
-.
void,
, Task,
. ,
, void, 1.

async (Main) C# . await Main,


Main
await. , Main, Task
, (-
Main), Main . C#
.
1

804

28. -

FCL
, ,
FCL. ,
Async. FCL
, -,
XxxAsync. 1:
System.IO.Stream ReadAsync,
WriteAsync, FlushAsync CopyToAsync.
System.IO.textReader
ReadAsync, ReadLineAsync, ReadToEndAsync ReadBlockAsync. , System.IO.TextWriter, WriteAsync, Write
LineAsync FlushAsync.
System.Net.Http.HttpClient GetAsync, Get
StreamAsync, GetByteArrayAsync, PostAsync, PutAsync, DeleteAsync .
System.Net.WebRequest ( FileWebRequest,
FtpWebRequest HttpWebRequest) GetRequestStreamAsync
GetResponseAsync.
System.Data.SqlClient.SqlCommand Exe
cuteDbDataReaderAsync , ExecuteNonQueryAsync , ExecuteReaderAsync ,
ExecuteScalarAsync ExecuteXmlReaderAsync.
(, SvcUtil.exe), , XxxAsync.
.NET Framework
, , , BeginXxx EndXxx
IAsyncResult. , XxxAsync
( Task)
. ,
Task.
FCL, ,
XxxAsync, BeginXxx EndXxx.
, Microsoft
WinRT
IAsyncInfo. , .NET Framework , IAsyncInfo Task.
WinRT API 25.
1

FCL

805

. , .
,
BeginXxx/EndXxx Task.
,
. .
private static async void StartServer() {
while (true) {
var pipe = new NamedPipeServerStream(c_pipeName, PipeDirection.InOut,
1,
PipeTransmissionMode.Message, PipeOptions.Asynchronous |
PipeOptions.WriteThrough);
// .
// : NamedPipeServerStream
// .
// Task
// FromAsync TaskFactory.
await Task.Factory.FromAsync(pipe.BeginWaitForConnection,
pipe.EndWaitForConnection, null);
// ; ,
// .
ServiceClientRequestAsync(pipe);
}
}

NamedPipeServerStream BeginWaitForConnection
EndWaitForConnection, WaitForConnectionAsync.
, FCL. ,
, FromAsync TaskScheduler,
BeginXxx EndXxx, FromAsync
Task, . Task
await1.
FCL , Task,
. , WebClient ( )
TaskCompletionSource, await
.
private static async Task<String> AwaitWebClient(Uri uri) {
// System.Net.WebClient

FromAsync TaskScheduler ,
IAsyncResult, , BeginXxx
EndXxx. IAsyncResult,
.
1

806

28. -

//
var wc = new System.Net.WebClient();
// TaskCompletionSource Task
var tcs = new TaskCompletionSource<String>();
// WebClient
// DownloadStringCompleted, TaskCompletionSource
wc.DownloadStringCompleted += (s, e) => {
if (e.Cancelled) tcs.SetCanceled();
else if (e.Error != null) tcs.SetException(e.Error);
else tcs.SetResult(e.Result);
};
//
wc.DownloadStringAsync(uri);
// Task TaskCompletionSource
// .
String result = await tcs.Task;
// ( )...
}

return result;


-
, Windows . , , -.
, ,
. IRP- CLR- , Task .
await ,
, .
27 , Task
AggregateException, InnerExceptions . await Task AggregateException
1. ,
. ,
AggregateException , , . .

: GetResult TaskAwaiter.

807

, Task, , -
. ,
Task, .
void;
. ,
, void,

(. ). , .
.


. Microsoft Visual Studio
. await,
(F10)
.
, , !
.
, (F11)
, (Shift+F11); ,
.
Shift+F11 ,
.
, ,
(F5).
, , ,
.
, ; .
, , await,
.
, ,
.
, , , ,
.
, .
,

808

28. -

. ,
,
Run Task:
// Task.Run
Task.Run(async () => {
//
// TODO: ...
await XxxAsync(); //
// ...
});

C#:
-. , awat
-,
. async - - ,
Task Task<TResult>,
Func Task Task<TResult>.
async, await:
static async Task OuterAsyncFunction() {
InnerAsyncFunction(); // await!
// , InnerAsyncFunction...
}
static async Task InnerAsyncFunction() { /* ... */ }

, C# await . ,
, InnerAsyncFunction,
.
, Task, InnerAsyncFunction. 1.
static async Task OuterAsyncFunction() {
var noWarning = InnerAsyncFunction(); // await
// , InnerAsyncFunction...
}

, :
[MethodImpl(MethodImplOptions.AggressiveInlining)] //
//
public static void NoWarning(this Task task) { /* */ }

, ,
.
1

809

:
static async Task OuterAsyncFunction() {
InnerAsyncFunction().NoWarning(); // await
// , InnerAsyncFunction...
}

-
: , . . ,
, .
:
public static async Task Go() {
// ,
//
StartServer(); // void,
// ;
// Task<String> .
List<Task<String>> requests = new List<Task<String>>(10000);
for (Int32 n = 0; n < requests.Capacity; n++)
requests.Add(IssueClientRequestAsync("localhost", "Request #" + n));
//
// : 1+ ,
// WhenAll
String[] responses = await Task.WhenAll(requests);
//
for (Int32 n = 0; n < responses.Length; n++)
Console.WriteLine(responses[n]);
}

,
, for 10000 . IssueClientRequestAsync
Task<String>, ,

, , 1. ,
, Task<String>
, .
: ,
8- , , 100%. , , !
, .
1

810

28. -


, .
WhenAll Task.
Task<String[]>,
Task List. await Task<String[]>, . (
Console.WriteLine).
,
, .
WhenAny Task.
:
public static async Task Go() {
// ,
//
StartServer();
// ;
// Task<String> .
List<Task<String>> requests = new List<Task<String>>(10000);
for (Int32 n = 0; n < requests.Capacity; n++)
requests.Add(IssueClientRequestAsync("localhost", "Request #" + n));
//
while (requests.Count > 0) {
//
Task<String> response = await Task.WhenAny(requests);
requests.Remove(response); //
//
Console.WriteLine(response.Result);
}
}

while, .
await WhenAny Task,
Task<String> , .
Task<String> ,
( Console.WriteLine).


.NET Framework ,
. Windows- (

811

, )
; , .
(GUI),
Windows Forms, Windows Presentation Foundation (WPF),
Silverlight Windows Store, ,
. GUI-
,
, , , .
Task, .
,
. (,
) ,
. -
.
ASP.NET , .
,
(System.Globalization.CultureInfo),
, 1.
- (System.
Security.Principal.IPrincipal), ,
. , .
,
,
, ,
.
, FCL System.Threading.Synchronization
Context, . ,
, . FCL
, SynchronizationContext,
; , .
SynchronizationContext. await Task
SynchronizationContext .
Task, SynchronizationContext,
. , GUI-
await Task, , await,
GUI-,
http://msdn.microsoft.
com/ru-ru/library/bz9tc508.aspx.
1

812

28. -

. ASP.NET , await, ,
.
. ,
.
WPF:
private sealed class MyWpfWindow : Window {
public MyWpfWindow() { Title = "WPF Window"; }
protected override void OnActivated(EventArgs e) {
// Result GUI- ;
//
String http = GetHttp().Result; //
}

base.OnActivated(e);

private async Task<String> GetHttp() {


// HTTP GetHttp
HttpResponseMessage msg = await new
HttpClient().GetAsync("http://Wintellect.com/");
// : GUI-
// , , GUI-
//
> !

return await msg.Content.ReadAsStringAsync();

, , SynchronizationContext.
, . , , SynchronizationContext.
, ,
.
Task Task<TResult>
ConfigureAwait :
// Task :
public ConfiguredTaskAwaitable
ConfigureAwait(Boolean continueOnCapturedContext);
// Task<TResult> :
public ConfiguredTaskAwaitable<TResult>
ConfigureAwait(Boolean continueOnCapturedContext);

true , . false, await

813

SynchronizationContext , Task,
await .
GetHttp ,
ConfigureAwait.
GetHttp :
private async Task<String> GetHttp() {
// HTTP GetHttp
HttpResponseMessage msg = await new
HttpClient().GetAsync("http://Wintellect.com/")
.ConfigureAwait(false);
// ,
// ( GUI-).
}

return await msg.Content.ReadAsStringAsync().ConfigureAwait(false);

, ConfigureAwait(false)
Task, await. ,
, ,
; ,
SynchronizationContext,
. ,
.
GetHttp , , :
private Task<String> GetHttp() {
return Task.Run(async () => {
// ,
// SynchronizationContext
HttpResponseMessage msg = await new
HttpClient().GetAsync("http://Wintellect.com/");
return await msg.Content.ReadAsStringAsync();
});
}

: GetHttp
; async ,
await. , -, Task.Run, .


,
.NET Framework,

814

28. -

.
, ,
, MSDN.
Web Forms ASP.NET:
.aspx Async=true page
RegisterAsyncTask System.Web.UI.Page.
MVC- ASP.NET:
System.Web.Mvc.AsyncController
Task<ActionResult> .
ASP.NET:
System.Web.HttpTaskAsyncHandler
ProcessRequestAsync.
WCF:
, Task Task<TResult>.

-
Windows -. ,
. ,
, , ;
. ,
, .
?
, , .

WithCancellation, Task<TResult> (
, Task) :
private struct Void { } // -
// TaskCompletionSource.
private static async Task<TResult>
WithCancellation<TResult>(this Task<TResult> originalTask,
CancellationToken ct) {
// Task, CancellationToken
var cancelTask = new TaskCompletionSource<Void>();
// CancellationToken Task
using (ct.Register(

815

t => ((TaskCompletionSource<Void>)t).TrySetResult(new Void()),


cancelTask)) {
// Task,
// Task Task CancellationToken
Task any = await Task.WhenAny(originalTask, cancelTask.Task);
// - Task - CancellationToken,
// OperationCanceledException
if (any == cancelTask.Task) ct.ThrowIfCancellationRequested();
}
// await (); awaiting it
// ,
// AggregateException
return await originalTask;
}

:
public static async Task Go() {
// CancellationTokenSource,
//
var cts = new CancellationTokenSource(5000); // ,
var ct = cts.Token; // cts.Cancel()
try {
// Task.Delay ; ,
// Task
await Task.Delay(10000).WithCancellation(ct);
Console.WriteLine("Task completed");
}
catch (OperationCanceledException) {
Console.WriteLine("Task cancelled");
}
}

Win32 API , -. , . ,
Win32- CreateFile ( FileStream) . CreateFile
. ,
, Win32-,
, . , Win32 , CreateFile, , , FCL
. Windows

816

28. -

, ,
/, / ..
, .
,
( ). ,
, Windows .
,
,
. Windows Vista Win32- CancelSynchronousIO.
-, . FCL,
, P/Invoke.
P/Invoke .
,
, .
.
- , -, Windows Runtime Windows
/ . ,
Windows Runtime API (.
OpenAsync Windows.Storage.StorageFile). Windows Runtime
API /. ,
C# .

FileStream
FileStream FileOptions.Asynchronous ,
( Win32- CreateFile
FILE_FLAG_OVERLAPPED). Windows
. ,
ReadAsync FileStream.
, FileStream
,
.
FileStream, FileOptions.
Asynchronous. Read FileStream
. FileStream ,
. ,

817

, BeginRead FileStream,
FileOptions.Asynchronous.
. FileStream ,
- ,
FileOptions.Asynchronous ( ). ,
ReadAsync, Read.
.
FileStream, FileOptions.Asynchronous.
FileStream . FileStream
-, . ,
System.IO.File (Create, Open OpenWrite),
FileStream.
FileOptions.Asynchronous,

.
, NTFS
.
http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B156932.

-
26 ,
. - . ,
.
, ,
, .

, ,
, ..1
Windows . http://www.
microsoft.com/whdc/driver/priorityio.mspx. ,
FCL; , .
P/Invoking. :
Windows- SuperFetch -
.
1

818

28. -

internal static class ThreadIO {


public static BackgroundProcessingDisposer BeginBackgroundProcessing(
Boolean process = false) {
ChangeBackgroundProcessing(process, true);
return new BackgroundProcessingDisposer(process);
}
public static void EndBackgroundProcessing(Boolean process = false) {
ChangeBackgroundProcessing(process, false);
}
private static void ChangeBackgroundProcessing(
Boolean process, Boolean start) {
Boolean ok =
process ? SetPriorityClass(GetCurrentWin32ProcessHandle(),
start ? ProcessBackgroundMode.Start : ProcessBackgroundMode.End)
: SetThreadPriority(GetCurrentWin32ThreadHandle(),
start ? ThreadBackgroundgMode.Start : ThreadBackgroundgMode.End);
if (!ok) throw new Win32Exception();
}
// using
//
public struct BackgroundProcessingDisposer : IDisposable {
private readonly Boolean m_process;
public BackgroundProcessingDisposer(
Boolean process) { m_process = process; }
public void Dispose() { EndBackgroundProcessing(m_process); }
}
// . Win32- THREAD_MODE_BACKGROUND_BEGIN
// THREAD_MODE_BACKGROUND_END
private enum ThreadBackgroundgMode { Start = 0x10000, End = 0x20000 }
// . Win32- PROCESS_MODE_BACKGROUND_BEGIN
// PROCESS_MODE_BACKGROUND_END
private enum ProcessBackgroundMode { Start = 0x100000, End = 0x200000 }
[DllImport("Kernel32", EntryPoint = "GetCurrentProcess",
ExactSpelling = true)]
private static extern SafeWaitHandle GetCurrentWin32ProcessHandle();
[DllImport("Kernel32", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean SetPriorityClass(
SafeWaitHandle hprocess, ProcessBackgroundMode mode);
[DllImport(
"Kernel32", EntryPoint = "GetCurrentThread", ExactSpelling = true)]
private static extern SafeWaitHandle GetCurrentWin32ThreadHandle();
[DllImport("Kernel32", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean SetThreadPriority(

819

SafeWaitHandle hthread, ThreadBackgroundgMode mode);


// http://msdn.microsoft.com/en-us/library/aa480216.aspx
[DllImport(
"Kernel32", SetLastError = true, EntryPoint = "CancelSynchronousIo")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean CancelSynchronousIO(SafeWaitHandle hThread);
}

, :
public static void Main () {
using (ThreadIO.BeginBackgroundProcessing()) {
// -
// (, BeginRead/BeginWrite)
}
}

Windows, - BeginBackgroundProcessing ThreadIO.


,
. - ( )
EndBackgroundProcessing Dispose , BeginBackgroundProcessing ( using
C#, ).
; Windows
.

- ,
BeginBackgroundProcessing, true
process.
; Windows
.

, ,
. - , ,
- .

, ,
.
-.
( ). , -
, .

29.

, ;
( ) , . ,
, ,
- . ,
. 27
, ,
28 -.
.
. ,
.
, , . 28 ,
. ,
.
, ,
, ,
.
,
. -,
. ,
. ,
. ,
.
,
. ,
. , , .
-

821

, ,
,
.
.
,
,
, , .
.
, , :
// LinkedList
public class Node {
internal Node m_next;
//
}
public sealed class LinkedList {
private Node m_head;
public void Add(Node newNode) {
//
newNode.m_next = m_head;
m_head = newNode;
}
}

Add .
,
,
Add :
public sealed class LinkedList {
private SomeKindOfLock m_lock = new SomeKindOfLock();
private Node m_head;
public void Add(Node newNode) {
m_lock.Acquire();
//
newNode.m_next = m_head;
m_head = newNode;
m_lock.Release();
}
}

Add , .
;
, . Add
. , Add

822

29.


.
, . ,
, , ,
.
, ,
. 26,
. ,
;
, ,
, , , , .
, ,
,
. , .
new,
. ,
. ,
, ,
.
,
, . ,
,
, . , . , ;
,
, , .
String. , ,
.


. FCL Microsoft
. ,
.
FCL,
, .

823

Console ,
, ,
.
, , , ,
.

. System.Math
Max, :
public static Int32 Max(Int32 val1, Int32 val2) {
return (val1 < val2) ? val2 : val1;
}

, . Int32 ,
Max , , .
, .
FCL ,
. ,
, , ,
. , ,
, , .
, ,
. (
, ThreadPool.
QueueUserWorkItem Task ..), ,
.

, . , , ,
. ,
, Cancel CancellationTokenSource, , IsCancellationRequested
CancellationToken, , .
,
1.
, , volatile,
.
1

824

29.

. ,
. : .
,
. (
). ,
Windows .
,
. ,
.
, ? , ,
. ,
. Windows
, .

, . ,
, , .
,
.
.
Windows
, . ,
1.
.
, , Windows , . ,
, , .
, , ,
.
;
() (livelock),

, .

825

. ,
() (deadlock). -
, , , ,
( ..), 1.
,
: ( ) . , .
,
(hybrid constructs), .
,
.
, . ,
.
CLR - ,
Win32. , CLR-
Windows, . 1992
2, .


CLR : Boolean,
Char, (S)Byte, (U)Int16, (U)Int32, (U)IntPtr, Single . , . , :
internal static class SomeType {
public static Int32 x = 0;
}

- , x
() 0x00000000 0x01234567:
SomeType.x = 0x01234567;

, ,
.
2
Windows via C/C++ (Microsoft Press, 2007) .
1

826

29.

. , SomeType.x 0x01230000. , x SomeType


Int64. , x 0x0123456700000000
0x0000000089abcdef, :
SomeType.x = 0x0123456789abcdef;

(torn read).
, , -
, .
, ,
. ,

U(Int64) Double.

:
Volatile- ,
, .
Interlocked- , , .
( ) , .

Volatile-
, . ,
: ,
, ..
.
if/else, switch/case, , ,
, , .
, , .
, C# C# (Intermediate Language, IL), , ,
JIT- , . C#, JIT-
. , :

827

private static void OptimizedAway() {


//
Int32 value = (1 * 100) (50 * 2);
// 0,
for (Int32 x = 0; x < value; x++) {
// ,
Console.WriteLine("Jeff");
}
}

, 0, ,

. . ,
, OptimizedAway, JIT-
OptimizedAway, ,
. . ;
, .
, . ,
.
C#, JIT- .
, , .
. ,
, :
internal static class StrangeBehavior {
// , volatile
private static Boolean s_stopWorker = false;
public static void Main() {
Console.WriteLine("Main: letting worker run for 5 seconds");
Thread t = new Thread(Worker);
t.Start();
Thread.Sleep(5000);
s_stopWorker = true;
Console.WriteLine("Main: waiting for worker to stop");
t.Join();
}
private static void Worker(Object o) {
Int32 x = 0;
while (!s_stopWorker) x++;
Console.WriteLine("Worker: stopped when x={0}", x);
}
}

828

29.

Main ,
Worker, , .
Main Worker 5, , Boolean true.
Worker , .
Main Worker, Join, Main , .

, ?
- . Worker , s_stopWorker true false,
.
, s_stopWorker.
true, "Worker: stopped when x=0". ,
x.
, s_stopWorker
, .
, , .cs platform:x86 /optimize+ C#.
,
. , JIT-
x86, x64 IA64, ,
. JIT
, .
:
, , JIT-, ,
. , ,
, JIT- , .
,
:
internal sealed class ThreadsSharingData {
private Int32 m_flag = 0;
private Int32 m_value = 0;
//
public void Thread1() {
// .
m_value = 5;
m_flag = 1;
}
//

829

public void Thread2() {


// . m_value , m_flag
if (m_flag == 1)
Console.WriteLine(m_value);
}
}

, , Thread1 .
, . 5 m_value 1 m_flag.
.
, ,
Thread2, , m_flag 1,
0.
. ,
Thread1 , ( , ). Thread2, ,
m_flag m_value . ,
m_value, 0. Thread1,
m_value 5, m_flag 1. Thread2 , m_value
5.
m_flag, 1.
Thread2 0.
, , , .
.
, .
System.Threading.Volatile ,
1:
public sealed class Volatile {
public static void Write(ref Int32 location, Int32 value);
public static Int32 Read(ref Int32 location);
}

, ,
C#, JIT- .
:
VolatileRead VolatileWrite, : Boolean, (S)Byte, (U)Int16, UInt32, (U)Int64, (U)IntPtr, Single, Double
T, T 'class' ( ).
1

830

29.

Volatile.Write location . .
Volatile.Read address .
.

, :
Volatile.
Write, Volatile.Read.

ThreadsSharing

Data:

internal sealed class ThreadsSharingData {


private Int32 m_flag = 0;
private Int32 m_value = 0;
//
public void Thread1() {
// . 5 m_value 1 m_flag
m_value = 5;
Volatile.Write(ref m_flag, 1);
}
//
public void Thread2() {
// . m_value m_flag
if (Volatile.Read(ref m_flag) == 1)
Console.WriteLine(m_value);
}
}

. Thread1 , .
, ( m_flag 1),
Volatile.Write. Thread2 , (m_flag)
Volatile.Read.
? Thread1
Volatile.Write , 1 m_flag. m_value = 5
Volatile.Write, . ,
Volatile.
Write, 1

831

m_flag. ,
; , Volatile.Write.
Volatile.Read Thread2 ,
m_flag.
m_value Volatile.Read,
m_flag.
,
Volatile.Read. Volatile.Read
, ; Volatile.Read.

Volatile C#
, Volatile.
Read Volatile.Write ? , ,
.
C# volatile,
Boolean, (S)Byte, (U)Int16, (U)Int32,
(U)IntPtr, Single Char.
, (S)Byte, (U)Int16
(U)Int32. JIT- , ,
, ,
Read Write Volatile
. , volatile C# JIT- .
,
.
volatile ThreadsSharingData
:
internal sealed class ThreadsSharingData {
private volatile Int32 m_flag = 0;
private
Int32 m_value = 0;
//
public void Thread1() {
// . 5 m_value
// 1 m_flag
m_value = 5;
m_flag = 1;
}
//
public void Thread2() {
// . m_value m_flag
if (m_flag == 1)
Console.WriteLine(m_value);
}
}

832

29.

( ) volatile
, C#1. , .
, . ,
volatile, . , ,
:
m_amount = m_amount + m_amount; // , m_amount
// volatile


,
. m_amount volatile, . ,
m_amount , ,
m_amount.
; .
C# .
, Int32 m_amount
Int32.TryParse, :
Boolean success = Int32.TryParse("123", out m_amount);
// :
// CS0420:

, volatile CLS,
( Visual Basic).

Interlocked-
, Read Volatile
, Write .
, .
System.Threading.Interlocked.
, .
, Interlocked ,
Interlocked
, .
, Int32,
. :
public static class Interlocked {
// (++location)

, Microsoft Visual Basic volatile.

833

public static Int32 Increment(ref Int32 location);


// (--location)
public static Int32 Decrement(ref Int32 location);
// (location += value)
// . ,
//
public static Int32 Add(ref Int32 location, Int32 value);
// Int32 old = location; location = value; old;
public static Int32 Exchange(ref Int32 location, Int32 value);
// Int32 old = location1;
// (location1 == comparand) location = value;
// old;
public static Int32 CompareExchange(ref Int32 location,
Int32 value, Int32 comparand);
...
}

, Int64. , Interlocked Exchange


CompareExchange, Object, IntPtr, Single Double.
, class
( ).
Interlocked -,
. ,

-. , ,

, . , , ,
2147483647 (Int32.MaxValue). ,
.
internal sealed class MultiWebRequests {
// Helper
private AsyncCoordinator m_ac = new AsyncCoordinator();
// -,
// ,
// ,
//
private Dictionary<String, Object> m_servers = new Dictionary<String, Object> {
{ "http://Wintellect.com/", null },
{ "http://Microsoft.com/", null },
{ "http://1.1.1.1/", null }
};
public MultiWebRequests(Int32 timeout = Timeout.Infinite) {

834

29.

//
var httpClient = new HttpClient();
foreach (var server in m_servers.Keys) {
m_ac.AboutToBegin(1);
httpClient.GetByteArrayAsync(server)
.ContinueWith(task => ComputeResult(server, task));
}
// AsyncCoordinator,
// AllDone ,
// Cancel -
m_ac.AllBegun(AllDone, timeout);
}
private void ComputeResult(String server, Task<Byte[]> task) {
Object result;
if (task.Exception != null) {
result = task.Exception.InnerException;
} else {
// - - (-)
// ...
result = task.Result.Length; //
} //
// (/)
//
m_servers[server] = result;
m_ac.JustEnded();
}
//
public void Cancel() { m_ac.Cancel(); }
// -,
// Cancel -
private void AllDone(CoordinationStatus status) {
switch (status) {
case CoordinationStatus.Cancel:
Console.WriteLine("Operation canceled.");
break;
case CoordinationStatus.Timeout:
Console.WriteLine("Operation timed
out.");
break;
case CoordinationStatus.AllDone:
Console.WriteLine("Operation completed; results below:");
foreach (var server in m_servers) {
Console.Write("{0} ", server.Key);
Object result = server.Value;
if (result is Exception) {
Console.WriteLine("failed due to {0}.", result.GetType().Name);
} else {

835

Console.WriteLine("returned {0:N0} bytes.", result);

}
break;

Interlocked-, AsyncCoordinator.
, , .
MultiWebRequest AsyncCoordinator
URI ( ).
-. AboutToBegin AsyncCoordinator,
1.
GetByteArrayAsync HttpClient.
Task, ContinueWith,

ComputeResult . AllBegun AsyncCoordinator,
, (AllDone),
-, -.
ComputeResult MultiWebRequests.
, ( ), .
JustEnded AsyncCoordinator, AsyncCoordinator
.
AsyncCoordinator
AllDone , -.
, .
AllDone
, AsyncCoordinator ,
, , Cancel. , , , AllDone,
AllBegin.
, , , AllBegun,
Cancel. , AsyncCoordinator , , AllDone
. AllDone
, ,
CoordinationStatus:
internal enum CoordinationStatus { AllDone, Timeout, Cancel };

, m_ac.AboutToBeging(m_requests.
Length) AboutToBegin .
1

836

29.

, , , ,
. AsyncCoordinator . Interlocked,
. :
internal sealed class AsyncCoordinator {
private Int32 m_opCount = 1; // 1 AllBegun
private Int32 m_statusReported = 0; // 0=false, 1=true
private Action<CoordinationStatus> m_callback;
private Timer m_timer;
//
public void AboutToBegin(Int32 opsToAdd = 1) {
Interlocked.Add(ref m_opCount, opsToAdd);
}
//
public void JustEnded() {
if (Interlocked.Decrement(ref m_opCount) == 0)
ReportStatus(CoordinationStatus.AllDone);
}
//
public void AllBegun(Action<CoordinationStatus> callback,
Int32 timeout = Timeout.Infinite) {
m_callback = callback;
if (timeout != Timeout.Infinite)
m_timer = new Timer(TimeExpired, null, timeout, Timeout.Infinite);
JustEnded();
}
private void TimeExpired(Object o) {
ReportStatus(CoordinationStatus.Timeout);
}
public void Cancel() { ReportStatus(CoordinationStatus.Cancel); }
private void ReportStatus(CoordinationStatus status) {
// , ;
//
if (Interlocked.Exchange(ref m_statusReported, 1) == 0)
m_callback(status);
}
}

m_opCount.
, .
AboutToBegin. Interlocked.
Add, m_opCount .
, -
.

837

JustEnded. Interlocked.Decrement
m_opCount . , m_opCount 0, ReportStatus.

m_opCount 1 ( 0); ,
, AllDone , . AllBegun
m_opCount 0.
AllBegun, , JustEnded,
m_opCount 1
1. m_opCount
0,
-.

ReportStatus , ,
Cancel. , , m_callback
. Interlocked.Exchange
m_statusReported. Boolean;
, Interlocked Boolean. Int32,
0 false, 1 true.
ReportStatus Interlocked.Exchange
m_statusReported 1.
, Interlocked.Exchange 0,
. ,
Interlocked.Exchange, 1, , ,
.


Interlocked- , Int32.

,
?
, . Interlocked- :
internal struct SimpleSpinLock {
private Int32 m_ResourceInUse; // 0=false ( ), 1=true
public void Enter() {
while (true) {
// , .

838

29.

//
//
if
//
}
}

,

(Interlocked.Exchange(ref m_ResourceInUse, 1) == 0) return;
- ...

public void Leave() {


// ,
Volatile.Write(ref m_ResourceInUse, 0);
}
}

, SimpleSpinLock:
public sealed class SomeResource {
private SimpleSpinLock m_sl = new SimpleSpinLock();
public void AccessResource() {
m_sl.Enter();
// ...
m_sl.Leave();
}
}

SimpleSpinLock .
Enter, Interlocked.Exchange ,
m_resourceInUse 0 1. , m_resourceInUse 0, Enter ,
AccessResource.
m_resourceInUse 1.
, 0, ,
Exchange , Leave.

SomeResource, Leave, , ,
Volatile.Write m_resourceInUse 0.
m_resourceInUse 0 1 ,
, Enter,
SomeResource.
.
. , ,
,
. ,
.

, - . , ,

839

, , ,
. , . Windows . ,
, .
PriorityBoostEnabled System.Diagnostics.Process System.
Diagnostics.ProcessThread.
. .
, .
, FCL System.Threading.SpinWait,
.

, ,
, ,
, . SpinWait
Sleep, Yield SpinWait Thread.
.
,
. Sleep:
public static void Sleep(Int32 millisecondsTimeout);
public static void Sleep(TimeSpan timeout);

Sleep -

. .
, 100,
,
. , Windows
. , , ,
.
millisecondsTimeout Sleep
System.Threading.Timeout.Infinite ( 1).
. , .
Sleep 0 ,
. ,
,
Sleep.

840

29.

Windows
, Yield Thread:
public static Boolean Yield();

, ,
true, , .
Yield . ,
, Yield false,
.
Yield
. ,
, . , Windows
, . ,
Yield ,
.
Thread.Sleep(0) Thread.Sleep(1).
,
Thread.Sleep(1) ,
Windows 1,
.

. , ,
. , , SpinWait Thread:
public static void SpinWait(Int32 iterations);

,
. Windows - (
, ).
,
.

, Win32: Sleep, SwitchToThread YieldProcessor.


Win32 timeBeginPeriod timeEndPeriod.

841

FCL System.Threading.SpinLock ,
SimpleSpinLock.
SpinWait . SpinLock
. ,
SimpleSpinLock SpinLock FCL .
, .
SpinLock , , ,
.
, SpinLock ,
, - .
SpinLock,
(readonly),
.

Interlocked-
, Interlocked-, , Microsoft ,
. , Interlocked
Multiple, Divide, Minimum, Maximum, And, Or, Xor
. ,
Interlocked.CompareExchange
Int32.
Int64, Single, Double, Object,
, .
Maximum:
public static Int32 Maximum(ref Int32 target, Int32 value) {
Int32 currentVal = target, startVal, desiredVal;
// target ,
//
do {
//
startVal = currentVal;
// startVal value
desiredVal = Math.Max(startVal, value);
// . !
// if (target == startVal) target = desiredVal
// ,
currentVal = Interlocked.CompareExchange(
ref target, desiredVal, startVal);
// ,
} while (startVal != currentVal);

842

29.

// ,
return desiredVal;
}

, . ,
, currentVal
target.
startVal.
.
. ,
desiredVal.
startVal value.
, target
. , . ,
derivedVal startVal, target, ,
. ,
target desiredVal ,
,
Interlocked.CompareExchange. ,
target startVal ( target ).
target , CompareExchange
desiredVal. , CompareExchange
target.
CompareExchange target
, currentVal. startVal currentVal.
target ,
desiredVal, while ,
. , ,
target,
desiredVal,
currentVal,
, .
Morph1:
delegate Int32 Morpher<TResult, TArgument>(
Int32 startValue, TArgument argument,
out TResult morphResult);

, - morpher Morph . , (inline),


Maximum.
1

843

static TResult Morph<TResult, TArgument>(


ref Int32 target, TArgument argument,
Morpher<TResult, TArgument> morpher) {
TResult morphResult;
Int32 currentVal = target, startVal, desiredVal;
do {
startVal = currentVal;
desiredVal = morpher(startVal, argument, out morphResult);
currentVal = Interlocked.CompareExchange(
ref target, desiredVal, startVal);
} while (startVal != currentVal);
return morphResult;
}


Windows
. ,
. ,

, ,
. .
, :
, Windows
, , .
.
, .
, .
,
.
, ;
,
.
(events) (semaphores).

844

29.

,
(mutex). Windows via
C/C++ (Microsoft Press, 2007).
System.Threading
WaitHandle. Windows. FCL .
System.Threading MSCorLib.dll.
Semaphore, System.dll. :
WaitHandle
EventWaitHandle
AutoResetEvent
ManualResetEvent
Semaphore
Mutex

WaitHandle SafeWaitHandle, Win32. , WaitHandle. , WaitHandle


, . .
WaitHandle (
):
public abstract class WaitHandle : MarshalByRefObject, IDisposable {
// WaitOne Win32 WaitForSingleObjectEx.
public virtual Boolean WaitOne();
public virtual Boolean WaitOne(Int32 millisecondsTimeout);
public virtual Boolean WaitOne(TimeSpan timeout);
// WaitAll Win32 WaitForMultipleObjectsEx
public static Boolean WaitAll(WaitHandle[] waitHandles);
public static Boolean WaitAll(WaitHandle[] waitHandles,
Int32 millisecondsTimeout);
public static Boolean WaitAll(WaitHandle[] waitHandles, TimeSpan timeout);
// WaitAny Win32 WaitForMultipleObjectsEx
public static Int32 WaitAny(WaitHandle[] waitHandles);
public static Int32 WaitAny(WaitHandle[] waitHandles,
Int32 millisecondsTimeout);
public static Int32 WaitAny(WaitHandle[] waitHandles, TimeSpan timeout);
public const Int32 WaitTimeout = 258; // WaitAny
// -
// Dispose Win32
// CloseHandle !
public void Dispose();
}

845

:
WaitOne WaitHandle
. Win32- WaitForSingleObjectEx.
true , .
, false.
WaitAll WaitHandle
, WaitHandle[].
, true,
false.
Win32- WaitForMultipleObjectsEx,
bWaitAll TRUE.
WaitAny WaitHandle
,
WaitHandle[] . Int32 .
, WaitHandle.WaitTimeout.
Win32- WaitForMultipleObjectsEx,
bWaitAll FALSE.
Dispose .
Win32 CloseHandle. Dispose
, ,
. ,
Dispose; .
, , .

(apartment)
. , Windows-,
. COM. . , .
29, ,
.

WaitOne, WaitAll SignalAndWait, timeout, void, Boolean.


true - (System.Threading.Timeout.Infinite).

846

29.


.
, AutoResetEvent, ManualResetEvent, Semaphore
Mutex WaitHandle,
. , , .
-, Win32-
CreateEvent ( bManualReset FALSE), CreateEvent
( bManualReset TRUE ), CreateSemaphore
CreateMutex. , ,
SafeWaitHandle, WaitHandle.
-, EventWaitHandle, Semaphore Mutex
OpenExisting, Win32- OpenEvent, OpenSemaphore
OpenMutex, String .
, ,
, OpenExisting.
WaitHandleCannotBeOpenedExcep
tion.
, .
Microsoft Office Outlook, Windows Live
Messenger, Windows Media Player Windows Media Center.
:
using System;
using System.Threading;
public static class Program {
public static void Main() {
Boolean createdNew;
//
using (new Semaphore(0, 1, "SomeUniqueStringIdentifyingMyApp",
out createdNew)) {
if (createdNew) {
// ,
// . ...
} else {
// ;
// .
// , Main,
//
}
}
}
}

847

Semaphore,
EventWaitHandle Mutex, .
. ,
. ,
. , Semaphore ( SomeUniqueStringIdentifyingMyApp). Windows
; createdNew
true.
Windows ,
; ,
. , ,
, .
.
, createdNew
false. , ,
.

(events) Boolean,
. ,
false, true. . true,
,
false. true
, ,
false ,
. , :
public class EventWaitHandle
public Boolean Set(); //
//
public Boolean Reset(); //
//
}

: WaitHandle {
Boolean true;
true
Boolean false;
true

public sealed class AutoResetEvent : EventWaitHandle {


public AutoResetEvent(Boolean initialState);
}
public sealed class ManualResetEvent : EventWaitHandle {
public ManualResetEvent(Boolean initialState);
}

848

29.


,
SimpleSpinLock:
internal sealed class SimpleWaitLock : IDisposable {
private readonly AutoResetEvent m_available;
public SimpleWaitLock() {
m_available = new AutoResetEvent(true); //
}
public void Enter() {
//
m_available.WaitOne();
}
public void Leave() {
//
m_available.Set();
}
}

public void Dispose() { m_available.Dispose(); }

SimpleWaitLock ,
SimpleSpinLock. , ; -

.
SimpleWaitLock
SimpleSpinLock, Enter
Leave .

, . ,
AutoResetEvent Dispose,
. , ,
.
, :
public static void Main() {
Int32 x = 0;
const Int32 iterations = 10000000; // 10
// x 10 ?
Stopwatch sw = Stopwatch.StartNew();
for (Int32 i = 0; i < iterations; i++) {
x++;
}
Console.WriteLine("Incrementing x: {0:N0}", sw.ElapsedMilliseconds);
// x 10 ,

849

// ?
sw.Restart();
for (Int32 i = 0; i < iterations; i++) {
M(); x++; M();
}
Console.WriteLine("Incrementing x in M: {0:N0}", sw.ElapsedMilliseconds);
// x 10 ,
// SimpleSpinLock?
SpinLock sl = new SpinLock(false);
sw.Restart();
for (Int32 i = 0; i < iterations; i++) {
Boolean taken = false; sl.Enter(ref taken); x++; sl.Exit();
}
Console.WriteLine("Incrementing x in SpinLock: {0:N0}",
sw.ElapsedMilliseconds);
// x 10 ,
// SimpleWaitLock?
using (SimpleWaitLock swl = new SimpleWaitLock()) {
sw.Restart();
for (Int32 i = 0; i < iterations; i++) {
swl.Enter(); x++; swl.Leave();
}
Console.WriteLine(
"Incrementing x in SimpleWaitLock: {0:N0}", sw.ElapsedMilliseconds);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void M() { /* */ }

, :
Incrementing
Incrementing
Incrementing
Incrementing

x: 8
x in M: 69 ~9
x in SpinLock: 164 ~21
x in SimpleWaitLock: 8,854 ~1107

, x 8.
9 ! , ,
21 (164/8) . ,
.
1107 (8854/8) ! , . ,
. .

850

29.

(semaphores) Int32,
. 0
0.
.
Int32, .
Semaphore:
public sealed class Semaphore : WaitHandle {
public Semaphore(Int32 initialCount, Int32 maximumCount);
public Int32 Release(); // Release(1);
//
public Int32 Release(Int32 releaseCount); //
//
}

, :

.
.
, ,
releaseCount ( releaseCount , Release Semaphore).
, , .
, Set
, , Release
,
. , Release ,
,
SemaphoreFullException.
SimpleWaitLock
,
( ,
):
public sealed class SimpleWaitLock : IDisposable {
private Semaphore m_AvailableResources;
public SimpleWaitLock(Int32 maximumConcurrentThreads) {
m_AvailableResources =

851

new Semaphore(maximumConcurrentThreads, maximumConcurrentThreads);


}
public void Enter() {
//
m_AvailableResources.WaitOne();
}
public void Leave() {
// ;
m_ AvailableResources.Release();
}
}

public void Dispose() { m_AvailableResources.Close(); }

(mutex) . AutoResetEvent ( Semaphore


1), . Mutex:
public sealed class Mutex : WaitHandle {
public Mutex();
public void ReleaseMutex();
}

,
. -, Mutex
, . (Int32). ReleaseMutex, Mutex
, . ,
Mutex , ReleaseMutex System.
ApplicationException. Mutex - , , ,
System.Threading.AbandonedMutexException.
, . , Mutex,

. AbandonedMutexException,
, .
, Mutex , ,
- .
,
, .

852

29.

ReleaseMutex . ,

0, .
. , . Mutex

. , Mutex ,
. , , Mutex.
.
,
, .
:
internal class SomeClass : IDisposable {
private readonly Mutex m_lock = new Mutex();
public void Method1() {
m_lock.WaitOne();
// -...
Method2(); // Method2,
m_lock.ReleaseMutex();
}
public void Method2() {
m_lock.WaitOne();
// -...
m_lock.ReleaseMutex();
}
}

public void Dispose() { m_lock.Dispose(); }

, SomeClass, Method1, Mutex. -


, Method2,
- .
Mutex ,
, . SomeClass AutoResetEvent,
WaitOne .

AutoResetEvent:
internal sealed class RecursiveAutoResetEvent : IDisposable {
private AutoResetEvent m_lock = new AutoResetEvent(true);
private Int32 m_owningThreadId = 0;
private Int32 m_recursionCount = 0;

853

public void Enter() {


//
Int32 currentThreadId = Thread.CurrentThread.ManagedThreadId;
// ,
//
if (m_owningThreadId == currentThreadId) {
m_recursionCount++;
return;
}
// ,
m_lock.WaitOne();
// ,
//
m_owningThreadId = currentThreadId;
m_recursionCount = 1;
}
public void Leave() {
// ,
//
if (m_owningThreadId != Thread.CurrentThread.ManagedThreadId)
throw new InvalidOperationException();
//
if (--m_recursionCount == 0) {
// 0,
//
m_owningThreadId = 0;
m_lock.Set(); // ( )
}
}
public void Dispose() { m_lock.Dispose(); }
}

RecursiveAutoResetEvent Mutex, RecursiveAutoResetEvent


, -
. Windows
AutoResetEvent .

30.

29
.
.
, ,
(hybrid thread synchronization
constructs).
,
.
, ( )
.
,
.

. , ,
FCL,
, .
Wintellect Power Threading, (http://Wintellect.com/PowerThreading.aspx).
,
FCL, .
,
,
.



:
internal sealed class SimpleHybridLock : IDisposable {
// Int32

855

// (Interlocked-)
private Int32 m_waiters = 0;
// AutoResetEvent -
private AutoResetEvent m_waiterLock = new AutoResetEvent(false);
public void Enter() {
//
if (Interlocked.Increment(ref m_waiters) == 1)
return; // , ,
// (),
// .
m_waiterLock.WaitOne(); //
// WaitOne ,
}
public void Leave() {
//
if (Interlocked.Decrement(ref m_waiters) == 0)
return; // ,
// ,
m_waiterLock.Set(); //
}
public void Dispose() { m_waiterLock.Dispose(); }
}

SimpleHybridLock : Int32 , ,
AutoResetEvent, .
,
Int32 AutoResetEvent.
AutoResetEvent SimpleHybridLock
,
Int32.
(AutoResetEventSlim), AutoResetEvent
, . AutoResetEvent Dispose
.
SimpleHybridLock,
Enter Leave,
. .
Enter Interlocked.Incre
ment m_waiters 1, .
, , ,
, Enter .

856

30.

, .
Enter, m_waiters
, , WaitOne, AutoResetEvent. WaitOne
Windows,
.
, ,
, .
-
. 29
Enter SimpleSpinLock.
Leave.
Interlocked.Decrement, m_waiters .
Enter, , Leave,
. , .
, Int32,
! ,
Leave
m_waiters, , , ,
. , Leave,
( ) .
Set AutoResetEvent.
, . , .
, AutoResetEvent
; AutoResetEvent
,
Leave.

Leave
, Enter , .
, ,
, Enter Leave,
.
.
, ;
.

857

, ,
,
. ,
, , .
, , , .
. Mutex1.
,
, .
:
internal sealed class AnotherHybridLock : IDisposable {
// Int32
// ( Interlocked)
private Int32 m_waiters = 0;
// AutoResetEvent
private AutoResetEvent m_waiterLock = new AutoResetEvent(false);
//
private Int32 m_spincount = 4000; //
// ,
private Int32 m_owningThreadId = 0, m_recursion = 0;
public void Enter() {
// ,
//
Int32 threadId = Thread.CurrentThread.ManagedThreadId;
if (threadId == m_owningThreadId) { m_recursion++; return; }
// ,
SpinWait spinwait = new SpinWait();
for (Int32 spinCount = 0; spinCount < m_spincount; spinCount++) {
// ,
//
if (Interlocked.CompareExchange(
ref m_waiters, 1, 0) == 0) goto GotLock;

Mutex , . Mutex
.
1

858

30.

//
//
spinwait.SpinOnce();
}
// , ,
//
if (Interlocked.Increment(ref m_waiters) > 1) {
//
//
m_waiterLock.WaitOne(); // ;
//
// ,
//
}
GotLock:
// ,
// ,
m_owningThreadId = threadId; m_recursion = 1;
}
public void Leave() {
// ,
Int32 threadId = Thread.CurrentThread.ManagedThreadId;
if (threadId != m_owningThreadId)
throw new SynchronizationLockException(
"Lock not owned by calling thread");
// .
// ,
if (--m_recursion > 0) return;
m_owningThreadId = 0; //
// ,
if (Interlocked.Decrement(ref m_waiters) == 0)
return;
// ,
m_waiterLock.Set(); //
}

public void Dispose() { m_waiterLock.Dispose(); }

, , , . ,
, ,

FCL

859

. 29 ,
Int32 , .
,
SimpleHybridlock AnotherHybridLock.
:
Incrementing x: 8
Incrementing x in M: 69 ~9
Incrementing x in SpinLock: 164 ~21
Incrementing x in SimpleHybridLock: 164 ~21 ( SpinLock)
Incrementing x in AnotherHybridLock: 230 ~29 (- /
)
Incrementing x in SimpleWaitLock: 8,854 ~1107

, AnotherHybridLock
, SimpleHybridLock. , .
, , .

FCL
FCL ,
, ,
.
. , ,
. CancellationToken ( 27), ,
,
.
.

ManualResetEventSlim SemaphoreSlim
System.Threading.ManualReset
EventSlim System.Threading.SemaphoreSlim1. ,
,
AutoResetEventSlim ,
SemaphoreSlim maxCount .
1

860

30.

, , . Wait
CancellationToken. (
):
public class ManualResetEventSlim : IDisposable {
public ManualResetEventSlim(Boolean initialState, Int32 spinCount);
public void Dispose();
public void Reset();
public void Set();
public Boolean Wait(
Int32 millisecondsTimeout, CancellationToken cancellationToken);
public Boolean IsSet { get; }
public Int32 SpinCount { get; }
public WaitHandle WaitHandle { get; }

}
public class SemaphoreSlim : IDisposable {
public SemaphoreSlim(Int32 initialCount, Int32 maxCount);
public void Dispose();
public Int32 Release(Int32 releaseCount);
public Boolean Wait(
Int32 millisecondsTimeout, CancellationToken cancellationToken);
// async await (. 28)
public Task<Boolean> WaitAsync(Int32 millisecondsTimeout,
CancellationToken cancellationToken);

public Int32 CurrentCount { get; }


public WaitHandle AvailableWaitHandle { get; }

Monitor
,
Monitor, , .
, , C#
, JIT, CLR . ,
, , .
, .
,
(sync block). ,
AnotherHybridLock. ,
, -,
. Monitor ,

FCL

861

. .
Monitor:
public static class Monitor {
public static void Enter(Object obj);
public static void Exit(Object obj);
// ( ):
public static Boolean TryEnter(Object obj, Int32 millisecondsTimeout);
// lockTaken
public static void Enter(Object obj, ref Boolean lockTaken);
public static void TryEnter(
Object obj, Int32 millisecondsTimeout, ref Boolean lockTaken);
}

, , , .
, CLR
. CLR
. ,
.
- . (sync block index),
.
1,
.
Monitor.Enter CLR .
. Exit ,
. ,
1, ,
- .
30.1 ,
CLR.
- A, B C T.
. 4,
: -.
-,
Monitor. , ,
,
.

862

30.

. 30.1. ( -).
CLR

Monitor:
internal sealed class Transaction {
private DateTime m_timeOfLastTrans;
public void PerformTransaction() {
Monitor.Enter(this);
// ...
m_timeOfLastTrans = DateTime.Now;
Monitor.Exit(this);
}
public DateTime LastTransaction {
get {
Monitor.Enter(this);
// ...
DateTime temp = m_timeOfLastTrans;
Monitor.Exit(this);
return temp;
}
}
}

FCL

863

, . ,

. :
public static void SomeMethod() {
var t = new Transaction();
Monitor.Enter(t); //
// LastTransaction
// .
// SomeMethod Monitor.Exit!
ThreadPool.QueueUserWorkItem(o => Console.WriteLine(t.LastTransaction));
// - ...
Monitor.Exit(t);
}

, SomeMethod, Monitor.
Enter, Transaction. LastTransaction, Monitor.
Enter, .
, , SomeMethod,
Monitor.Exit. ,
LastTransaction, ,
, . ,
. , ,
, ,
.
. Transaction:
internal sealed class Transaction {
private readonly Object m_lock = new Object(); //
//
private DateTime m_timeOfLastTrans;
public void PerformTransaction() {
Monitor.Enter(m_lock); //
// ...
m_timeOfLastTrans = DateTime.Now;
Monitor.Exit(m_lock); //
}
public DateTime LastTransaction {
get {
Monitor.Enter(m_lock); //
// ...
DateTime temp = m_timeOfLastTrans;
Monitor.Exit(m_lock); //
return temp;
}
}
}

864

30.

Transaction ,
m_lock.
, ,
Monitor ; ,
, ,
. Monitor
:
- System.Marshal
ByRefObject, ( 22). Monitor
, .
Monitor.Enter , ( , ,
22), .
CLR,
. ,
.
- Monitor.
( 14),
String
. Monitor
.
CLR ;
. ,
, String .
, , , . ,
. CLR,
.
String
Monitor.
Monitor Object,
.
. Monitor.Enter
, .
[MethodImpl(MethodImplOptions.Synchro
nized)] JIT-
Monitor.Enter Monitor.Exit. , this, .

FCL

865

,
. .
( 8) CLR
-, , .
. ,
,
.

.
, . , - ,
, C#
lock. :
private void SomeMethod() {
lock (this) {
// ...
}
}

:
private void SomeMethod() {
Boolean lockTaken = false;
try {
//
Monitor.Enter(this, ref lockTaken);
// ...
}
finally {
if (lockTaken) Monitor.Exit(this);
}
}

C# , Monitor.Exit finally. ,
try. . try
, .
finally ,
. ,
. ,
try .
JIT- ,
try, .

866

30.

,
1. lock.
lockTaken Boolean ,
. , try Monitor.Enter ( 22).
finally, .
lockTaken.
false, , .
Monitor.Enter , lockTaken
true. finally ,
Monitor.Exit. , SpinLock
lockTaken.

ReaderWriterLockSlim
. (, SimpleSpinLock , SimpleWaitLock ,
SimpleHybridLock, AnotherHybridLock, Mutex Monitor), ,
,
. ,
,
. ,
, . ReaderWriterLockSlim
, .
:
, ,
, .
, , , , , .
, , , , , .
, .
, ,
, .
,
.
, finally, try
, (,
).
1

FCL

867

(
):
public class ReaderWriterLockSlim : IDisposable {
public ReaderWriterLockSlim(LockRecursionPolicy recursionPolicy);
public void Dispose();
public void EnterReadLock();
public Boolean TryEnterReadLock(Int32 millisecondsTimeout);
public void ExitReadLock();
public void EnterWriteLock();
public Boolean TryEnterWriteLock(Int32 millisecondsTimeout);
public void ExitWriteLock();
//
public Boolean IsReadLockHeld { get; }
public Boolean IsWriteLockHeld { get; }
public Int32 CurrentReadCount { get; }
public Int32 RecursiveReadCount { get; }
public Int32 RecursiveWriteCount { get; }
public Int32 WaitingReadCount { get; }
public Int32 WaitingWriteCount { get; }
public LockRecursionPolicy RecursionPolicy { get; }
// ,
}

:
internal sealed class Transaction : IDisposable {
private readonly ReaderWriterLockSlim m_lock =
new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
private DateTime m_timeOfLastTrans;
public void PerformTransaction() {
m_lock.EnterWriteLock();
// ...
m_timeOfLastTrans = DateTime.Now;
m_lock.ExitWriteLock();
}
public DateTime LastTransaction {
get {
m_lock.EnterReadLock();
// ...
DateTime temp = m_timeOfLastTrans;
m_lock.ExitReadLock();
return temp;
}
}
}

public void Dispose() { m_lock.Dispose(); }

868

30.

, . -, ReaderWriterLockSlim
LockRecurionsPolicy, :
public enum LockRecursionPolicy { NoRecursion, SupportsRecursion }

SupportsRecursion . ,
,
LockRecursionPolicy.NoRecursion (
).
- ,
,
, .

ReaderWriterLockSlim ! .
ReaderWriterLockSlim (
), . .
,
.
. . ,
.
,
. , ,
.

FCL ReaderWriterLock, Microsoft


.NETFramework1.0. , 3.5 Microsoft ReaderWriterLockSlim.
ReaderWriterLock ,
.
. , .
, .

OneManyLock
-, ,
FCL ReaderWriterLockSlim1.
Ch30-1-HybridThreadSync.cs
. http://Wintellect.com/Books.
1

FCL

869

OneManyLock, ,

. :
public sealed class OneManyLock : IDisposable {
public OneManyLock();
public void Dispose();

public void Enter(Boolean exclusive);


public void Leave();

, . Int32, , Semaphore,
, AutoResetEvent, .
.
. 0 Free (), 1 OwnedByWriter ( ), 2 OwnedByReaders
( ), 3 OwnedByReadersAndWriterPending (
) 4 ReservedForWriter ( ). .
( 0 1048575)
(RR), .
(RW),
. AutoResetEvent.
(WW),
. Semaphore.
,
Int64, Interlocked.

.
:
, OwnedByReaders,
RR= 1, .
OwnedByReaders (
), RR++, .
RW++, .
, .
:
RR--.

870

30.

RR > 0, .
WW > 0, ReservedForWriter ( ), WW--,
, .
RW = 0 WW = 0, Free (), .
:
, OwnedByWriter
( ), .
ReservedForWriter (
), OwnedByWriter ( ), .
OwnedByWriter ( ),
WW++, . ,
.
OwnedByReaders
AndWriterPending ( ), WW++, . ,
.
:
WW= 0 RW= 0, Free (), .
WW> 0, ReservedForWriter ( ), WW--,
, .
WW= 0 RW> 0, Free (), RW= 0, ,
.
, ,
, .
, , , .
, , RR WW 0,
Free. ,
.
, -

FCL

871

.
.
,
Interlocked- 29. ,
. .
OneManyLock ReaderWriterLockSlim
ReaderWriterLock FCL, :
x OneManyLock: 330 .
x ReaderWriterLockSlim: 554 1,7 .
x ReaderWriterLock: 984 3 .
, -
- , , . , - .
Power
Threading library ( http://Wintellect.com/
PowerThreading.aspx). , OneManyResourceLock.
,
(deadlocks), ( ),

.
,
.

CountdownEvent
System.Threading.CountdownEvent. ManualResetEventSlim
0.
( ,
0). (
):
public class CountdownEvent : IDisposable {
public CountdownEvent(Int32 initialCount);
public void Dispose();
public void Reset(Int32 count); //
//
public void AddCount(Int32 signalCount); //
//
public Boolean TryAddCount(Int32 signalCount); //
//

CurrentCount
count
CurrentCount
signalCount
CurrentCount
signalCount

872

30.

public Boolean Signal(Int32 signalCount); // CurrentCount


// signameCount
public Boolean Wait(
Int32 millisecondsTimeout, CancellationToken cancellationToken);
public Int32 CurrentCount { get; }
public Boolean IsSet { get; } // true,
// CurrentCount 0
public WaitHandle WaitHandle { get; }
}

CurrentCount CountdownEvent
. CurrentCount 0, AddCount
InvalidOperationException, TryAddCount
false.

Barrier
System.Threading.Barrier
, -
. ,
. ,
CLR ,
.
, .
, .
,
. , , ,
. ,
.

.
Barrier,
( ):
public class Barrier : IDisposable {
public Barrier(Int32 participantCount, Action<Barrier> postPhaseAction);
public void Dispose();
public Int64 AddParticipants(Int32 participantCount); //
//
public void RemoveParticipants(Int32 participantCount); //
//
public Boolean SignalAndWait(
Int32 millisecondsTimeout, CancellationToken cancellationToken);
public Int64 CurrentPhaseNumber { get; } //

FCL
//
public Int32 ParticipantCount { get; } //
public Int32 ParticipantsRemaining { get; } //
//
}

873

( 0)

,
SignalAndWait

Barrier , .
Action<Barrier>, ,
.
Barrier AddParticipant
RemoveParticipant, .
SignalAndWait , Barrier (
ManualResetEventSlim). SignalAndWait
Barrier (
SignalAndWait ) , .


, .
-,
,
. ,
Volatile Interlocked, . , .
, ,
.
, :
. , , , . C#

.
.
.
. ,
. . Windows ,
.
, GUI- - .

874

30.

. , GUI-
.
, . , , , , , ,
.. ,
.
, .
.
, , ..
, , ,
.

Monitor 1. -.
Monitor,
,
.
(
-), . ,
Monitor, , 2. , finally,

. ,
,
, -
.
, , - ,
, . ,
.
, , ( 27),
. , ,
Monitor SpinLock.
, .
, SpinLock Monitor ,
.
2
, Monitor , .
1

875

,
. ,
, . -
XxxAsync,
- ( , ).


,
(double-check locking). , ,
(lazy initialization).
, .
.
,
.

, . Java, , Java .
www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html.
, , (.29) CLR
. ,
C#:
internal sealed class Singleton {
// s_lock
// . ,
//
// , System.Object
// .
//
private static readonly Object s_lock = new Object();
// Singleton
private static Singleton s_value = null;
//
private Singleton() {
// Singleton
}

876

30.

// , Singleton
// ( )
public static Singleton GetSingleton() {
// Singleton ,
if (s_value != null) return s_value;
Monitor.Enter(s_lock); // ,
//
if (s_value == null) {
// ,
Singleton temp = new Singleton();
// s_value (. )
Volatile.Write(ref s_value, temp);
}
Monitor.Exit(s_lock);
// Singleton
return s_value;
}
}

GetSingleton s_value, , -

. .
,
. , GetSingleton,
,
, , .

.
, Java.
GetSingleton Java s_value
if
.
true, , Singleton . , ,
GetSingleton , .
.
CLR
:
, .
GetSingleton , s_value
Monitor.Enter;
.
GetSingleton Volatile.Write. ,
if :
s_value = new Singleton(); //

877

, ,

Singleton, s_value,

(publishing).
Singleton, s_value ( ) .
, .
, s_value,
GetSingleton? ,
s_value null Singleton,
!
, - , .
Interlocked.Exchange. ,
temp s_value ,
. s_value volatile.
() s_value
. , , ,
.
. , ,
. .
Singleton
, :
internal sealed class Singleton {
private static Singleton s_value = new Singleton();
//
//
private Singleton() {
// Singleton
}
// , Singleton
// ( , )
public static Singleton GetSingleton() { return s_value; }
}

CLR ,
GetSingleton Singleton .
, CLR . 8.
.
Singleton ,

878

30.

Singleton. .
Singleton:
internal sealed class Singleton {
private static Singleton s_value = null;
//
//
private Singleton() {
// Singleton
}
// , Singleton
// ( , )
public static Singleton GetSingleton() {
if (s_value != null) return s_value;
// Singleton ,
//
Singleton temp = new Singleton();
Interlocked.CompareExchange(ref s_value, temp, null);
// Singleton
//
return s_value; //
}
}

GetSingleton
( ) Singleton .
Interlocked.CompareExchange s_value
. , ,
. ,
GetSingleton , -
Singleton.
,
Singleton, . -, . -, .
Monitor
, , .
, . CompareExchange
. ,
.
FCL ,
. System.Lazy (
):

879

public class Lazy<T> {


public Lazy(Func<T> valueFactory, LazyThreadSafetyMode mode);
public Boolean IsValueCreated { get; }
public T Value { get; }
}

:
public static void Main() {
// DateTime
Lazy<String> s = new Lazy<String>(
() => DateTime.Now.ToLongTimeString(),
LazyThreadSafetyMode.PublicationOnly);
Console.WriteLine(s.IsValueCreated); //
//
Console.WriteLine(s.Value); //
Console.WriteLine(s.IsValueCreated); //
//
Thread.Sleep(10000); //
//
Console.WriteLine(s.Value); //
//
}

false,
Value

true,
Value
10

,

:
False
2:40:42 PM
True
2:40:42 PM , 10 ,

Lazy
LazyThreadSafetyMode. :
public enum LazyThreadSafetyMode {
None, //
// ( GUI-)
ExecutionAndPublication, //
PublicationOnly, // Interlocked.CompareExchange
}


Lazy. System.Threading.LazyInitializer. :
public static class LazyInitializer {
// Interlocked.CompareExchange
public static T EnsureInitialized<T>(ref T target) where T: class;
public static T EnsureInitialized<T>(
ref T target, Func<T> valueFactory) where T: class;
// syncLock Enter Exit Monitor
public static T EnsureInitialized<T>(

880

30.

ref T target, ref Boolean initialized, ref Object syncLock);


public static T EnsureInitialized<T>(ref T target,
ref Boolean initialized, ref Object syncLock, Func<T> valueFactory);
}

syncLock
EnsureInitialized
.
:

public static void Main() {


String name = null;
// null,
LazyInitializer.EnsureInitialized(ref name, () => "Jeffrey");
Console.WriteLine(name); // "Jeffrey"
// null,
LazyInitializer.EnsureInitialized(ref name, () => "Richter");
Console.WriteLine(name); // "Jeffrey"
}


, .

. , -, , -,
, . , ,
.
(condition variable pattern),
Monitor:
public static class Monitor {
public static Boolean Wait(Object obj);
public static Boolean Wait(Object obj, Int32 millisecondsTimeout);

public static void Pulse(Object obj);


public static void PulseAll(Object obj);

:
internal sealed class ConditionVariablePattern {
private readonly Object m_lock = new Object();
private Boolean m_condition = false;
public void Thread1() {
Monitor.Enter(m_lock); //

881

// ""
while (!m_condition) {
// , ,
Monitor.Wait(m_lock); // ,
//
}
// , ...
Monitor.Exit(m_lock); //
}
public void Thread2() {
Monitor.Enter(m_lock); //
// ...
m_condition = true;
// Monitor.Pulse(m_lock); //
Monitor.PulseAll(m_lock); //
Monitor.Exit(m_lock); //
}
}

, Thread1, .
Boolean ,
. , ,
, , 10.
, ,
, Wait.
, ,
.
Thread2 , .
Enter , - ,
, Pulse(All),
Wait. Pulse ,
( ), PulseAll
( ). .
, Thread2, Monitor.Exit,
. ,
PulseAll .
, Wait, ,
, .
, Wait Exit.

882

30.

, , Thread1,
. , Wait.
, , Exit,
.

( ),
, .
, .
, , ,
, .
internal sealed class SynchronizedQueue<T> {
private readonly Object m_lock = new Object();
private readonly Queue<T> m_queue = new Queue<T>();
public void Enqueue(T item) {
Monitor.Enter(m_lock);
//
// /
m_queue.Enqueue(item);
Monitor.PulseAll(m_lock);
}

Monitor.Exit(m_lock);

public T Dequeue() {
Monitor.Enter(m_lock);
// , ()
while (m_queue.Count == 0)
Monitor.Wait(m_queue);
//
T item = m_queue.Dequeue();
Monitor.Exit(m_lock);
return item;
}
}


, . ,

883

, .
.
-, . .
,
- . , . ,
, . ,
, . !
.
, , .
-
. Windows .
, .
, ,
Task, 27.
, Barrier:
( Task),
Task.
, :
, , ,
.
.
,
, , .

, , ,
.
,
.
, ,
. ,
( ). , , , , .

884

30.

. Microsoft. 2009
7603502.
SemaphoreSlim WaitAsync.
:
public Task<Boolean> WaitAsync(Int32 millisecondsTimeout,
CancellationToken cancellationToken);


( - ).
private static async Task
AccessResourceViaAsyncSynchronization(SemaphoreSlim asyncLock) {
// TODO: ...
await asyncLock.WaitAsync(); // .
// , ,
// .
// TODO: ( )...
// , ,
// .
asyncLock.Release();
// TODO: ...
}

WaitAsync SemaphoreSlim , , ,
. SemaphoreSlim 1, .
, ,
Monitor , SemaphoreSlim
(, ).
/? .NET Framework
ConcurrentExclusiveSchedulerPair, :
public class ConcurrentExclusiveSchedulerPair {
public ConcurrentExclusiveSchedulerPair();
public TaskScheduler ExclusiveScheduler { get; }
public TaskScheduler ConcurrentScheduler { get; }
//
}

TaskScheduler , / . , ExclusiveScheduler,
,
ConcurrentScheduler. , ,
ConcurrentScheduler, -

885

, ExclusiveScheduler.
ConcurrentExclusiveSchedulerPair :
private static void ConcurrentExclusiveSchedulerDemo() {
var cesp = new ConcurrentExclusiveSchedulerPair();
var tfExclusive = new TaskFactory(cesp.ExclusiveScheduler);
var tfConcurrent = new TaskFactory(cesp.ConcurrentScheduler);
for (Int32 operation = 0; operation < 5; operation++) {
var exclusive = operation < 2; //
// 2 3
(exclusive ? tfExclusive : tfConcurrent).StartNew(() => {
Console.WriteLine("{0} access", exclusive ? "exclusive" : "concurrent");
// TODO: ...
});
}
}

, .NET Framework /. , ,
AsyncOneManyLock. , SemaphoreSlim:
private static async Task
AccessResourceViaAsyncSynchronization(AsyncOneManyLock asyncLock) {
// TODO: ...
// OneManyMode.Exclusive OneManyMode.Shared
//
await asyncLock.AcquireAsync(OneManyMode.Shared); //
// , ,
// , ;
// TODO: ...
// , ,
// .
asyncLock.Release();
// TODO: ...
}

AsyncOneManyLock.
public enum OneManyMode { Exclusive, Shared }
public sealed class AsyncOneManyLock {
#region Lock code
private SpinLock m_lock = new SpinLock(true); //
// readonly SpinLock
private void Lock() { Boolean taken = false; m_lock.Enter(ref taken); }
private void Unlock() { m_lock.Exit(); }
#endregion
#region Lock state and helper methods

886

30.

private Int32 m_state = 0;


private Boolean IsFree { get { return m_state == 0; } }
private Boolean IsOwnedByWriter { get { return m_state == 1
; } }
private Boolean IsOwnedByReaders { get { return m_state > 0; } }
private Int32 AddReaders(Int32 count) { return m_state += count; }
private Int32 SubtractReader() { return m_state;

}
private void MakeWriter() { m_state = 1
; }
private void MakeFree() { m_state = 0; }
#endregion
// (
// )
private readonly Task m_noContentionAccessGranter;
//
// TaskCompletionSource,
private readonly Queue<TaskCompletionSource<Object>> m_qWaitingWriters =
new Queue<TaskCompletionSource<Object>>();
//
// TaskCompletionSource
private TaskCompletionSource<Object> m_waitingReadersSignal =
new TaskCompletionSource<Object>();
private Int32 m_numWaitingReaders = 0;
public AsyncOneManyLock() {
m_noContentionAccessGranter = Task.FromResult<Object>(null);
}
public Task WaitAsync(OneManyMode mode) {
Task accressGranter = m_noContentionAccessGranter; //
//
Lock();
switch (mode) {
case OneManyMode.Exclusive:
if (IsFree) {
MakeWriter(); //
} else {
// :
var tcs = new TaskCompletionSource<Object>();
m_qWaitingWriters.Enqueue(tcs);
accressGranter = tcs.Task;
}
break;
case OneManyMode.Shared:
if (IsFree || (IsOwnedByReaders && m_qWaitingWriters.Count == 0)) {
AddReaders(1); //
} else { //
//
m_numWaitingReaders++;

887

accressGranter =
m_waitingReadersSignal.Task.ContinueWith(t => t.Result);

}
break;

}
Unlock();
}

return accressGranter;

public void Release() {


TaskCompletionSource<Object> accessGranter = null;
Lock();
if (IsOwnedByWriter) MakeFree(); //
else SubtractReader(); //
if (IsFree) {
// ,
//
if (m_qWaitingWriters.Count > 0) {
MakeWriter();
accessGranter = m_qWaitingWriters.Dequeue();
} else if (m_numWaitingReaders > 0) {
AddReaders(m_numWaitingReaders);
m_numWaitingReaders = 0;
accessGranter = m_waitingReadersSignal;
// TCS ,
//
m_waitingReadersSignal = new TaskCompletionSource<Object>();
}
}
Unlock();
// /
//
if (accessGranter != null) accessGranter.SetResult(null);
}
}

, , .
SpinLock,
. SpinLock 29, , . WaitAsync,
,
, ,
TaskCompletionSource . -

888

30.

,
.
Release , , , TaskCompletionSource
. . SpinLock Queue.
, , .

FCL , System.Collections.Concurrent: ConcurrentQueue,


ConcurrentStack, ConcurrentDictionary ConcurrentBag. :
// FIFO
public class ConcurrentQueue<T> : IProducerConsumerCollection<T>,
IEnumerable<T>, ICollection, IEnumerable {

public
public
public
public
public

ConcurrentQueue();
void Enqueue(T item);
Boolean TryDequeue(out T result);
Int32 Count { get; }
IEnumerator<T> GetEnumerator();

// LIFO
public class ConcurrentStack<T> : IProducerConsumerCollection<T>,
IEnumerable<T>, ICollection, IEnumerable {

public
public
public
public
public

ConcurrentStack();
void Push(T item);
Boolean TryPop(out T result);
Int32 Count { get; }
IEnumerator<T> GetEnumerator();

//
public class ConcurrentBag<T> : IProducerConsumerCollection<T>,
IEnumerable<T>, ICollection, IEnumerable {
public ConcurrentBag();
public void Add(T item);
public Boolean TryTake(out T result);

889

public Int32 Count { get; }


public IEnumerator<T> GetEnumerator();

// /
public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>,
ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey,
TValue>>, IDictionary, ICollection, IEnumerable {
public
public
public
public
public
TKey
public
public
TKey
public
public
public
}

ConcurrentDictionary();
Boolean TryAdd(TKey key, TValue value);
Boolean TryGetValue(TKey key, out TValue value);
TValue this[TKey key] { get; set; }
Boolean TryUpdate(
key, TValue newValue, TValue comparisonValue);
Boolean TryRemove(TKey key, out TValue value);
TValue AddOrUpdate(
key, TValue addValue, Func<TKey, TValue> updateValueFactory);
TValue GetOrAdd(TKey key, TValue value);
Int32 Count { get; }
IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator();

. , ,
. , TryDequeue, TryPop,
TryTake TryGetValue, true,
false.
, ,
. ConcurrentDictionary
Monitor, , . ConcurrentQueue
ConcurrentStack Interlocked
. ConcurrentBag - .
Interlocked - .
-
.
Interlocked. - , Monitor - . ,
(stealing) .
,
GetEnumerator, C# foreach,
LINQ. ConcurrentStack, ConcurrentQueue ConcurrentBag
GetEnumerator ;
. GetEnumerator ConcurrentDictionary

890

30.

, ,
; . Count
. ,
.
ConcurrentStack, ConcurrentQueue ConcurrentBag IProducerConsumerCollection, :
public interface IProducerConsumerCollection<T> : IEnumerable<T>,
ICollection, IEnumerable {
Boolean TryAdd(T item);
Boolean TryTake(out T item);
T[] ToArray();
void CopyTo(T[] array, Int32 index);
}

. , , ,
, , , , . ,
,
.
System.Collections.Concurrent.BlockingCollection, . ( ):
public class BlockingCollection<T> : IEnumerable<T>, ICollection,
IEnumerable, IDisposable {
public BlockingCollection(
IProducerConsumerCollection<T> collection, Int32 boundedCapacity);
public void Add(T item);
public Boolean TryAdd(
T item, Int32 msTimeout, CancellationToken cancellationToken);
public void CompleteAdding();
public T Take();
public Boolean TryTake(
out T item, Int32 msTimeout, CancellationToken cancellationToken);
public Int32 BoundedCapacity { get; }
public Int32 Count { get; }
public Boolean IsAddingCompleted { get; } //
//
public Boolean IsCompleted { get; } //
//

true,
AddingComplete
true,
IsAddingComplete Count==0

public IEnumerable<T> GetConsumingEnumerable(


CancellationToken cancellationToken);
public void CopyTo(T[] array, int index);

891

public T[] ToArray();


public void Dispose();

BlockingCollection bounded
Capacity .
Add , .
, TryAdd, () / CancellationToken.

,
CancellationToken ( CancellationToken 27).
BlockingCollection IDisposable.
Dispose
SemaphoreSlim, -
-.
, -
CompleteAdding. -,
foreach, GetConsumingEnumerable,
. ,
/ :
public static void Main() {
var bl = new BlockingCollection<Int32>(new ConcurrentQueue<Int32>());
//
ThreadPool.QueueUserWorkItem(ConsumeItems, bl);
// 5
for (Int32 item = 0; item < 5; item++) {
Console.WriteLine("Producing: " + item);
bl.Add(item);
}
// -,
bl.CompleteAdding();
Console.ReadLine(); //
}
private static void ConsumeItems(Object o) {
var bl = (BlockingCollection<Int32>) o;
// ,
foreach (var item in bl.GetConsumingEnumerable()) {
Console.WriteLine("Consuming: " + item);
}
//
Console.WriteLine("All items have been consumed");
}

892

30.

:
Producing: 0
Producing: 1
Producing: 2
Producing: 3
Producing: 4
Consuming: 0
Consuming: 1
Consuming: 2
Consuming: 3
Consuming: 4
All items have been consumed

, Producing ()
Consuming () , All items have been
consumed ( ) .
BlockingCollection AddToAny,
TryAddToAny, TakeFromAny TryTakeFromAny. BlockingCollection<T>[], , ,
CancellationToken. (Try)AddToAny
, ,
. (Try)TakeFromAny , .

foreground thread

arity

lock

verification

deadlock

inline

delegate

deserialization

handle

AppDomain

task

closed types

private

sealed class
protected

( )

value type

cloning

covariant
,

code page
contra-variant

versioning

tuple

heap

manifest

894


array

, , ( )

native

metadata

callback method

extension method

()

accessor methods

mutex

inheritance

custom attribute

jagged array

unmanaged

implicit

generic

shim

event handler

constraint

public

lazy initialization

reflection

type parameter

overloading

override

enumerated type

scheduler

reference counting

late binding

threading model

casting

binding


application

,
,

code contract

marshaling

namespace

thread pool

()

parse

deploying

hosting

early binding

895

unboxing

distributed application

culture

null

nullable

,
,

assembly

semaphore

serialization

weak reference

reference type

strong reference
garbage collection

boxing

managed code

finalization

background thread

hash code

partial method

instance method

explicit

kernel

CLR via C#.


Microsoft .NET Framework 4.5 C#
4-

.
.

.
.

, 192102, -, . (. ), . 3, , . 7.
005-93,
2; 95 3005 .
13.06.13. 70100/16. . . . 72,240. 2000.
CtP .
194044, -, . , 9. / (812) 495-56-10.

Вам также может понравиться