-
Notifications
You must be signed in to change notification settings - Fork 86
/
classes.md
5136 lines (4295 loc) · 248 KB
/
classes.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# 14 Classes
## 14.1 General
A class is a data structure that may contain data members (constants and fields), function members (methods, properties, events, indexers, operators, instance constructors, finalizers, and static constructors), and nested types. Class types support inheritance, a mechanism whereby a ***derived class*** can extend and specialize a ***base class***.
## 14.2 Class declarations
### 14.2.1 General
A *class_declaration* is a *type_declaration* ([§13.7](namespaces.md#137-type-declarations)) that declares a new class.
```ANTLR
class_declaration
: attributes? class_modifier* 'partial'? 'class' identifier
type_parameter_list? class_base? type_parameter_constraints_clause*
class_body ';'?
;
```
A *class_declaration* consists of an optional set of *attributes* ([§21](attributes.md#21-attributes)), followed by an optional set of *class_modifier*s ([§14.2.2](classes.md#1422-class-modifiers)), followed by an optional `partial` modifier ([§14.2.7](classes.md#1427-partial-declarations)), followed by the keyword `class` and an *identifier* that names the class, followed by an optional *type_parameter_list* ([§14.2.3](classes.md#1423-type-parameters)), followed by an optional *class_base* specification ([§14.2.4](classes.md#1424-class-base-specification)), followed by an optional set of *type_parameter_constraints_clause*s ([§14.2.5](classes.md#1425-type-parameter-constraints)), followed by a *class_body* ([§14.2.6](classes.md#1426-class-body)), optionally followed by a semicolon.
A class declaration shall not supply a *type_parameter_constraints_clause*s unless it also supplies a *type_parameter_list*.
A class declaration that supplies a *type_parameter_list* is a generic class declaration. Additionally, any class nested inside a generic class declaration or a generic struct declaration is itself a generic class declaration, since type arguments for the containing type shall be supplied to create a constructed type ([§8.4](types.md#84-constructed-types)).
### 14.2.2 Class modifiers
#### 14.2.2.1 General
A *class_declaration* may optionally include a sequence of class modifiers:
```ANTLR
class_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
| 'abstract'
| 'sealed'
| 'static'
| unsafe_modifier // unsafe code support
;
```
*unsafe_modifier* ([§22.2](unsafe-code.md#222-unsafe-contexts)) is only available in unsafe code ([§22](unsafe-code.md#22-unsafe-code)).
It is a compile-time error for the same modifier to appear multiple times in a class declaration.
The `new` modifier is permitted on nested classes. It specifies that the class hides an inherited member by the same name, as described in [§14.3.5](classes.md#1435-the-new-modifier). It is a compile-time error for the `new` modifier to appear on a class declaration that is not a nested class declaration.
The `public`, `protected`, `internal`, and `private` modifiers control the accessibility of the class. Depending on the context in which the class declaration occurs, some of these modifiers might not be permitted ([§7.5.2](basic-concepts.md#752-declared-accessibility)).
When a partial type declaration ([§14.2.7](classes.md#1427-partial-declarations)) includes an accessibility specification (via the `public`, `protected`, `internal`, and `private` modifiers), that specification shall agree with all other parts that include an accessibility specification. If no part of a partial type includes an accessibility specification, the type is given the appropriate default accessibility ([§7.5.2](basic-concepts.md#752-declared-accessibility)).
The `abstract`, `sealed`, and `static` modifiers are discussed in the following subclauses.
#### 14.2.2.2 Abstract classes
The `abstract` modifier is used to indicate that a class is incomplete and that it is intended to be used only as a base class. An ***abstract class*** differs from a ***non-abstract class*** in the following ways:
- An abstract class cannot be instantiated directly, and it is a compile-time error to use the `new` operator on an abstract class. While it is possible to have variables and values whose compile-time types are abstract, such variables and values will necessarily either be `null` or contain references to instances of non-abstract classes derived from the abstract types.
- An abstract class is permitted (but not required) to contain abstract members.
- An abstract class cannot be sealed.
When a non-abstract class is derived from an abstract class, the non-abstract class shall include actual implementations of all inherited abstract members, thereby overriding those abstract members.
> *Example*: In the following code
>
> <!-- Example: {template:"standalone-lib", name:"AbstractMethodImplementation"} -->
> ```csharp
> abstract class A
> {
> public abstract void F();
> }
>
> abstract class B : A
> {
> public void G() {}
> }
>
> class C : B
> {
> public override void F()
> {
> // Actual implementation of F
> }
> }
> ```
>
> the abstract class `A` introduces an abstract method `F`. Class `B` introduces an additional method `G`, but since it doesn’t provide an implementation of `F`, `B` shall also be declared abstract. Class `C` overrides `F` and provides an actual implementation. Since there are no abstract members in `C`, `C` is permitted (but not required) to be non-abstract.
>
> *end example*
If one or more parts of a partial type declaration ([§14.2.7](classes.md#1427-partial-declarations)) of a class include the `abstract` modifier, the class is abstract. Otherwise, the class is non-abstract.
#### 14.2.2.3 Sealed classes
The `sealed` modifier is used to prevent derivation from a class. A compile-time error occurs if a sealed class is specified as the base class of another class.
A sealed class cannot also be an abstract class.
> *Note*: The `sealed` modifier is primarily used to prevent unintended derivation, but it also enables certain run-time optimizations. In particular, because a sealed class is known to never have any derived classes, it is possible to transform virtual function member invocations on sealed class instances into non-virtual invocations. *end note*
If one or more parts of a partial type declaration ([§14.2.7](classes.md#1427-partial-declarations)) of a class include the `sealed` modifier, the class is sealed. Otherwise, the class is unsealed.
#### 14.2.2.4 Static classes
##### 14.2.2.4.1 General
The `static` modifier is used to mark the class being declared as a ***static class***. A static class shall not be instantiated, shall not be used as a type and shall contain only static members. Only a static class can contain declarations of extension methods ([§14.6.10](classes.md#14610-extension-methods)).
A static class declaration is subject to the following restrictions:
- A static class shall not include a `sealed` or `abstract` modifier. (However, since a static class cannot be instantiated or derived from, it behaves as if it was both sealed and abstract.)
- A static class shall not include a *class_base* specification ([§14.2.4](classes.md#1424-class-base-specification)) and cannot explicitly specify a base class or a list of implemented interfaces. A static class implicitly inherits from type `object`.
- A static class shall only contain static members ([§14.3.8](classes.md#1438-static-and-instance-members)).
> *Note*: All constants and nested types are classified as static members. *end note*
- A static class shall not have members with `protected`, `private protected`, or `protected internal` declared accessibility.
It is a compile-time error to violate any of these restrictions.
A static class has no instance constructors. It is not possible to declare an instance constructor in a static class, and no default instance constructor ([§14.11.5](classes.md#14115-default-constructors)) is provided for a static class.
The members of a static class are not automatically static, and the member declarations shall explicitly include a `static` modifier (except for constants and nested types). When a class is nested within a static outer class, the nested class is not a static class unless it explicitly includes a `static` modifier.
If one or more parts of a partial type declaration ([§14.2.7](classes.md#1427-partial-declarations)) of a class include the `static` modifier, the class is static. Otherwise, the class is not static.
##### 14.2.2.4.2 Referencing static class types
A *namespace_or_type_name* ([§7.8](basic-concepts.md#78-namespace-and-type-names)) is permitted to reference a static class if
- The *namespace_or_type_name* is the `T` in a *namespace_or_type_name* of the form `T.I`, or
- The *namespace_or_type-name* is the `T` in a *typeof_expression* ([§11.7.16](expressions.md#11716-the-typeof-operator)) of the form `typeof(T)`.
A *primary_expression* ([§11.7](expressions.md#117-primary-expressions)) is permitted to reference a static class if
- The *primary_expression* is the `E` in a *member_access* ([§11.7.6](expressions.md#1176-member-access)) of the form `E.I`.
In any other context, it is a compile-time error to reference a static class.
> *Note*: For example, it is an error for a static class to be used as a base class, a constituent type ([§14.3.7](classes.md#1437-constituent-types)) of a member, a generic type argument, or a type parameter constraint. Likewise, a static class cannot be used in an array type, a pointer type, a new expression, a cast expression, an is expression, an as expression, a `sizeof` expression, or a default value expression. *end note*
### 14.2.3 Type parameters
A type parameter is a simple identifier that denotes a placeholder for a type argument supplied to create a constructed type. By constrast, a type argument ([§8.4.2](types.md#842-type-arguments)) is the type that is substituted for the type parameter when a constructed type is created.
```ANTLR
type_parameter_list
: '<' type_parameters '>'
;
type_parameters
: attributes? type_parameter
| type_parameters ',' attributes? type_parameter
;
```
*type_parameter* is defined in [§8.5](types.md#85-type-parameters).
Each type parameter in a class declaration defines a name in the declaration space ([§7.3](basic-concepts.md#73-declarations)) of that class. Thus, it cannot have the same name as another type parameter of that class or a member declared in that class. A type parameter cannot have the same name as the type itself.
Two partial generic type declarations (in the same program) contribute to the same unbound generic type if they have the same fully qualified name (which includes a *generic_dimension_specifier* ([§11.7.16](expressions.md#11716-the-typeof-operator)) for the number of type parameters) ([§7.8.3](basic-concepts.md#783-fully-qualified-names)). Two such partial type declarations shall specify the same name for each type parameter, in order.
### 14.2.4 Class base specification
#### 14.2.4.1 General
A class declaration may include a *class_base* specification, which defines the direct base class of the class and the interfaces ([§17](interfaces.md#17-interfaces)) directly implemented by the class.
```ANTLR
class_base
: ':' class_type
| ':' interface_type_list
| ':' class_type ',' interface_type_list
;
interface_type_list
: interface_type (',' interface_type)*
;
```
#### 14.2.4.2 Base classes
When a *class_type* is included in the *class_base*, it specifies the direct base class of the class being declared. If a non-partial class declaration has no *class_base*, or if the *class_base* lists only interface types, the direct base class is assumed to be `object`. When a partial class declaration includes a base class specification, that base class specification shall reference the same type as all other parts of that partial type that include a base class specification. If no part of a partial class includes a base class specification, the base class is `object`. A class inherits members from its direct base class, as described in [§14.3.4](classes.md#1434-inheritance).
> *Example*: In the following code
>
> <!-- Example: {template:"standalone-lib", name:"DirectBaseClass"} -->
> ```csharp
> class A {}
> class B : A {}
> ```
>
> Class `A` is said to be the direct base class of `B`, and `B` is said to be derived from `A`. Since `A` does not explicitly specify a direct base class, its direct base class is implicitly `object`.
>
> *end example*
For a constructed class type, including a nested type declared within a generic type declaration ([§14.3.9.7](classes.md#14397-nested-types-in-generic-classes)), if a base class is specified in the generic class declaration, the base class of the constructed type is obtained by substituting, for each *type_parameter* in the base class declaration, the corresponding *type_argument* of the constructed type.
> *Example*: Given the generic class declarations
>
> <!-- Example: {template:"standalone-lib", name:"GenericBaseClass", replaceEllipsis:true} -->
> ```csharp
> class B<U,V> {...}
> class G<T> : B<string,T[]> {...}
> ```
>
> the base class of the constructed type `G<int>` would be `B<string,int[]>`.
>
> *end example*
The base class specified in a class declaration can be a constructed class type ([§8.4](types.md#84-constructed-types)). A base class cannot be a type parameter on its own ([§8.5](types.md#85-type-parameters)), though it can involve the type parameters that are in scope.
> *Example*:
>
> <!-- TODO: This example has been modified to add 1, 2, 3 to the class names. Is that okay? -->
> <!-- Example: {template:"standalone-lib", name:"TypeParameterUsedAsBaseClass", expectedErrors:["CS0689"]} -->
> ```csharp
> class Base<T> {}
>
> // Valid, non-constructed class with constructed base class
> class Extend1 : Base<int> {}
>
> // Error, type parameter used as base class
> class Extend2<V> : V {}
>
> // Valid, type parameter used as type argument for base class
> class Extend3<V> : Base<V> {}
> ```
>
> *end example*
The direct base class of a class type shall be at least as accessible as the class type itself ([§7.5.5](basic-concepts.md#755-accessibility-constraints)). For example, it is a compile-time error for a public class to derive from a private or internal class.
The direct base class of a class type shall not be any of the following types: `System.Array`, `System.Delegate`, `System.Enum`, or `System.ValueType`. Furthermore, a generic class declaration shall not use `System.Attribute` as a direct or indirect base class ([§21.2.1](attributes.md#2121-general)).
In determining the meaning of the direct base class specification `A` of a class `B`, the direct base class of `B` is temporarily assumed to be `object`, which ensures that the meaning of a base class specification cannot recursively depend on itself.
> *Example*: The following
>
> <!-- Example: {template:"standalone-lib", name:"RecursiveBaseClassSpecification", expectedErrors:["CS0146"]} -->
> ```csharp
> class X<T>
> {
> public class Y{}
> }
>
> class Z : X<Z.Y> {}
> ```
>
> is in error since in the base class specification `X<Z.Y>` the direct base class of `Z` is considered to be `object`, and hence (by the rules of [§7.8](basic-concepts.md#78-namespace-and-type-names)) `Z` is not considered to have a member `Y`.
>
> *end example*
The base classes of a class are the direct base class and its base classes. In other words, the set of base classes is the transitive closure of the direct base class relationship.
> *Example*: In the following:
>
> <!-- Example: {template:"standalone-lib", name:"DirectBaseClasses", replaceEllipsis:true} -->
> ```csharp
> class A {...}
> class B<T> : A {...}
> class C<T> : B<IComparable<T>> {...}
> class D<T> : C<T[]> {...}
> ```
>
> the base classes of `D<int>` are `C<int[]>`, `B<IComparable<int[]>>`, `A`, and `object`.
>
> *end example*
Except for class `object`, every class has exactly one direct base class. The `object` class has no direct base class and is the ultimate base class of all other classes.
It is a compile-time error for a class to depend on itself. For the purpose of this rule, a class ***directly depends on*** its direct base class (if any) and *directly depends on* the nearest enclosing class within which it is nested (if any). Given this definition, the complete set of classes upon which a class depends is the transitive closure of the *directly depends on* relationship.
> *Example*: The example
>
> <!-- Example: {template:"standalone-lib", name:"SelfBaseClass", expectedErrors:["CS0146"]} -->
> ```csharp
> class A : A {}
> ```
>
> is erroneous because the class depends on itself. Likewise, the example
>
> <!-- Example: {template:"standalone-lib", name:"CircularBaseClass1", expectedErrors:["CS0146","CS0146","CS0146"]} -->
> ```csharp
> class A : B {}
> class B : C {}
> class C : A {}
> ```
>
> is in error because the classes circularly depend on themselves. Finally, the example
>
> <!-- Example: {template:"standalone-lib", name:"CircularBaseClass2", expectedErrors:["CS0146","CS0146"]} -->
> ```csharp
> class A : B.C {}
> class B : A
> {
> public class C {}
> }
> ```
>
> results in a compile-time error because A depends on `B.C` (its direct base class), which depends on `B` (its immediately enclosing class), which circularly depends on `A`.
>
> *end example*
A class does not depend on the classes that are nested within it.
> *Example*: In the following code
>
> <!-- Example: {template:"standalone-lib", name:"NestedClassDependency"} -->
> ```csharp
> class A
> {
> class B : A {}
> }
> ```
>
> `B` depends on `A` (because `A` is both its direct base class and its immediately enclosing class), but `A` does not depend on `B` (since `B` is neither a base class nor an enclosing class of `A`). Thus, the example is valid.
>
> *end example*
It is not possible to derive from a sealed class.
> *Example*: In the following code
>
> <!-- Example: {template:"standalone-lib", name:"DeriveFromSealedClass", expectedErrors:["CS0509"]} -->
> ```csharp
> sealed class A {}
> class B : A {} // Error, cannot derive from a sealed class
> ```
>
> Class `B` is in error because it attempts to derive from the sealed class `A`.
>
> *end example*
#### 14.2.4.3 Interface implementations
A *class_base* specification may include a list of interface types, in which case the class is said to implement the given interface types. For a constructed class type, including a nested type declared within a generic type declaration ([§14.3.9.7](classes.md#14397-nested-types-in-generic-classes)), each implemented interface type is obtained by substituting, for each *type_parameter* in the given interface, the corresponding *type_argument* of the constructed type.
The set of interfaces for a type declared in multiple parts ([§14.2.7](classes.md#1427-partial-declarations)) is the union of the interfaces specified on each part. A particular interface can only be named once on each part, but multiple parts can name the same base interface(s). There shall only be one implementation of each member of any given interface.
> *Example*: In the following:
>
> ```csharp
> partial class C : IA, IB {...}
> partial class C : IC {...}
> partial class C : IA, IB {...}
> ```
>
> the set of base interfaces for class `C` is `IA`, `IB`, and `IC`.
>
> *end example*
Typically, each part provides an implementation of the interface(s) declared on that part; however, this is not a requirement. A part can provide the implementation for an interface declared on a different part.
> *Example*:
>
> ```csharp
> partial class X
> {
> int IComparable.CompareTo(object o) {...}
> }
>
> partial class X : IComparable
> {
> ...
> }
> ```
>
> *end example*
The base interfaces specified in a class declaration can be constructed interface types ([§8.4](types.md#84-constructed-types), [§17.2](interfaces.md#172-interface-declarations)). A base interface cannot be a type parameter on its own, though it can involve the type parameters that are in scope.
> *Example*: The following code illustrates how a class can implement and extend constructed types:
>
> ```csharp
> class C<U, V> {}
> interface I1<V> {}
> class D : C<string, int>, I1<string> {}
> class E<T> : C<int, T>, I1<T> {}
> ```
>
> *end example*
Interface implementations are discussed further in [§17.6](interfaces.md#176-interface-implementations).
### 14.2.5 Type parameter constraints
Generic type and method declarations can optionally specify type parameter constraints by including *type_parameter_constraints_clause*s.
```ANTLR
type_parameter_constraints_clauses
: type_parameter_constraints_clause
| type_parameter_constraints_clauses type_parameter_constraints_clause
;
type_parameter_constraints_clause
: 'where' type_parameter ':' type_parameter_constraints
;
type_parameter_constraints
: primary_constraint
| secondary_constraints
| constructor_constraint
| primary_constraint ',' secondary_constraints
| primary_constraint ',' constructor_constraint
| secondary_constraints ',' constructor_constraint
| primary_constraint ',' secondary_constraints ',' constructor_constraint
;
primary_constraint
: class_type
| 'class'
| 'struct'
;
secondary_constraints
: interface_type
| type_parameter
| secondary_constraints ',' interface_type
| secondary_constraints ',' type_parameter
;
constructor_constraint
: 'new' '(' ')'
;
```
Each *type_parameter_constraints_clause* consists of the token `where`, followed by the name of a type parameter, followed by a colon and the list of constraints for that type parameter. There can be at most one `where` clause for each type parameter, and the `where` clauses can be listed in any order. Like the `get` and `set` tokens in a property accessor, the `where` token is not a keyword.
The list of constraints given in a `where` clause can include any of the following components, in this order: a single primary constraint, one or more secondary constraints, and the constructor constraint, `new()`.
A primary constraint can be a class type or the ***reference type constraint*** `class` or the ***value type constraint*** `struct`. A secondary constraint can be a *type_parameter* or *interface_type*.
The reference type constraint specifies that a type argument used for the type parameter shall be a reference type. All class types, interface types, delegate types, array types, and type parameters known to be a reference type (as defined below) satisfy this constraint.
The value type constraint specifies that a type argument used for the type parameter shall be a non-nullable value type. All non-nullable struct types, enum types, and type parameters having the value type constraint satisfy this constraint. Note that although classified as a value type, a nullable value type ([§8.3.11](types.md#8311-nullable-value-types)) does not satisfy the value type constraint. A type parameter having the value type constraint shall not also have the *constructor_constraint*, although it may be used as a type argument for another type parameter with a *constructor_constraint*.
> *Note*: The `System.Nullable<T>` type specifies the non-nullable value type constraint for `T`. Thus, recursively constructed types of the forms `T??` and `Nullable<Nullable<T>>` are prohibited. *end note*
Pointer types are never allowed to be type arguments and are not considered to satisfy either the reference type or value type constraints.
If a constraint is a class type, an interface type, or a type parameter, that type specifies a minimal “base type” that every type argument used for that type parameter shall support. Whenever a constructed type or generic method is used, the type argument is checked against the constraints on the type parameter at compile-time. The type argument supplied shall satisfy the conditions described in [§8.4.5](types.md#845-satisfying-constraints).
A *class_type* constraint shall satisfy the following rules:
- The type shall be a class type.
- The type shall not be `sealed`.
- The type shall not be one of the following types: `System.Array`, `System.Delegate`, `System.Enum`, or `System.ValueType`.
- The type shall not be `object`.
- At most one constraint for a given type parameter may be a class type.
A type specified as an *interface_type* constraint shall satisfy the following rules:
- The type shall be an interface type.
- A type shall not be specified more than once in a given `where` clause.
In either case, the constraint may involve any of the type parameters of the associated type or method declaration as part of a constructed type, and may involve the type being declared.
Any class or interface type specified as a type parameter constraint shall be at least as accessible ([§7.5.5](basic-concepts.md#755-accessibility-constraints)) as the generic type or method being declared.
A type specified as a *type_parameter* constraint shall satisfy the following rules:
- The type shall be a type parameter.
- A type shall not be specified more than once in a given `where` clause.
In addition there shall be no cycles in the dependency graph of type parameters, where dependency is a transitive relation defined by:
- If a type parameter `T` is used as a constraint for type parameter `S` then `S` ***depends on*** `T`.
- If a type parameter `S` depends on a type parameter `T` and `T` depends on a type parameter `U` then `S` *depends on* `U`.
Given this relation, it is a compile-time error for a type parameter to depend on itself (directly or indirectly).
Any constraints shall be consistent among dependent type parameters. If type parameter `S` depends on type parameter `T` then:
- `T` shall not have the value type constraint. Otherwise, `T` is effectively sealed so `S` would be forced to be the same type as `T`, eliminating the need for two type parameters.
- If `S` has the value type constraint then `T` shall not have a *class_type* constraint.
- If `S` has a *class_type* constraint `A` and `T` has a *class_type* constraint `B` then there shall be an identity conversion or implicit reference conversion from `A` to `B` or an implicit reference conversion from `B` to `A`.
- If `S` also depends on type parameter `U` and `U` has a *class_type* constraint `A` and `T` has a *class_type* constraint `B` then there shall be an identity conversion or implicit reference conversion from `A` to `B` or an implicit reference conversion from `B` to `A`.
It is valid for `S` to have the value type constraint and `T` to have the reference type constraint. Effectively this limits `T` to the types `System.Object`, `System.ValueType`, `System.Enum`, and any interface type.
If the `where` clause for a type parameter includes a constructor constraint (which has the form `new()`), it is possible to use the `new` operator to create instances of the type ([§11.7.15.2](expressions.md#117152-object-creation-expressions)). Any type argument used for a type parameter with a constructor constraint shall be a value type, a non-abstract class having a public parameterless constructor, or a type parameter having the value type constraint or constructor constraint.
It is a compile-time error for *type_parameter_constraints* having a *primary_constraint* of `struct` to also have a *constructor_constraint*.
> *Example*: The following are examples of constraints:
>
> ```csharp
> interface IPrintable
> {
> void Print();
> }
>
> interface IComparable<T>
> {
> int CompareTo(T value);
> }
>
> interface IKeyProvider<T>
> {
> T GetKey();
> }
>
> class Printer<T> where T : IPrintable {...}
> class SortedList<T> where T : IComparable<T> {...}
>
> class Dictionary<K,V>
> where K : IComparable<K>
> where V : IPrintable, IKeyProvider<K>, new()
> {
> ...
> }
> ```
>
> The following example is in error because it causes a circularity in the dependency graph of the type parameters:
>
> ```csharp
> class Circular<S,T>
> where S: T
> where T: S // Error, circularity in dependency graph
> {
> ...
> }
> ```
>
> The following examples illustrate additional invalid situations:
>
> ```csharp
> class Sealed<S,T>
> where S : T
> where T : struct // Error, `T` is sealed
> {
> ...
> }
>
> class A {...}
> class B {...}
>
> class Incompat<S,T>
> where S : A, T
> where T : B // Error, incompatible class-type constraints
> {
> ...
> }
>
> class StructWithClass<S,T,U>
> where S : struct, T
> where T : U
> where U : A // Error, A incompatible with struct
> {
> ...
> }
> ```
>
> *end example*
The ***dynamic erasure*** of a type `C` is type `Cₓ` constructed as follows:
- If `C` is a nested type `Outer.Inner` then `Cₓ` is a nested type `Outerₓ.Innerₓ`.
- If `C` `Cₓ`is a constructed type `G<A¹, ..., Aⁿ>` with type arguments `A¹, ..., Aⁿ` then `Cₓ` is the constructed type `G<A¹ₓ, ..., Aⁿₓ>`.
- If `C` is an array type `E[]` then `Cₓ` is the array type `Eₓ[]`.
- If `C` is a pointer type `E*` then `Cₓ` is the pointer type `Eₓ*`.
- If `C` is dynamic then `Cₓ` is `object`.
- Otherwise, `Cₓ` is `C`.
The ***effective base class*** of a type parameter `T` is defined as follows:
Let `R` be a set of types such that:
- For each constraint of `T` that is a type parameter, `R` contains its effective base class.
- For each constraint of `T` that is a struct type, `R` contains `System.ValueType`.
- For each constraint of `T` that is an enumeration type, `R` contains `System.Enum`.
- For each constraint of `T` that is a delegate type, `R` contains its dynamic erasure.
- For each constraint of `T` that is an array type, `R` contains `System.Array`.
- For each constraint of `T` that is a class type, `R` contains its dynamic erasure.
Then
- If `T` has the value type constraint, its effective base class is `System.ValueType`.
- Otherwise, if `R` is empty then the effective base class is `object`.
- Otherwise, the effective base class of `T` is the most-encompassed type ([§10.5.3](conversions.md#1053-evaluation-of-user-defined-conversions)) of set `R`. If the set has no encompassed type, the effective base class of `T` is `object`. The consistency rules ensure that the most-encompassed type exists.
If the type parameter is a method type parameter whose constraints are inherited from the base method the effective base class is calculated after type substitution.
These rules ensure that the effective base class is always a *class_type*.
The ***effective interface set*** of a type parameter `T` is defined as follows:
- If `T` has no *secondary_constraints*, its effective interface set is empty.
- If `T` has *interface_type* constraints but no *type_parameter* constraints, its effective interface set is the set of dynamic erasures of its *interface_type* constraints.
- If `T` has no *interface_type* constraints but has *type_parameter* constraints, its effective interface set is the union of the effective interface sets of its *type_parameter* constraints.
- If `T` has both *interface_type* constraints and *type_parameter* constraints, its effective interface set is the union of the set of dynamic erasures of its *interface_type* constraints and the effective interface sets of its *type_parameter* constraints.
A type parameter is *known to be a reference type* if it has the reference type constraint or its effective base class is not `object` or `System.ValueType`.
Values of a constrained type parameter type can be used to access the instance members implied by the constraints.
> *Example*: In the following:
>
> ```csharp
> interface IPrintable
> {
> void Print();
> }
>
> class Printer<T> where T : IPrintable
> {
> void PrintOne(T x) => x.Print();
> }
> ```
>
> the methods of `IPrintable` can be invoked directly on `x` because `T` is constrained to always implement `IPrintable`.
>
> *end example*
When a partial generic type declaration includes constraints, the constraints shall agree with all other parts that include constraints. Specifically, each part that includes constraints shall have constraints for the same set of type parameters, and for each type parameter, the sets of primary, secondary, and constructor constraints shall be equivalent. Two sets of constraints are equivalent if they contain the same members. If no part of a partial generic type specifies type parameter constraints, the type parameters are considered unconstrained.
> *Example*:
>
> ```csharp
> partial class Map<K,V>
> where K : IComparable<K>
> where V : IKeyProvider<K>, new()
> {
> ...
> }
>
> partial class Map<K,V>
> where V : IKeyProvider<K>, new()
> where K : IComparable<K>
> {
> ...
> }
>
> partial class Map<K,V>
> {
> ...
> }
> ```
>
> is correct because those parts that include constraints (the first two) effectively specify the same set of primary, secondary, and constructor constraints for the same set of type parameters, respectively.
>
> *end example*
### 14.2.6 Class body
The *class_body* of a class defines the members of that class.
```ANTLR
class_body
: '{' class_member_declaration* '}'
;
```
### 14.2.7 Partial declarations
The modifier `partial` is used when defining a class, struct, or interface type in multiple parts. The `partial` modifier is a contextual keyword ([§6.4.4](lexical-structure.md#644-keywords)) and only has special meaning immediately before one of the keywords `class`, `struct`, or `interface`.
Each part of a ***partial type*** declaration shall include a `partial` modifier and shall be declared in the same namespace or containing type as the other parts. The `partial` modifier indicates that additional parts of the type declaration might exist elsewhere, but the existence of such additional parts is not a requirement; it is valid for the only declaration of a type to include the `partial` modifier.
All parts of a partial type shall be compiled together such that the parts can be merged at compile-time. Partial types specifically do not allow already compiled types to be extended.
Nested types can be declared in multiple parts by using the `partial` modifier. Typically, the containing type is declared using `partial` as well, and each part of the nested type is declared in a different part of the containing type.
> *Example*: The following partial class is implemented in two parts, which reside in different compilation units. The first part is machine generated by a database-mapping tool while the second part is manually authored:
>
> ```csharp
> public partial class Customer
> {
> private int id;
> private string name;
> private string address;
> private List<Order> orders;
>
> public Customer()
> {
> ...
> }
> }
>
> public partial class Customer
> {
> public void SubmitOrder(Order orderSubmitted) => orders.Add(orderSubmitted);
>
> public bool HasOutstandingOrders() => orders.Count > 0;
> }
> ```
>
> When the two parts above are compiled together, the resulting code behaves as if the class had been written as a single unit, as follows:
>
> ```csharp
> public class Customer
> {
> private int id;
> private string name;
> private string address;
> private List<Order> orders;
>
> public Customer()
> {
> ...
> }
>
> public void SubmitOrder(Order orderSubmitted) => orders.Add(orderSubmitted);
>
> public bool HasOutstandingOrders() => orders.Count > 0;
> }
> ```
>
> *end example*
The handling of attributes specified on the type or type parameters of different parts of a partial declaration is discussed in [§21.3](attributes.md#213-attribute-specification).
## 14.3 Class members
### 14.3.1 General
The members of a class consist of the members introduced by its *class_member_declaration*s and the members inherited from the direct base class.
```ANTLR
class_member_declaration
: constant_declaration
| field_declaration
| method_declaration
| property_declaration
| event_declaration
| indexer_declaration
| operator_declaration
| constructor_declaration
| finalizer_declaration
| static_constructor_declaration
| type_declaration
;
```
The members of a class are divided into the following categories:
- Constants, which represent constant values associated with the class ([§14.4](classes.md#144-constants)).
- Fields, which are the variables of the class ([§14.5](classes.md#145-fields)).
- Methods, which implement the computations and actions that can be performed by the class ([§14.6](classes.md#146-methods)).
- Properties, which define named characteristics and the actions associated with reading and writing those characteristics ([§14.7](classes.md#147-properties)).
- Events, which define notifications that can be generated by the class ([§14.8](classes.md#148-events)).
- Indexers, which permit instances of the class to be indexed in the same way (syntactically) as arrays ([§14.9](classes.md#149-indexers)).
- Operators, which define the expression operators that can be applied to instances of the class ([§14.10](classes.md#1410-operators)).
- Instance constructors, which implement the actions required to initialize instances of the class ([§14.11](classes.md#1411-instance-constructors))
- Finalizers, which implement the actions to be performed before instances of the class are permanently discarded ([§14.13](classes.md#1413-finalizers)).
- Static constructors, which implement the actions required to initialize the class itself ([§14.12](classes.md#1412-static-constructors)).
- Types, which represent the types that are local to the class ([§13.7](namespaces.md#137-type-declarations)).
A *class_declaration* creates a new declaration space ([§7.3](basic-concepts.md#73-declarations)), and the *type_parameter*s and the *class_member_declaration*s immediately contained by the *class_declaration* introduce new members into this declaration space. The following rules apply to *class_member_declaration*s:
- Instance constructors, finalizers, and static constructors shall have the same name as the immediately enclosing class. All other members shall have names that differ from the name of the immediately enclosing class.
- The name of a type parameter in the *type_parameter_list* of a class declaration shall differ from the names of all other type parameters in the same *type_parameter_list* and shall differ from the name of the class and the names of all members of the class.
- The name of a type shall differ from the names of all non-type members declared in the same class. If two or more type declarations share the same fully qualified name, the declarations shall have the `partial` modifier ([§14.2.7](classes.md#1427-partial-declarations)) and these declarations combine to define a single type.
> *Note*: Since the fully qualified name of a type declaration encodes the number of type parameters, two distinct types may share the same name as long as they have different number of type parameters. *end note*
- The name of a constant, field, property, or event shall differ from the names of all other members declared in the same class.
- The name of a method shall differ from the names of all other non-methods declared in the same class. In addition, the signature ([§7.6](basic-concepts.md#76-signatures-and-overloading)) of a method shall differ from the signatures of all other methods declared in the same class, and two methods declared in the same class shall not have signatures that differ solely by `ref` and `out`.
- The signature of an instance constructor shall differ from the signatures of all other instance constructors declared in the same class, and two constructors declared in the same class shall not have signatures that differ solely by `ref` and `out`.
- The signature of an indexer shall differ from the signatures of all other indexers declared in the same class.
- The signature of an operator shall differ from the signatures of all other operators declared in the same class.
The inherited members of a class ([§14.3.4](classes.md#1434-inheritance)) are not part of the declaration space of a class.
> *Note*: Thus, a derived class is allowed to declare a member with the same name or signature as an inherited member (which in effect hides the inherited member). *end note*
The set of members of a type declared in multiple parts ([§14.2.7](classes.md#1427-partial-declarations)) is the union of the members declared in each part. The bodies of all parts of the type declaration share the same declaration space ([§7.3](basic-concepts.md#73-declarations)), and the scope of each member ([§7.7](basic-concepts.md#77-scopes)) extends to the bodies of all the parts. The accessibility domain of any member always includes all the parts of the enclosing type; a private member declared in one part is freely accessible from another part. It is a compile-time error to declare the same member in more than one part of the type, unless that member is a type having the `partial` modifier.
> *Example*:
>
> ```csharp
> partial class A
> {
> int x; // Error, cannot declare x more than once
>
> partial class Inner // Ok, Inner is a partial type
> {
> int y;
> }
> }
>
> partial class A
> {
> int x; // Error, cannot declare x more than once
>
> partial class Inner // Ok, Inner is a partial type
> {
> int z;
> }
> }
> ```
>
> *end example*
Field initialization order can be significant within C# code, and some guarantees are provided, as defined in [§14.5.6.1](classes.md#14561-general). Otherwise, the ordering of members within a type is rarely significant, but may be significant when interfacing with other languages and environments. In these cases, the ordering of members within a type declared in multiple parts is undefined.
### 14.3.2 The instance type
Each class declaration has an associated ***instance type***. For a generic class declaration, the instance type is formed by creating a constructed type ([§8.4](types.md#84-constructed-types)) from the type declaration, with each of the supplied type arguments being the corresponding type parameter. Since the instance type uses the type parameters, it can only be used where the type parameters are in scope; that is, inside the class declaration. The instance type is the type of `this` for code written inside the class declaration. For non-generic classes, the instance type is simply the declared class.
> *Example*: The following shows several class declarations along with their instance types:
>
> ```csharp
> class A<T> // instance type: A<T>
> {
> class B {} // instance type: A<T>.B
> class C<U> {} // instance type: A<T>.C<U>
> }
> class D {} // instance type: D
> ```
>
> *end example*
### 14.3.3 Members of constructed types
The non-inherited members of a constructed type are obtained by substituting, for each *type_parameter* in the member declaration, the corresponding *type_argument* of the constructed type. The substitution process is based on the semantic meaning of type declarations, and is not simply textual substitution.
> *Example*: Given the generic class declaration
>
> ```csharp
> class Gen<T,U>
> {
> public T[,] a;
> public void G(int i, T t, Gen<U,T> gt) {...}
> public U Prop { get {...} set {...} }
> public int H(double d) {...}
> }
> ```
>
> the constructed type `Gen<int[],IComparable<string>>` has the following members:
>
> ```csharp
> public int[,][] a;
> public void G(int i, int[] t, Gen<IComparable<string>,int[]> gt) {...}
> public IComparable<string> Prop { get {...} set {...} }
> public int H(double d) {...}
> ```
>
> The type of the member `a` in the generic class declaration `Gen` is “two-dimensional array of `T`”, so the type of the member `a` in the constructed type above is “two-dimensional array of single-dimensional array of `int`”, or `int[,][]`.
>
> *end example*
Within instance function members, the type of `this` is the instance type ([§14.3.2](classes.md#1432-the-instance-type)) of the containing declaration.
All members of a generic class can use type parameters from any enclosing class, either directly or as part of a constructed type. When a particular closed constructed type ([§8.4.3](types.md#843-open-and-closed-types)) is used at run-time, each use of a type parameter is replaced with the type argument supplied to the constructed type.
> *Example*:
>
> <!-- Example: {template:"standalone-console",name:"TypeParameterSubstitution",expectedOutput:["1","3.1415"]} -->
> ```csharp
> class C<V>
> {
> public V f1;
> public C<V> f2 = null;
>
> public C(V x)
> {
> this.f1 = x;
> this.f2 = this;
> }
> }
>
> class Application
> {
> static void Main()
> {
> C<int> x1 = new C<int>(1);
> Console.WriteLine(x1.f1); // Prints 1
>
> C<double> x2 = new C<double>(3.1415);
> Console.WriteLine(x2.f1); // Prints 3.1415
> }
> }
> ```
>
> *end example*
### 14.3.4 Inheritance
A class ***inherits*** the members of its direct base class. Inheritance means that a class implicitly contains all members of its direct base class, except for the instance constructors, finalizers, and static constructors of the base class. Some important aspects of inheritance are:
- Inheritance is transitive. If `C` is derived from `B`, and `B` is derived from `A`, then `C` inherits the members declared in `B` as well as the members declared in `A`.
- A derived class *extends* its direct base class. A derived class can add new members to those it inherits, but it cannot remove the definition of an inherited member.
- Instance constructors, finalizers, and static constructors are not inherited, but all other members are, regardless of their declared accessibility ([§7.5](basic-concepts.md#75-member-access)). However, depending on their declared accessibility, inherited members might not be accessible in a derived class.
- A derived class can *hide* ([§7.7.2.3](basic-concepts.md#7723-hiding-through-inheritance)) inherited members by declaring new members with the same name or signature. However, hiding an inherited member does not remove that member—it merely makes that member inaccessible directly through the derived class.
- An instance of a class contains a set of all instance fields declared in the class and its base classes, and an implicit conversion ([§10.2.8](conversions.md#1028-implicit-reference-conversions)) exists from a derived class type to any of its base class types. Thus, a reference to an instance of some derived class can be treated as a reference to an instance of any of its base classes.
- A class can declare virtual methods, properties, indexers, and events, and derived classes can override the implementation of these function members. This enables classes to exhibit polymorphic behavior wherein the actions performed by a function member invocation vary depending on the run-time type of the instance through which that function member is invoked.
The inherited members of a constructed class type are the members of the immediate base class type ([§14.2.4.2](classes.md#14242-base-classes)), which is found by substituting the type arguments of the constructed type for each occurrence of the corresponding type parameters in the *base_class_specification*. These members, in turn, are transformed by substituting, for each *type_parameter* in the member declaration, the corresponding *type_argument* of the *base_class_specification*.
> *Example*:
>
> ```csharp
> class B<U>
> {
> public U F(long index) {...}
> }
>
> class D<T> : B<T[]>
> {
> public T G(string s) {...}
> }
> ```
>
> In the code above, the constructed type `D<int>` has a non-inherited member public `int` `G(string s)` obtained by substituting the type argument `int` for the type parameter `T`. `D<int>` also has an inherited member from the class declaration `B`. This inherited member is determined by first determining the base class type `B<int[]>` of `D<int>` by substituting `int` for `T` in the base class specification `B<T[]>`. Then, as a type argument to `B`, `int[]` is substituted for `U` in `public U F(long index)`, yielding the inherited member `public int[] F(long index)`.
>
> *end example*
### 14.3.5 The new modifier
A *class_member_declaration* is permitted to declare a member with the same name or signature as an inherited member. When this occurs, the derived class member is said to *hide* the base class member. See [§7.7.2.3](basic-concepts.md#7723-hiding-through-inheritance) for a precise specification of when a member hides an inherited member.
An inherited member `M` is considered to be ***available*** if `M` is accessible and there is no other inherited accessible member N that already hides `M`. Implicitly hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning unless the declaration of the derived class member includes a `new` modifier to explicitly indicate that the derived member is intended to hide the base member. If one or more parts of a partial declaration ([§14.2.7](classes.md#1427-partial-declarations)) of a nested type include the `new` modifier, no warning is issued if the nested type hides an available inherited member.
If a `new` modifier is included in a declaration that doesn’t hide an available inherited member, a warning to that effect is issued.
### 14.3.6 Access modifiers
A *class_member_declaration* can have any one of the permitted kinds of declared accessibility ([§7.5.2](basic-concepts.md#752-declared-accessibility)): `public`, `protected internal`, `protected`, `private protected`, `internal`, or `private`. Except for the `protected internal` and `private protected` combinations, it is a compile-time error to specify more than one access modifier. When a *class_member_declaration* does not include any access modifiers, `private` is assumed.
### 14.3.7 Constituent types
Types that are used in the declaration of a member are called the ***constituent types*** of that member. Possible constituent types are the type of a constant, field, property, event, or indexer, the return type of a method or operator, and the parameter types of a method, indexer, operator, or instance constructor. The constituent types of a member shall be at least as accessible as that member itself ([§7.5.5](basic-concepts.md#755-accessibility-constraints)).
### 14.3.8 Static and instance members
Members of a class are either ***static members*** or ***instance members***.
> *Note*: Generally speaking, it is useful to think of static members as belonging to classes and instance members as belonging to objects (instances of classes). *end note*
When a field, method, property, event, operator, or constructor declaration includes a `static` modifier, it declares a static member. In addition, a constant or type declaration implicitly declares a static member. Static members have the following characteristics:
- When a static member `M` is referenced in a *member_access* ([§11.7.6](expressions.md#1176-member-access)) of the form `E.M`, `E` shall denote a type that has a member `M`. It is a compile-time error for `E` to denote an instance.
- A static field in a non-generic class identifies exactly one storage location. No matter how many instances of a non-generic class are created, there is only ever one copy of a static field. Each distinct closed constructed type ([§8.4.3](types.md#843-open-and-closed-types)) has its own set of static fields, regardless of the number of instances of the closed constructed type.
- A static function member (method, property, event, operator, or constructor) does not operate on a specific instance, and it is a compile-time error to refer to this in such a function member.
When a field, method, property, event, indexer, constructor, or finalizer declaration does not include a static modifier, it declares an instance member. (An instance member is sometimes called a non-static member.) Instance members have the following characteristics:
- When an instance member `M` is referenced in a *member_access* ([§11.7.6](expressions.md#1176-member-access)) of the form `E.M`, `E` shall denote an instance of a type that has a member `M`. It is a binding-time error for E to denote a type.
- Every instance of a class contains a separate set of all instance fields of the class.
- An instance function member (method, property, indexer, instance constructor, or finalizer) operates on a given instance of the class, and this instance can be accessed as `this` ([§11.7.12](expressions.md#11712-this-access)).
> *Example*: The following example illustrates the rules for accessing static and instance members:
>
> ```csharp
> class Test
> {
> int x;
> static int y;
> void F()
> {
> x = 1; // Ok, same as this.x = 1
> y = 1; // Ok, same as Test.y = 1
> }
>
> static void G()
> {
> x = 1; // Error, cannot access this.x
> y = 1; // Ok, same as Test.y = 1
> }
>
> static void Main()
> {
> Test t = new Test();
> t.x = 1; // Ok
> t.y = 1; // Error, cannot access static member through instance
> Test.x = 1; // Error, cannot access instance member through type
> Test.y = 1; // Ok
> }
> }
> ```
>
> The `F` method shows that in an instance function member, a *simple_name* ([§11.7.4](expressions.md#1174-simple-names)) can be used to access both instance members and static members. The `G` method shows that in a static function member, it is a compile-time error to access an instance member through a *simple_name*. The `Main` method shows that in a *member_access* ([§11.7.6](expressions.md#1176-member-access)), instance members shall be accessed through instances, and static members shall be accessed through types.
>
> *end example*
### 14.3.9 Nested types
#### 14.3.9.1 General
A type declared within a class or struct is called a ***nested type***. A type that is declared within a compilation unit or namespace is called a ***non-nested type***.
> *Example*: In the following example:
>
> ```csharp
> using System;