SınıflarClasses

Sınıf veri üyeleri (sabitler ve alanlar), işlev üyeleri (Yöntemler, özellikler, olaylar, Dizin oluşturucular, işleçler, örnek oluşturucular, Yıkıcılar ve statik oluşturucular) ve iç içe türler içerebilen bir veri yapısıdır.A class is a data structure that may contain data members (constants and fields), function members (methods, properties, events, indexers, operators, instance constructors, destructors and static constructors), and nested types. Sınıf türleri, türetilmiş bir sınıfın bir temel sınıfı genişletebileceği ve özelleştirileceği bir mekanizma olan devralmayı destekler.Class types support inheritance, a mechanism whereby a derived class can extend and specialize a base class.

Sınıf bildirimleriClass declarations

Class_declaration , yeni bir sınıf bildiren bir type_declaration (tür bildirimleri).A class_declaration is a type_declaration (Type declarations) that declares a new class.

class_declaration
    : attributes? class_modifier* 'partial'? 'class' identifier type_parameter_list?
      class_base? type_parameter_constraints_clause* class_body ';'?
    ;

Class_declaration , isteğe bağlı bir öznitelik kümesinden (öznitelikler) ve ardından isteğe bağlı bir class_modifier s kümesiyle (sınıf değiştiricileri) oluşur. sonra isteğe bağlı bir değiştirici, ardından bir isteğe bağlı bir partial class Type_parameter_list (tür parametreleri) ve ardından isteğe bağlı bir class_base belirtimi (sınıf temel belirtimi) ve ardından, isteğe bağlı bir type_parameter_constraints_clause s (tür parametresi kısıtlamaları) ve ardından bir class_body (sınıf gövdesi) ve daha sonra noktalı virgül gelen bir tanımlayıcı tarafından izlenir.A class_declaration consists of an optional set of attributes (Attributes), followed by an optional set of class_modifier s (Class modifiers), followed by an optional partial modifier, followed by the keyword class and an identifier that names the class, followed by an optional type_parameter_list (Type parameters), followed by an optional class_base specification (Class base specification) , followed by an optional set of type_parameter_constraints_clause s (Type parameter constraints), followed by a class_body (Class body), optionally followed by a semicolon.

Bir sınıf bildirimi, ayrıca bir type_parameter_list sağlamadıkça type_parameter_constraints_clause s 'yi sağlayaamaz.A class declaration cannot supply type_parameter_constraints_clause s unless it also supplies a type_parameter_list.

Bir type_parameter_list sağlayan bir sınıf bildirimi, Genel sınıf bildirimidir.A class declaration that supplies a type_parameter_list is a generic class declaration. Ayrıca, bir genel sınıf bildiriminde iç içe yerleştirilmiş olan herhangi bir sınıf ya da genel bir yapı bildirimi, oluşturulmuş bir tür oluşturmak için, kapsayan türün tür parametreleri sağlanmalıdır.Additionally, any class nested inside a generic class declaration or a generic struct declaration is itself a generic class declaration, since type parameters for the containing type must be supplied to create a constructed type.

Sınıf değiştiricileriClass modifiers

Class_declaration , isteğe bağlı olarak bir sınıf değiştiricileri dizisi içerebilir:A class_declaration may optionally include a sequence of class modifiers:

class_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'abstract'
    | 'sealed'
    | 'static'
    | class_modifier_unsafe
    ;

Aynı değiştiricinin bir sınıf bildiriminde birden çok kez görünmesi için derleme zamanı hatası vardır.It is a compile-time error for the same modifier to appear multiple times in a class declaration.

newİç içe sınıflarda değiştiriciye izin verilir.The new modifier is permitted on nested classes. Bu, sınıfın, Yeni değiştiricibölümünde açıklandığı gibi, devralınan bir üyeyi aynı adla gizlediğini belirtir.It specifies that the class hides an inherited member by the same name, as described in The new modifier. newDeğiştiricinin iç içe geçmiş sınıf bildirimi olmayan bir sınıf bildiriminde görünmesi için derleme zamanı hatası.It is a compile-time error for the new modifier to appear on a class declaration that is not a nested class declaration.

public,, protected internal Ve private değiştiricileri sınıfının erişilebilirliğini denetler.The public, protected, internal, and private modifiers control the accessibility of the class. Sınıf bildiriminin gerçekleştiği içeriğe bağlı olarak, bu değiştiricilerin bazılarına izin verilmeyebilir (belirtilen erişilebilirlik).Depending on the context in which the class declaration occurs, some of these modifiers may not be permitted (Declared accessibility).

abstract, sealed Ve static değiştiricileri aşağıdaki bölümlerde ele alınmıştır.The abstract, sealed and static modifiers are discussed in the following sections.

Soyut sınıflarAbstract classes

abstractDeğiştirici, bir sınıfın tamamlanmamış olduğunu ve yalnızca temel sınıf olarak kullanılması amaçlanan olduğunu göstermek için kullanılır.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. Soyut bir sınıf, soyut olmayan bir sınıftan aşağıdaki yollarla farklılık gösterir:An abstract class differs from a non-abstract class in the following ways:

  • Soyut bir sınıf doğrudan başlatılamaz ve bir derleme zamanı hatası, new işleci bir soyut sınıfta kullanılır.An abstract class cannot be instantiated directly, and it is a compile-time error to use the new operator on an abstract class. Derleme zamanı türleri soyut olan değişkenler ve değerler olması mümkün olsa da, bu tür değişkenler ve değerler, null soyut türlerden türetilmiş soyut olmayan sınıfların örneklerine başvuru ya da içermeli.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.
  • Soyut bir sınıfa, soyut Üyeler içermesi için izin verilir (ancak gerekli değildir).An abstract class is permitted (but not required) to contain abstract members.
  • Soyut bir sınıf korumalı olamaz.An abstract class cannot be sealed.

Soyut olmayan bir sınıf, soyut bir sınıftan türetilmişse, soyut olmayan sınıfın devralınan tüm soyut üyelerin gerçek uygulamalarını içermesi gerekir, böylece bu soyut üyeleri geçersiz kılar.When a non-abstract class is derived from an abstract class, the non-abstract class must include actual implementations of all inherited abstract members, thereby overriding those abstract members. ÖrnekteIn the example

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
    }
}

Soyut sınıf, A soyut bir yöntem sunar F .the abstract class A introduces an abstract method F. Sınıfı B ek bir yöntem tanıtır G , ancak uygulamasının bir uygulamasını sağlamadığından F , soyut olarak B da bildirilmelidir.Class B introduces an additional method G, but since it doesn't provide an implementation of F, B must also be declared abstract. Sınıfı C geçersiz kılar F ve gerçek bir uygulama sağlar.Class C overrides F and provides an actual implementation. İçinde soyut üye olmadığından C , C soyut olmayan olması için izin verilir (ancak zorunlu değildir).Since there are no abstract members in C, C is permitted (but not required) to be non-abstract.

Mühürlü sınıflarSealed classes

sealedDeğiştirici, bir sınıftan türetmeye engel olmak için kullanılır.The sealed modifier is used to prevent derivation from a class. Bir Sealed sınıfı, başka bir sınıfın temel sınıfı olarak belirtilmişse, derleme zamanı hatası oluşur.A compile-time error occurs if a sealed class is specified as the base class of another class.

Sealed bir sınıf de soyut bir sınıf olamaz.A sealed class cannot also be an abstract class.

sealedDeğiştirici, genellikle istenmeden Türetmenin önlenmesi için kullanılır, ancak belirli çalışma zamanı iyileştirmeleri de sağlar.The sealed modifier is primarily used to prevent unintended derivation, but it also enables certain run-time optimizations. Özellikle, korumalı bir sınıfın hiç türetilmiş sınıfa sahip olmadığı bilindiğinden, korumalı sınıf örneklerine sanal işlev üye çağırmaları sanal olmayan çağırmaları dönüştürmek mümkündür.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.

Statik sınıflarStatic classes

staticDeğiştirici, bir statik sınıf olarak bildirildiği sınıfı işaretlemek için kullanılır.The static modifier is used to mark the class being declared as a static class. Statik bir sınıf örneği oluşturulamıyor, tür olarak kullanılamaz ve yalnızca statik üyeleri içerebilir.A static class cannot be instantiated, cannot be used as a type and can contain only static members. Yalnızca bir statik sınıf uzantı yöntemlerinin bildirimlerini içerebilir (Uzantı yöntemleri).Only a static class can contain declarations of extension methods (Extension methods).

Statik sınıf bildirimi aşağıdaki kısıtlamalara tabidir:A static class declaration is subject to the following restrictions:

  • Statik bir sınıf, sealed veya abstract değiştiricisini içeremez.A static class may not include a sealed or abstract modifier. Ancak, statik bir sınıf tarafından örneklenemez veya türetilmediği için, hem korumalı hem de soyut gibi davranır.Note, however, that since a static class cannot be instantiated or derived from, it behaves as if it was both sealed and abstract.
  • Statik bir sınıf class_base belirtimi (sınıf taban belirtimi) içeremez ve açıkça bir temel sınıf veya uygulanan arabirimlerin listesini belirtemez.A static class may not include a class_base specification (Class base specification) and cannot explicitly specify a base class or a list of implemented interfaces. Statik bir sınıf örtülü olarak türünden devralınır object .A static class implicitly inherits from type object.
  • Statik bir sınıf yalnızca statik Üyeler (statik ve örnek üyeleri) içerebilir.A static class can only contain static members (Static and instance members). Sabitler ve iç içe geçmiş türlerin statik üye olarak sınıflandırıldığını unutmayın.Note that constants and nested types are classified as static members.
  • Statik bir sınıf, erişilebilirliği olan veya tarafından tanımlanan üyelere sahip olamaz protected protected internal .A static class cannot have members with protected or protected internal declared accessibility.

Bu kısıtlamaların herhangi birini ihlal etmek için derleme zamanı hatası vardır.It is a compile-time error to violate any of these restrictions.

Statik bir sınıfın örnek oluşturucuları yok.A static class has no instance constructors. Statik bir sınıfta örnek Oluşturucu bildirmek mümkün değildir ve statik bir sınıf için varsayılan örnek Oluşturucu (Varsayılan oluşturucular) sağlanmaz.It is not possible to declare an instance constructor in a static class, and no default instance constructor (Default constructors) is provided for a static class.

Statik bir sınıfın üyeleri otomatik olarak statik değildir ve üye bildirimlerinin açıkça bir değiştirici içermesi gerekir static (sabitler ve iç içe türler hariç).The members of a static class are not automatically static, and the member declarations must explicitly include a static modifier (except for constants and nested types). Bir sınıf statik bir dış sınıf içinde iç içe olduğunda, açıkça bir değiştirici içermiyorsa, iç içe yerleştirilmiş sınıf statik bir sınıf değildir static .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.

Statik Sınıf türlerine başvurmaReferencing static class types

Bir namespace_or_type_name (ad alanı ve tür adları), şu durumlarda bir statik sınıfa başvurmak için izin verilirA namespace_or_type_name (Namespace and type names) is permitted to reference a static class if

  • Namespace_or_type_name , T formun namespace_or_type_name T.I veyaThe namespace_or_type_name is the T in a namespace_or_type_name of the form T.I, or
  • Namespace_or_type_name , T formun bir typeof_expression (bağımsız değişken listeleri1) typeof(T) .The namespace_or_type_name is the T in a typeof_expression (Argument lists1) of the form typeof(T).

Bir primary_expression (işlev üyeleri), şu durumlarda bir statik sınıfa başvurmak için izin verilirA primary_expression (Function members) is permitted to reference a static class if

Diğer bir bağlamda, statik bir sınıfa başvurmak için derleme zamanı hatası olur.In any other context it is a compile-time error to reference a static class. Örneğin, bir statik sınıfın temel sınıf olarak kullanılabilmesi, bir üyenin bir bileşen türü (Iç içe türler), bir genel tür bağımsız değişkeni veya tür parametresi kısıtlaması olması hatadır.For example, it is an error for a static class to be used as a base class, a constituent type (Nested types) of a member, a generic type argument, or a type parameter constraint. Benzer şekilde, bir statik sınıf dizi türünde, bir işaretçi türü, bir new ifade, bir tür dönüştürme ifadesi, is ifade, as ifade, sizeof ifade veya varsayılan değer ifadesi içinde kullanılamaz.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.

Kısmi değiştiriciPartial modifier

partialDeğiştirici, bu class_declaration kısmi bir tür bildirimi olduğunu göstermek için kullanılır.The partial modifier is used to indicate that this class_declaration is a partial type declaration. Bir kapsayan ad alanı veya tür bildiriminde aynı ada sahip birden çok kısmi tür bildirimi, kısmi türlerdebelirtilen kurallara göre tek bir tür bildirimi oluşturmak için birleştirilir.Multiple partial type declarations with the same name within an enclosing namespace or type declaration combine to form one type declaration, following the rules specified in Partial types.

Program metninin ayrı kesimleri üzerinde dağıtılan bir sınıf bildiriminin olması, bu parçaların farklı bağlamlarda üretilmesi veya saklanması durumunda yararlı olabilir.Having the declaration of a class distributed over separate segments of program text can be useful if these segments are produced or maintained in different contexts. Örneğin, bir sınıf bildiriminin bir kısmı makine tarafından oluşturulmuş olabilir, diğeri el ile yazılır.For instance, one part of a class declaration may be machine generated, whereas the other is manually authored. İki ' un metinsel ayrımı, diğer bir güncelleştirme ile çakışma arasından güncelleştirme yapılmasını engeller.Textual separation of the two prevents updates by one from conflicting with updates by the other.

Tür parametreleriType parameters

Tür parametresi, oluşturulmuş bir tür oluşturmak için sağlanan bir tür bağımsız değişkeni için yer tutucuyu belirten basit bir tanıtıcıdır.A type parameter is a simple identifier that denotes a placeholder for a type argument supplied to create a constructed type. Tür parametresi, daha sonra sağlanacak bir tür için resmi yer tutucudur.A type parameter is a formal placeholder for a type that will be supplied later. Buna karşılık, bir tür bağımsız değişkeni (tür bağımsız değişkenleri) oluşturulmuş bir tür oluşturulduğunda tür parametresi için değiştirilen gerçek türdür.By contrast, a type argument (Type arguments) is the actual type that is substituted for the type parameter when a constructed type is created.

type_parameter_list
    : '<' type_parameters '>'
    ;

type_parameters
    : attributes? type_parameter
    | type_parameters ',' attributes? type_parameter
    ;

type_parameter
    : identifier
    ;

Bir sınıf bildirimindeki her tür parametresi, bu sınıfın bildirim alanında (bildirimlerinde) bir ad tanımlar.Each type parameter in a class declaration defines a name in the declaration space (Declarations) of that class. Bu nedenle, başka bir tür parametresiyle aynı ada veya bu sınıfta belirtilen bir üyeye sahip olamaz.Thus, it cannot have the same name as another type parameter or a member declared in that class. Tür parametresi, türün kendisiyle aynı ada sahip olamaz.A type parameter cannot have the same name as the type itself.

Sınıf temel belirtimiClass base specification

Sınıf bildirimi, sınıfının doğrudan temel sınıfını ve doğrudan sınıf tarafından uygulanan arabirimleri (arabirimler) tanımlayan bir class_base belirtimi içerebilir.A class declaration may include a class_base specification, which defines the direct base class of the class and the interfaces (Interfaces) directly implemented by the class.

class_base
    : ':' class_type
    | ':' interface_type_list
    | ':' class_type ',' interface_type_list
    ;

interface_type_list
    : interface_type (',' interface_type)*
    ;

Sınıf bildiriminde belirtilen temel sınıf, oluşturulmuş bir sınıf türü (oluşturulmuş türler) olabilir.The base class specified in a class declaration can be a constructed class type (Constructed types). Bir temel sınıf kendi üzerinde bir tür parametresi olamaz, ancak kapsamdaki tür parametreleri de içerebilir.A base class cannot be a type parameter on its own, though it can involve the type parameters that are in scope.

class Extend<V>: V {}            // Error, type parameter used as base class

Temel sınıflarBase classes

Class_base bir class_type dahil edildiğinde, bildirildiği sınıfın doğrudan temel sınıfını belirtir.When a class_type is included in the class_base, it specifies the direct base class of the class being declared. Bir sınıf bildiriminde class_base yoksa veya class_base yalnızca arabirim türlerini listelemeli, doğrudan taban sınıfın olduğu varsayılır object .If a class declaration has no class_base, or if the class_base lists only interface types, the direct base class is assumed to be object. Bir sınıf, Devralmabölümünde açıklandığı gibi doğrudan temel sınıfından üyeleri devralır.A class inherits members from its direct base class, as described in Inheritance.

ÖrnekteIn the example

class A {}

class B: A {}

sınıfının A doğrudan taban sınıfı olduğu söylenir B ve B öğesinden türetilmiştik A .class A is said to be the direct base class of B, and B is said to be derived from A. AAçıkça doğrudan bir temel sınıf belirtmediğinden, doğrudan temel sınıfı örtülü olarak bulunur object .Since A does not explicitly specify a direct base class, its direct base class is implicitly object.

Oluşturulmuş bir sınıf türü için, genel sınıf bildiriminde bir temel sınıf belirtilmişse, oluşturulan türün temel sınıfı, temel sınıf bildirimindeki her bir type_parameter , oluşturulan türün karşılık gelen type_argument yerine koyarak elde edilir.For a constructed class type, 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. Genel sınıf bildirimleri verildiğindeGiven the generic class declarations

class B<U,V> {...}

class G<T>: B<string,T[]> {...}

oluşturulan türün temel sınıfı olur G<int> B<string,int[]> .the base class of the constructed type G<int> would be B<string,int[]>.

Bir sınıf türünün doğrudan temel sınıfı en az sınıf türünün kendisi (erişilebilirlik etki alanları) olarak erişilebilir olmalıdır.The direct base class of a class type must be at least as accessible as the class type itself (Accessibility domains). Örneğin, public bir sınıf için bir veya sınıfından türetmeye yönelik derleme zamanı hatası olur private internal .For example, it is a compile-time error for a public class to derive from a private or internal class.

Bir sınıf türünün doğrudan temel sınıfı şu türlerden biri olmamalıdır: System.Array , System.Delegate , System.MulticastDelegate , System.Enum veya System.ValueType .The direct base class of a class type must not be any of the following types: System.Array, System.Delegate, System.MulticastDelegate, System.Enum, or System.ValueType. Ayrıca, genel bir sınıf bildirimi System.Attribute doğrudan veya dolaylı temel sınıf olarak kullanılamaz.Furthermore, a generic class declaration cannot use System.Attribute as a direct or indirect base class.

Bir sınıfın doğrudan temel sınıf belirtiminin anlamı belirlenirken A B , öğesinin doğrudan taban sınıfının B geçici olarak olduğu varsayılır object .While 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. Intuicanlı bu, bir temel sınıf belirtiminin anlamını özyinelemeli olarak kendi kendine bağımlı olmamasını sağlar.Intuitively this ensures that the meaning of a base class specification cannot recursively depend on itself. Örnek:The example:

class A<T> {
   public class B {}
}

class C : A<C.B> {}

temel sınıf belirtiminde bu yana hata durumunda, A<C.B> öğesinin doğrudan taban sınıfı olarak C kabul edilir object ve bu nedenle ( ad alanı ve tür adlarıkuralları tarafından) C bir üyeye sahip olduğu kabul edilmez B .is in error since in the base class specification A<C.B> the direct base class of C is considered to be object, and hence (by the rules of Namespace and type names) C is not considered to have a member B.

Bir sınıf türünün temel sınıfları doğrudan taban sınıfıdır ve temel sınıflarıdır.The base classes of a class type are the direct base class and its base classes. Diğer bir deyişle, temel sınıfların kümesi doğrudan temel sınıf ilişkisinin geçişli kapanışı olur.In other words, the set of base classes is the transitive closure of the direct base class relationship. Yukarıdaki örneğe başvurarak, temel sınıfları B ve ' dir A object .Referring to the example above, the base classes of B are A and object. ÖrnekteIn the example

class A {...}

class B<T>: A {...}

class C<T>: B<IComparable<T>> {...}

class D<T>: C<T[]> {...}

temel sınıfları,, D<int> C<int[]> B<IComparable<int[]>> A ve object .the base classes of D<int> are C<int[]>, B<IComparable<int[]>>, A, and object.

Sınıf dışında object , her sınıf türünün tam olarak bir doğrudan temel sınıfı vardır.Except for class object, every class type has exactly one direct base class. objectSınıfın doğrudan temel sınıfı yoktur ve diğer tüm sınıfların en son temel sınıfıdır.The object class has no direct base class and is the ultimate base class of all other classes.

Bir sınıf bir B sınıftan A türetildiği zaman, için derleme zamanı hatası olur A B .When a class B derives from a class A, it is a compile-time error for A to depend on B. Bir sınıf doğrudan kendi temel sınıfına (varsa) bağlıdır ve doğrudan iç içe geçmiş (varsa) sınıfa _bağlıdır*_ .A class directly depends on _ its direct base class (if any) and _directly depends on*_ the class within which it is immediately nested (if any). Bu tanım verildiğinde, bir sınıfın bağımlı olduğu tüm sınıf kümesi, _ öğesinin yansımalı ve geçişli kapanışı doğrudan * ilişkisine bağlıdır.Given this definition, the complete set of classes upon which a class depends is the reflexive and transitive closure of the _ directly depends on* relationship.

ÖrnekteThe example

class A: A {}

sınıf kendi kendine bağımlı olduğundan hatalı.is erroneous because the class depends on itself. Benzer şekilde, örnekLikewise, the example

class A: B {}
class B: C {}
class C: A {}

sınıfların kendilerine döngüsel olarak bağımlı olması nedeniyle hata oluştu.is in error because the classes circularly depend on themselves. Son olarak, örnekFinally, the example

class A: B.C {}

class B: A
{
    public class C {}
}

bir derleme zamanı hatasına neden olur çünkü ( A doğrudan kapsayan sınıfa) bağlı olan (kendisine ait B.C olan sınıf), bu, döngüsel olarak B değişir A .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.

Bir sınıfın içinde iç içe yerleştirilmiş sınıflara bağlı olmadığına unutmayın.Note that a class does not depend on the classes that are nested within it. ÖrnekteIn the example

class A
{
    class B: A {}
}

B öğesine bağlıdır A (çünkü A hem doğrudan temel sınıfı hem de onun hemen kapsayan sınıfı olduğundan), ancak A bağımlı değildir (çünkü B B , kendisi bir temel sınıf veya kapsayan bir sınıf değildir 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). Bu nedenle, örnek geçerlidir.Thus, the example is valid.

Bir sınıftan türetmek mümkün değildir sealed .It is not possible to derive from a sealed class. ÖrnekteIn the example

sealed class A {}

class B: A {}            // Error, cannot derive from a sealed class

sınıf B , sınıftan türemeye çalıştığı için hatalı sealed A .class B is in error because it attempts to derive from the sealed class A.

Arabirim UygulamalarıInterface implementations

Bir class_base belirtimi, arabirim türlerinin bir listesini içerebilir ve bu durumda sınıf verilen arabirim türlerini doğrudan uygulayacak şekilde söylenir.A class_base specification may include a list of interface types, in which case the class is said to directly implement the given interface types. Arabirim Uygulamaları, arabirim uygulamalarındadaha ayrıntılı bir şekilde ele alınmıştır.Interface implementations are discussed further in Interface implementations.

Tür parametresi kısıtlamalarıType parameter constraints

Genel tür ve yöntem bildirimleri, isteğe bağlı olarak type_parameter_constraints_clause s ekleyerek tür parametresi kısıtlamalarını belirtebilir.Generic type and method declarations can optionally specify type parameter constraints by including type_parameter_constraints_clause s.

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' '(' ')'
    ;

Her type_parameter_constraints_clause , belirteci where , ardından bir tür parametresinin adından, ardından iki nokta üst üste ve bu tür parametresi için kısıtlamaların listesine sahip.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. whereHer tür parametresi için en fazla bir yan tümce olabilir ve where yan tümceler herhangi bir sırada listelenebilir.There can be at most one where clause for each type parameter, and the where clauses can be listed in any order. get set Bir özellik erişimcisindeki ve belirteçleri gibi, where belirteç bir anahtar sözcük değildir.Like the get and set tokens in a property accessor, the where token is not a keyword.

Bir yan tümcesinde verilen kısıtlamaların listesi, where Şu bileşenlerden herhangi birini içerebilir: tek bir birincil kısıtlama, bir veya daha fazla ikincil kısıtlama ve Oluşturucu kısıtlaması new() .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().

Birincil kısıtlama bir sınıf türü veya başvuru türü kısıtlaması _ class veya _değer türü kısıtlaması*_ olabilir struct .A primary constraint can be a class type or the reference type constraint _ class or the _value type constraint*_ struct. İkincil kısıtlama bir _type_parameter * veya interface_type olabilir.A secondary constraint can be a _type_parameter* or interface_type.

Başvuru türü kısıtlaması, tür parametresi için kullanılan bir tür bağımsız değişkeninin bir başvuru türü olması gerektiğini belirtir.The reference type constraint specifies that a type argument used for the type parameter must be a reference type. Tüm sınıf türleri, arabirim türleri, temsilci türleri, dizi türleri ve başvuru türü olarak bilinen tür parametreleri (aşağıda tanımlandığı gibi), bu kısıtlamayı karşılar.All class types, interface types, delegate types, array types, and type parameters known to be a reference type (as defined below) satisfy this constraint.

Değer türü kısıtlaması, tür parametresi için kullanılan bir tür bağımsız değişkeninin null yapılamayan bir değer türü olması gerektiğini belirtir.The value type constraint specifies that a type argument used for the type parameter must be a non-nullable value type. Bu kısıtlamayı karşılayan, null olamayan tüm yapı türleri, sabit listesi türleri ve değer türü kısıtlamasına sahip tür parametreleri.All non-nullable struct types, enum types, and type parameters having the value type constraint satisfy this constraint. Değer türü olarak sınıflandırıldığından, null yapılabilir bir tür (null yapılabilir türler) değer türü kısıtlamasını karşılamadığına unutmayın.Note that although classified as a value type, a nullable type (Nullable types) does not satisfy the value type constraint. Değer türü kısıtlamasına sahip bir tür parametresi de constructor_constraint sahip olamaz.A type parameter having the value type constraint cannot also have the constructor_constraint.

İşaretçi türlerinin hiçbir şekilde tür bağımsız değişkeni olmasına izin verilmez ve başvuru türü veya değer türü kısıtlamalarını karşılamak için düşünülmez.Pointer types are never allowed to be type arguments and are not considered to satisfy either the reference type or value type constraints.

Bir kısıtlama bir sınıf türü, bir arabirim türü veya bir tür parametresi ise, bu tür parametresi için kullanılan her tür bağımsız değişkenin desteklemesi gereken en az "temel türü" değeri belirtir.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 must support. Oluşturulmuş bir tür veya genel yöntem kullanıldığında, tür bağımsız değişkeni derleme zamanında tür parametresindeki kısıtlamalara karşı denetlenir.Whenever a constructed type or generic method is used, the type argument is checked against the constraints on the type parameter at compile-time. Sağlanan tür bağımsız değişkeni, kısıtlamalarıkarşıladığı koşullarda açıklanan koşullara uymalıdır.The type argument supplied must satisfy the conditions described in Satisfying constraints.

Class_type kısıtlamasının aşağıdaki kuralları karşılaması gerekir:A class_type constraint must satisfy the following rules:

  • Tür bir sınıf türü olmalıdır.The type must be a class type.
  • Türün olmaması gerekir sealed .The type must not be sealed.
  • Tür şu türlerden biri olmalıdır: System.Array , System.Delegate , System.Enum veya System.ValueType .The type must not be one of the following types: System.Array, System.Delegate, System.Enum, or System.ValueType.
  • Türün olmaması gerekir object .The type must not be object. Tüm türler öğesinden türetildiğinden object , böyle bir kısıtlama izin verildiğinde hiçbir etkiye sahip olmaz.Because all types derive from object, such a constraint would have no effect if it were permitted.
  • Verilen tür parametresi için en fazla bir kısıtlama bir sınıf türü olabilir.At most one constraint for a given type parameter can be a class type.

İnterface_type kısıtlaması olarak belirtilen bir türün aşağıdaki kuralları karşılaması gerekir:A type specified as an interface_type constraint must satisfy the following rules:

  • Tür bir arabirim türü olmalıdır.The type must be an interface type.
  • Bir tür, verili bir yan tümce içinde birden çok kez belirtilmemelidir where .A type must not be specified more than once in a given where clause.

Her iki durumda da kısıtlama, oluşturulmuş bir türün parçası olarak ilişkili tür veya yöntem bildiriminin herhangi bir tür parametresini içerebilir ve bu tür, bildirildiği türü içerebilir.In either case, the constraint can involve any of the type parameters of the associated type or method declaration as part of a constructed type, and can involve the type being declared.

Tür parametresi kısıtlaması olarak belirtilen herhangi bir sınıf veya arabirim türünün, bildirildiği genel tür veya yöntem olarak en az erişilebilir (Erişilebilirlik kısıtlamaları) olması gerekir.Any class or interface type specified as a type parameter constraint must be at least as accessible (Accessibility constraints) as the generic type or method being declared.

Type_parameter kısıtlaması olarak belirtilen bir türün aşağıdaki kuralları karşılaması gerekir:A type specified as a type_parameter constraint must satisfy the following rules:

  • Tür bir tür parametresi olmalıdır.The type must be a type parameter.
  • Bir tür, verili bir yan tümce içinde birden çok kez belirtilmemelidir where .A type must not be specified more than once in a given where clause.

Ayrıca, bağımlılık grafiğinde tür parametrelerinin bağımlılık grafiğinde bir döngü olmaması gerekir; burada bağımlılık, tarafından tanımlanan geçişli bir ilişki olur:In addition there must be no cycles in the dependency graph of type parameters, where dependency is a transitive relation defined by:

  • Bir tür parametresi T tür parametresi için kısıtlama olarak kullanılırsa, S S öğesine bağlıdır T .If a type parameter T is used as a constraint for type parameter S then S depends on T.
  • Bir tür parametresi bir tür parametresine bağımlıysa ve bir tür parametresine bağımlıysa, S T T U S öğesine bağımlıdır U .If a type parameter S depends on a type parameter T and T depends on a type parameter U then S depends on U.

Bu ilişki verildiğinde, bir tür parametresinin kendisine (doğrudan veya dolaylı olarak) bağımlı olması için derleme zamanı hatası vardır.Given this relation, it is a compile-time error for a type parameter to depend on itself (directly or indirectly).

Herhangi bir kısıtlama bağımlı tür parametreleri arasında tutarlı olmalıdır.Any constraints must be consistent among dependent type parameters. Tür parametresi S daha sonra tür parametresine bağımlıysa T :If type parameter S depends on type parameter T then:

  • T değer türü kısıtlamasına sahip olmamalıdır.T must not have the value type constraint. Aksi takdirde, T etkin bir şekilde mühürlenmiş olduğundan S T , iki tür parametresi gereksinimini ortadan kaldıran aynı türde olmaya zorlanır.Otherwise, T is effectively sealed so S would be forced to be the same type as T, eliminating the need for two type parameters.
  • SDeğer türü kısıtlaması varsa, T class_type kısıtlamasına sahip olmamalıdır.If S has the value type constraint then T must not have a class_type constraint.
  • S Class_type kısıtlaması varsa A ve bir class_type kısıtlaması varsa, ' den ' a bir T B kimlik dönüştürme veya A B B A örtük başvuru dönüştürme olmalıdır.If S has a class_type constraint A and T has a class_type constraint B then there must be an identity conversion or implicit reference conversion from A to B or an implicit reference conversion from B to A.
  • SAyrıca tür parametresine bağımlıdır U ve U bir class_type kısıtlamasına sahiptir ve bir A class_type kısıtlaması varsa, ' den ' a bir T B kimlik dönüştürmesi veya A B B A örtük başvuru dönüştürme olmalıdır.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 must be an identity conversion or implicit reference conversion from A to B or an implicit reference conversion from B to A.

SDeğer türü kısıtlamasına sahip olmak ve T başvuru türü kısıtlamasına sahip olmak için geçerlidir.It is valid for S to have the value type constraint and T to have the reference type constraint. Bu türler, T System.Object System.ValueType , System.Enum , ve herhangi bir arabirim türü için etkili bir şekilde sınırlandırılmıştır.Effectively this limits T to the types System.Object, System.ValueType, System.Enum, and any interface type.

whereBir tür parametresi için yan tümce bir Oluşturucu kısıtlaması içeriyorsa (formun bulunduğu new() ), new türü örnekleri oluşturmak için işlecini kullanmak mümkündür (nesne oluşturma ifadeleri).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 (Object creation expressions). Oluşturucu kısıtlaması olan bir tür parametresi için kullanılan herhangi bir tür bağımsız değişkeni Ortak parametresiz bir oluşturucuya sahip olmalıdır (Bu Oluşturucu herhangi bir değer türü için örtülü olarak bulunur) veya değer türü kısıtlaması veya Oluşturucu kısıtlamasına sahip bir tür parametresi olmalıdır (Ayrıntılar için bkz. tür parametresi kısıtlamaları ).Any type argument used for a type parameter with a constructor constraint must have a public parameterless constructor (this constructor implicitly exists for any value type) or be a type parameter having the value type constraint or constructor constraint (see Type parameter constraints for details).

Kısıtlamaların örnekleri aşağıda verilmiştir:The following are examples of constraints:

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()
{
    ...
}

Tür parametrelerinin bağımlılık grafiğinde bir döngüye neden olduğu için aşağıdaki örnek hata durumunda:The following example is in error because it causes a circularity in the dependency graph of the type parameters:

class Circular<S,T>
    where S: T
    where T: S                // Error, circularity in dependency graph
{
    ...
}

Aşağıdaki örneklerde, ek geçersiz durumlar gösterilmektedir:The following examples illustrate additional invalid situations:

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
{
    ...
}

Bir tür parametresinin etkin temel sınıfı T aşağıdaki gibi tanımlanır:The effective base class of a type parameter T is defined as follows:

  • TBirincil kısıtlamaları veya tür parametresi kısıtlamalarına sahip değilse, etkin taban sınıfı olur object .If T has no primary constraints or type parameter constraints, its effective base class is object.
  • TDeğer türü kısıtlamasına sahipse, etkin taban sınıfı olur System.ValueType .If T has the value type constraint, its effective base class is System.ValueType.
  • T Class_type kısıtlaması varsa C ancak type_parameter kısıtlama yoksa, etkin taban sınıfı olur C .If T has a class_type constraint C but no type_parameter constraints, its effective base class is C.
  • T Class_type kısıtlaması yoksa, ancak bir veya daha fazla type_parameter kısıtlaması varsa, kendi etkin taban sınıfı type_parameter kısıtlamalarının etkin temel sınıfları kümesindeki en kapsamlı tür (yükseltilmemiş dönüştürme işleçleri).If T has no class_type constraint but has one or more type_parameter constraints, its effective base class is the most encompassed type (Lifted conversion operators) in the set of effective base classes of its type_parameter constraints. Tutarlılık kuralları, bu tür bir en kapsamlı türün mevcut olmasını güvence altına alıyor.The consistency rules ensure that such a most encompassed type exists.
  • THem bir class_type kısıtlaması hem de bir veya daha fazla type_parameter kısıtlaması varsa, etkin taban sınıfı, ' nin class_type kısıtlamasından ve type_parameter kısıtlamalarının etkin temel sınıflarından oluşan kümesinde en çok kullanılan türdür (yükseltilmemiş dönüştürme işleçleri) T . If T has both a class_type constraint and one or more type_parameter constraints, its effective base class is the most encompassed type (Lifted conversion operators) in the set consisting of the class_type constraint of T and the effective base classes of its type_parameter constraints. Tutarlılık kuralları, bu tür bir en kapsamlı türün mevcut olmasını güvence altına alıyor.The consistency rules ensure that such a most encompassed type exists.
  • TBaşvuru türü kısıtlaması varsa ancak class_type kısıtlamaları yoksa, etkin taban sınıfı olur object .If T has the reference type constraint but no class_type constraints, its effective base class is object.

Bu kuralların amacına yönelik olarak, T 'nin bir value_type kısıtlaması varsa V , bunun yerine V bir class_type olan en özel temel türü kullanın.For the purpose of these rules, if T has a constraint V that is a value_type, use instead the most specific base type of V that is a class_type. Bu, açıkça verilen kısıtlamada asla gerçekleşmeyebilir, ancak genel bir yöntemin kısıtlamaları geçersiz kılan bir yöntem bildirimi veya bir arabirim yönteminin açık bir uygulamasıyla dolaylı olarak devralındığında gerçekleşebilir.This can never happen in an explicitly given constraint, but may occur when the constraints of a generic method are implicitly inherited by an overriding method declaration or an explicit implementation of an interface method.

Bu kurallar, etkin temel sınıfın her zaman bir class_type olduğundan emin olur.These rules ensure that the effective base class is always a class_type.

Bir tür parametresinin etkin arabirim kümesi T Şu şekilde tanımlanır:The effective interface set of a type parameter T is defined as follows:

  • T Secondary_constraints yoksa, etkin arabirimi kümesi boştur.If T has no secondary_constraints, its effective interface set is empty.
  • T İnterface_type kısıtlamaları varsa ancak type_parameter kısıtlama yoksa, etkin arabirimi kümesi interface_type kısıtlamaları kümesidir.If T has interface_type constraints but no type_parameter constraints, its effective interface set is its set of interface_type constraints.
  • T İnterface_type kısıtlaması yoksa ancak type_parameter kısıtlamaları varsa, etkin arabirim kümesi, type_parameter kısıtlamalarının etkin arabirim kümelerinin birleşimidir.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.
  • THem interface_type kısıtlamaları hem de type_parameter kısıtlamalarına sahipse, etkin arabirim kümesi, kendi interface_type kısıtlamaları kümesinin ve type_parameter kısıtlamalarının etkin arabirim kümelerinin birleşimidir.If T has both interface_type constraints and type_parameter constraints, its effective interface set is the union of its set of interface_type constraints and the effective interface sets of its type_parameter constraints.

Bir tür parametresinin başvuru türü kısıtlaması varsa veya etkin taban sınıfı veya değilse, başvuru türü olarak bilinir object System.ValueType .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.

Kısıtlanmış tür parametre türünün değerleri, kısıtlamalar tarafından kapsanan örnek üyelerine erişmek için kullanılabilir.Values of a constrained type parameter type can be used to access the instance members implied by the constraints. ÖrnekteIn the example

interface IPrintable
{
    void Print();
}

class Printer<T> where T: IPrintable
{
    void PrintOne(T x) {
        x.Print();
    }
}

yöntemi, IPrintable x T her zaman uygulanması kısıtlanan için doğrudan üzerinde çağrılabilir IPrintable .the methods of IPrintable can be invoked directly on x because T is constrained to always implement IPrintable.

Sınıf gövdesiClass body

Bir sınıfın class_body , bu sınıfın üyelerini tanımlar.The class_body of a class defines the members of that class.

class_body
    : '{' class_member_declaration* '}'
    ;

Kısmi türlerPartial types

Bir tür bildirimi, birden çok Kısmi tür bildirimine bölünebilir.A type declaration can be split across multiple partial type declarations. Tür bildirimi, bu bölümdeki kurallara göre, programın derleme zamanı ve çalışma zamanı işlemenin geri kalanı sırasında tek bir bildirim olarak değerlendirilmesinin ardından parçalarından oluşturulur.The type declaration is constructed from its parts by following the rules in this section, whereupon it is treated as a single declaration during the remainder of the compile-time and run-time processing of the program.

Bir class_declaration, struct_declaration veya interface_declaration , bir değiştirici içeriyorsa kısmi tür bildirimini temsil eder partial .A class_declaration, struct_declaration or interface_declaration represents a partial type declaration if it includes a partial modifier. partial bir anahtar sözcük değildir ve yalnızca anahtar sözcüklerden birinden class struct veya bir interface tür bildiriminde ya da bir void yöntem bildiriminde bulunan türden önce görünürse bir değiştirici işlevi görür.partial is not a keyword, and only acts as a modifier if it appears immediately before one of the keywords class, struct or interface in a type declaration, or before the type void in a method declaration. Diğer bağlamlarda, normal tanımlayıcı olarak kullanılabilir.In other contexts it can be used as a normal identifier.

Kısmi tür bildiriminin her bölümü bir partial değiştirici içermelidir.Each part of a partial type declaration must include a partial modifier. Aynı ada sahip olmalıdır ve diğer bölümlerle aynı ad alanında veya tür bildiriminde bildirilmelidir.It must have the same name and be declared in the same namespace or type declaration as the other parts. partialDeğiştirici, tür bildiriminin ek bölümlerinin başka bir yerde mevcut olabileceğini gösterir, ancak bu tür ek parçaların varlığı bir gereksinim değildir; değiştiricisini içermesi için tek bir bildirime sahip bir tür için geçerlidir partial .The partial modifier indicates that additional parts of the type declaration may exist elsewhere, but the existence of such additional parts is not a requirement; it is valid for a type with a single declaration to include the partial modifier.

Kısmi bir türün tüm bölümlerinin, parçaların derleme zamanında tek bir tür bildirimine birleştirilebilmesi için birlikte derlenmesi gerekir.All parts of a partial type must be compiled together such that the parts can be merged at compile-time into a single type declaration. Kısmi türler özellikle derlenmiş türlerin genişletilmesini izin vermez.Partial types specifically do not allow already compiled types to be extended.

İç içe türler, değiştirici kullanılarak birden çok bölümde tanımlanmış olabilir partial .Nested types may be declared in multiple parts by using the partial modifier. Genellikle, kapsayan tür kullanılarak da tanımlanır partial ve iç içe türün her bölümü, kapsayan türün farklı bir bölümünde belirtilir.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.

partialTemsilci veya Enum bildirimlerinde değiştiriciye izin verilmez.The partial modifier is not permitted on delegate or enum declarations.

ÖzniteliklerAttributes

Kısmi bir türün öznitelikleri belirtilmemiş bir sıra, parçaların her birinin öznitelikleri birleştirilerek belirlenir.The attributes of a partial type are determined by combining, in an unspecified order, the attributes of each of the parts. Bir öznitelik birden çok parçaya yerleştirilmişse, öznitelik türü üzerinde birden çok kez belirtmeye eşdeğerdir.If an attribute is placed on multiple parts, it is equivalent to specifying the attribute multiple times on the type. Örneğin, iki bölüm:For example, the two parts:

[Attr1, Attr2("hello")]
partial class A {}

[Attr3, Attr2("goodbye")]
partial class A {}

, şöyle bir bildirime eşdeğerdir:are equivalent to a declaration such as:

[Attr1, Attr2("hello"), Attr3, Attr2("goodbye")]
class A {}

Tür parametrelerinin öznitelikleri benzer bir biçimde birleştirir.Attributes on type parameters combine in a similar fashion.

DeğiştiricilerModifiers

Kısmi bir tür bildirimi bir erişilebilirlik belirtimi (,, public protected internal ve değiştiricileri) içerdiğinde, private bir erişilebilirlik belirtimi içeren diğer tüm bölümleri kabul etmelidir.When a partial type declaration includes an accessibility specification (the public, protected, internal, and private modifiers) it must agree with all other parts that include an accessibility specification. Kısmi bir türün hiçbir bölümü bir erişilebilirlik belirtimi içeriyorsa, türe uygun varsayılan erişilebilirlik (belirtilenErişilebilirlik) verilir.If no part of a partial type includes an accessibility specification, the type is given the appropriate default accessibility (Declared accessibility).

İç içe bir türün bir veya daha fazla kısmi bildirimi bir new değiştirici içeriyorsa, iç içe geçmiş türü devralınan bir üyeyi gizliyor (Devralma yoluyla gizleme) için uyarı bildirilir.If one or more partial declarations of a nested type include a new modifier, no warning is reported if the nested type hides an inherited member (Hiding through inheritance).

Bir sınıfın bir veya daha fazla kısmi bildirimi bir değiştirici içeriyorsa abstract , sınıf soyut (soyut sınıflar) olarak değerlendirilir.If one or more partial declarations of a class include an abstract modifier, the class is considered abstract (Abstract classes). Aksi takdirde, sınıfı Özet olmayan olarak kabul edilir.Otherwise, the class is considered non-abstract.

Bir sınıfın bir veya daha fazla kısmi bildirimi bir değiştirici içeriyorsa sealed , sınıf sealed (Sealed sınıflar) olarak kabul edilir.If one or more partial declarations of a class include a sealed modifier, the class is considered sealed (Sealed classes). Aksi takdirde, sınıfı korumasız kabul edilir.Otherwise, the class is considered unsealed.

Bir sınıfın hem abstract hem de Sealed olamayacağını unutmayın.Note that a class cannot be both abstract and sealed.

unsafeDeğiştirici kısmi bir tür bildiriminde kullanıldığında, yalnızca bu belirli parça güvenli olmayan bir bağlam (güvenli olmayan bağlamlar) olarak kabul edilir.When the unsafe modifier is used on a partial type declaration, only that particular part is considered an unsafe context (Unsafe contexts).

Tür parametreleri ve kısıtlamalarıType parameters and constraints

Genel bir tür birden çok bölümde bildirilirse, her parçanın tür parametrelerini durumu olması gerekir.If a generic type is declared in multiple parts, each part must state the type parameters. Her parçanın aynı sayıda tür parametreleri ve her tür parametresi için aynı adı sırasıyla aynı olmalıdır.Each part must have the same number of type parameters, and the same name for each type parameter, in order.

Kısmi genel tür bildiriminde kısıtlamalar (yan tümceler) varsa, kısıtlamalar, kısıtlamaları içeren where diğer tüm bölümleri kabul etmelidir.When a partial generic type declaration includes constraints (where clauses), the constraints must agree with all other parts that include constraints. Özellikle, kısıtlamaları içeren her parçanın aynı tür parametreleri kümesi için kısıtlamaları olmalıdır ve her tür parametresi için, birincil, ikincil ve Oluşturucu kısıtlamalarının kümelerinin eşdeğeri olması gerekir.Specifically, each part that includes constraints must have constraints for the same set of type parameters, and for each type parameter the sets of primary, secondary, and constructor constraints must be equivalent. İki kısıtlama kümesi aynı üyeleri içeriyorsa eşdeğerdir.Two sets of constraints are equivalent if they contain the same members. Kısmi bir genel türün hiçbir bölümü tür parametresi kısıtlamalarını belirtiyorsa tür parametreleri Kısıtlanmamış olarak kabul edilir.If no part of a partial generic type specifies type parameter constraints, the type parameters are considered unconstrained.

ÖrnekteThe example

partial class Dictionary<K,V>
    where K: IComparable<K>
    where V: IKeyProvider<K>, IPersistable
{
    ...
}

partial class Dictionary<K,V>
    where V: IPersistable, IKeyProvider<K>
    where K: IComparable<K>
{
    ...
}

partial class Dictionary<K,V>
{
    ...
}

, kısıtlamaları (ilk iki) içeren parçalar, sırasıyla aynı tür parametreleri kümesi için aynı birincil, ikincil ve Oluşturucu kısıtlamaları kümesini etkin bir şekilde belirttiğinden doğrudur.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.

Temel sınıfBase class

Kısmi bir sınıf bildirimi bir temel sınıf belirtimi içerdiğinde, temel sınıf belirtimi içeren diğer tüm bölümleri kabul etmelidir.When a partial class declaration includes a base class specification it must agree with all other parts that include a base class specification. Kısmi bir sınıfın hiçbir bölümü bir temel sınıf belirtimi içeriyorsa, taban sınıf System.Object (temel sınıflar) olur.If no part of a partial class includes a base class specification, the base class becomes System.Object (Base classes).

Temel arabirimlerBase interfaces

Birden çok bölümde belirtilen bir türün temel arabirimler kümesi, her bölümde belirtilen temel arabirimlerin birleşimidir.The set of base interfaces for a type declared in multiple parts is the union of the base interfaces specified on each part. Belirli bir temel arabirim her bölümde yalnızca bir kez adlandırılabilir, ancak birden fazla parçanın aynı temel arabirimleri adlandırmasına izin verilir.A particular base interface may only be named once on each part, but it is permitted for multiple parts to name the same base interface(s). Yalnızca belirli bir temel arabirimin üyelerinin bir uygulanması gerekir.There must only be one implementation of the members of any given base interface.

ÖrnekteIn the example

partial class C: IA, IB {...}

partial class C: IC {...}

partial class C: IA, IB {...}

sınıfı için temel arabirimler kümesi, C ve ' IA dir IB IC .the set of base interfaces for class C is IA, IB, and IC.

Genellikle, her parça bu bölümde belirtilen arabirim (ler) in bir uygulamasını sağlar; Ancak, bu bir gereksinim değildir.Typically, each part provides an implementation of the interface(s) declared on that part; however, this is not a requirement. Bir bölüm, farklı bir bölümde belirtilen bir arabirim için uygulama sağlayabilir:A part may provide the implementation for an interface declared on a different part:

partial class X
{
    int IComparable.CompareTo(object o) {...}
}

partial class X: IComparable
{
    ...
}

ÜyelerMembers

Kısmi yöntemlerin (kısmi Yöntemler) dışında, birden çok bölümde belirtilen bir türün üyeleri kümesi, her bölümde belirtilen üye kümesinin birleşimidir.With the exception of partial methods (Partial methods), the set of members of a type declared in multiple parts is simply the union of the set of members declared in each part. Tür bildiriminin tüm bölümlerinin gövdeleri aynı bildirim alanını (Bildirimler) ve her üyenin kapsamını (kapsamlar) paylaşır ve tüm parçaların gövdeleriyle birlikte genişletilir.The bodies of all parts of the type declaration share the same declaration space (Declarations), and the scope of each member (Scopes) extends to the bodies of all the parts. Herhangi bir üyenin erişilebilirlik etki alanı her zaman kapsayan türün tüm parçalarını içerir; private tek bir bölümde belirtilen bir üyeye başka bir bölümden serbestçe erişilebilir.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. Üyenin değiştiriciyle bir tür olmadığı durumlar dışında, türün birden fazla bölümünde aynı üyeyi bildirmek için derleme zamanı hatası vardır partial .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 with the partial modifier.

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;
    }
}

Bir tür içindeki üyelerin sıralaması, C# kodu için nadiren önemlidir, ancak diğer diller ve ortamlarla arabirim oluştururken önemli olabilir.The ordering of members within a type is rarely significant to C# code, but may be significant when interfacing with other languages and environments. Bu durumlarda, birden çok bölümde belirtilen bir tür içindeki üyelerin sıralaması tanımsızdır.In these cases, the ordering of members within a type declared in multiple parts is undefined.

Kısmi YöntemlerPartial methods

Kısmi Yöntemler, bir tür bildiriminin bir bölümünde tanımlanabilir ve başka bir şekilde uygulanabilir.Partial methods can be defined in one part of a type declaration and implemented in another. Uygulama isteğe bağlıdır; kısmi yöntemi herhangi bir bölüm uygularsa, kısmi yöntem bildirimi ve buna yapılan tüm çağrılar, parçaların birleşiminden kaynaklanan tür bildiriminden kaldırılır.The implementation is optional; if no part implements the partial method, the partial method declaration and all calls to it are removed from the type declaration resulting from the combination of the parts.

Kısmi Yöntemler erişim değiştiricilerini tanımlanamaz, ancak örtülü olarak bulunur private .Partial methods cannot define access modifiers, but are implicitly private. Dönüş türü olmalıdır void ve parametreleri out değiştiriciye sahip olamaz.Their return type must be void, and their parameters cannot have the out modifier. Tanımlayıcı, partial bir yöntem bildiriminde yalnızca türden önce görünürse özel bir anahtar sözcük olarak tanınır void ; Aksi takdirde, normal tanımlayıcı olarak kullanılabilir.The identifier partial is recognized as a special keyword in a method declaration only if it appears right before the void type; otherwise it can be used as a normal identifier. Kısmi bir yöntem, arabirim yöntemlerini açıkça uygulayamaz.A partial method cannot explicitly implement interface methods.

İki tür kısmi yöntem bildirimi vardır: Yöntem bildiriminin gövdesi bir noktalı virgül ise, bildirim bir *tanımlayan kısmi yöntem bildirimi _ olarak kabul edilir.There are two kinds of partial method declarations: If the body of the method declaration is a semicolon, the declaration is said to be a *defining partial method declaration _. Gövde bir _block * olarak verilirse, bildirim bir Uygulama kısmi yöntem bildirimi olarak kabul edilir.If the body is given as a _block*, the declaration is said to be an implementing partial method declaration. Bir tür bildiriminin bölümlerinde, belirli bir imzayla yalnızca bir adet kısmi yöntem bildirimi tanımlama olabilir ve belirli bir imzaya sahip kısmi yöntem bildirimi yalnızca bir uygulama olabilir.Across the parts of a type declaration there can be only one defining partial method declaration with a given signature, and there can be only one implementing partial method declaration with a given signature. Bir uygulama kısmi yöntem bildirimi verilirse, karşılık gelen bir tanımlayıcı kısmi yöntem bildirimi mevcut olmalıdır ve bildirimlerin aşağıdaki gibi eşleşmesi gerekir:If an implementing partial method declaration is given, a corresponding defining partial method declaration must exist, and the declarations must match as specified in the following:

  • Bildirimlerin aynı değiştiricilere sahip olması gerekir (aynı sırada olması olmasa da), yöntem adı, tür parametrelerinin sayısı ve parametre sayısı.The declarations must have the same modifiers (although not necessarily in the same order), method name, number of type parameters and number of parameters.
  • Bildirimlerdeki karşılık gelen parametreler aynı değiştiricilere sahip olmalıdır (aynı sırada olması olmasa da) ve aynı türlerdir (tür parametre adlarında mod farklılıkları).Corresponding parameters in the declarations must have the same modifiers (although not necessarily in the same order) and the same types (modulo differences in type parameter names).
  • Bildirimlerdeki karşılık gelen tür parametreleri aynı kısıtlamalara (tür parametresi adlarında mod farklılıkları) sahip olmalıdır.Corresponding type parameters in the declarations must have the same constraints (modulo differences in type parameter names).

Uygulama kısmi yöntem bildirimi, karşılık gelen tanımlayan kısmi Yöntem bildirimiyle aynı bölümde bulunabilir.An implementing partial method declaration can appear in the same part as the corresponding defining partial method declaration.

Yalnızca tanımlama bir kısmi yöntem aşırı yükleme çözümüne katılır.Only a defining partial method participates in overload resolution. Bu nedenle, bir uygulama bildiriminin verilip verilmediğini belirtir, çağırma ifadeleri kısmi yöntemin çağırmaları için çözüm alabilir.Thus, whether or not an implementing declaration is given, invocation expressions may resolve to invocations of the partial method. Kısmi bir yöntem her zaman döndürdüğü için void , böyle bir çağırma ifadesi her zaman ifade deyimleri olur.Because a partial method always returns void, such invocation expressions will always be expression statements. Ayrıca, kısmi bir yöntem örtük olarak olduğu için private , bu tür deyimler her zaman kısmi yöntemin bildirildiği tür bildiriminin parçalarından biri içinde gerçekleşir.Furthermore, because a partial method is implicitly private, such statements will always occur within one of the parts of the type declaration within which the partial method is declared.

Kısmi bir tür bildiriminin hiçbir bölümü verili bir kısmi Yöntem için uygulama bildirimi içermiyorsa, çağıran herhangi bir ifade deyimi yalnızca Birleşik tür bildiriminden kaldırılır.If no part of a partial type declaration contains an implementing declaration for a given partial method, any expression statement invoking it is simply removed from the combined type declaration. Bu nedenle, bileşen ifadeleri dahil olmak üzere çağırma ifadesinin çalışma zamanında hiçbir etkisi yoktur.Thus the invocation expression, including any constituent expressions, has no effect at run-time. Kısmi yöntemin kendisi de kaldırılır ve birleştirilmiş tür bildiriminin üyesi olmayacaktır.The partial method itself is also removed and will not be a member of the combined type declaration.

Belirli bir kısmi Yöntem için uygulama bildirimi varsa, kısmi yöntemlerin etkinleştirmeleri korunur.If an implementing declaration exist for a given partial method, the invocations of the partial methods are retained. Kısmi Yöntem, aşağıdaki durumlar hariç, uygulama kısmi Yöntem bildirimine benzer bir yöntem bildirimine göre artış sağlar:The partial method gives rise to a method declaration similar to the implementing partial method declaration except for the following:

  • partialDeğiştirici dahil değildirThe partial modifier is not included
  • Elde edilen yöntem bildiriminde bulunan öznitelikler, tanımlama ve Uygulama kısmi Yöntem bildiriminin belirtilmemiş sırada tanımlanmasının Birleşik öznitelikleridir.The attributes in the resulting method declaration are the combined attributes of the defining and the implementing partial method declaration in unspecified order. Yinelemeler kaldırılmaz.Duplicates are not removed.
  • Sonuç yöntemi bildiriminin parametreleri üzerindeki öznitelikleri, tanımlanmasının karşılık gelen parametrelerinin Birleşik öznitelikleridir ve kısmi Yöntem bildiriminin uygulanması belirtilmemiş sırayla yapılır.The attributes on the parameters of the resulting method declaration are the combined attributes of the corresponding parameters of the defining and the implementing partial method declaration in unspecified order. Yinelemeler kaldırılmaz.Duplicates are not removed.

Bir tanımlama bildirimi ve kısmi Yöntem için bir uygulama bildirimi verilmezse, aşağıdaki kısıtlamalar uygulanır:If a defining declaration but not an implementing declaration is given for a partial method M, the following restrictions apply:

Kısmi Yöntemler, bir tür bildiriminin bir bölümünün bir araç tarafından oluşturulan başka bir parçanın davranışını özelleştirmesine izin vermek için yararlıdır.Partial methods are useful for allowing one part of a type declaration to customize the behavior of another part, e.g., one that is generated by a tool. Aşağıdaki kısmi sınıf bildirimini göz önünde bulundurun:Consider the following partial class declaration:

partial class Customer
{
    string name;

    public string Name {
        get { return name; }
        set {
            OnNameChanging(value);
            name = value;
            OnNameChanged();
        }

    }

    partial void OnNameChanging(string newName);

    partial void OnNameChanged();
}

Bu sınıf başka herhangi bir bölüm olmadan derlenirse, tanımlayıcı kısmi yöntem bildirimleri ve bunların etkinleştirmeleri kaldırılır ve sonuçta elde edilen birleştirilmiş sınıf bildirimi aşağıdaki gibi olacaktır:If this class is compiled without any other parts, the defining partial method declarations and their invocations will be removed, and the resulting combined class declaration will be equivalent to the following:

class Customer
{
    string name;

    public string Name {
        get { return name; }
        set { name = value; }
    }
}

Ancak kısmi yöntemlerin uygulama bildirimlerini sağlayan başka bir bölüme verildiğini varsayalım:Assume that another part is given, however, which provides implementing declarations of the partial methods:

partial class Customer
{
    partial void OnNameChanging(string newName)
    {
        Console.WriteLine("Changing " + name + " to " + newName);
    }

    partial void OnNameChanged()
    {
        Console.WriteLine("Changed to " + name);
    }
}

Sonuç olarak elde edilen birleştirilmiş sınıf bildirimi, aşağıdaki gibi olacaktır:Then the resulting combined class declaration will be equivalent to the following:

class Customer
{
    string name;

    public string Name {
        get { return name; }
        set {
            OnNameChanging(value);
            name = value;
            OnNameChanged();
        }

    }

    void OnNameChanging(string newName)
    {
        Console.WriteLine("Changing " + name + " to " + newName);
    }

    void OnNameChanged()
    {
        Console.WriteLine("Changed to " + name);
    }
}

Ad bağlamaName binding

Genişletilebilir bir türün her bölümü aynı ad alanı içinde bildirilmelidir, ancak parçalar genellikle farklı ad alanı bildirimleri içinde yazılır.Although each part of an extensible type must be declared within the same namespace, the parts are typically written within different namespace declarations. Bu nedenle, using her bölüm için farklı yönergeler (yönergeler kullanılarak) bulunabilir.Thus, different using directives (Using directives) may be present for each part. Tek bir bölüm içindeki basit adları (tür çıkarımı) yorumlarken, yalnızca using o parçayı kapsayan ad alanı bildiriminin yönergeleri göz önünde bulundurululur.When interpreting simple names (Type inference) within one part, only the using directives of the namespace declaration(s) enclosing that part are considered. Bu, farklı parçalardan farklı anlamlara sahip olan aynı tanımlayıcıya neden olabilir:This may result in the same identifier having different meanings in different parts:

namespace N
{
    using List = System.Collections.ArrayList;

    partial class A
    {
        List x;                // x has type System.Collections.ArrayList
    }
}

namespace N
{
    using List = Widgets.LinkedList;

    partial class A
    {
        List y;                // y has type Widgets.LinkedList
    }
}

Sınıf üyeleriClass members

Bir sınıfın üyeleri, class_member_declaration s tarafından tanıtılan üyelerden ve doğrudan temel sınıftan devralınan üyelere oluşur.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.

class_member_declaration
    : constant_declaration
    | field_declaration
    | method_declaration
    | property_declaration
    | event_declaration
    | indexer_declaration
    | operator_declaration
    | constructor_declaration
    | destructor_declaration
    | static_constructor_declaration
    | type_declaration
    ;

Bir sınıf türünün üyeleri aşağıdaki kategorilere ayrılmıştır:The members of a class type are divided into the following categories:

  • Sınıfla ilişkili sabit değerleri temsil eden sabitler (sabitler).Constants, which represent constant values associated with the class (Constants).
  • Sınıfının değişkenleri olan alanlar (alanlar).Fields, which are the variables of the class (Fields).
  • Sınıfı tarafından gerçekleştirilebilecek hesaplamalar ve eylemleri uygulayan Yöntemler (Yöntemler).Methods, which implement the computations and actions that can be performed by the class (Methods).
  • Adlandırılmış özellikleri ve bu özellikleri okuma ve yazma ile ilişkili eylemleri tanımlayan Özellikler (Özellikler).Properties, which define named characteristics and the actions associated with reading and writing those characteristics (Properties).
  • Sınıfı tarafından oluşturulabilecek bildirimleri tanımlayan Olaylar (Olaylar).Events, which define notifications that can be generated by the class (Events).
  • Dizin oluşturucular, sınıf örneklerinin (sözdizimsel) diziler (Dizin oluşturucular) ile aynı şekilde dizine eklenmesine izin verir.Indexers, which permit instances of the class to be indexed in the same way (syntactically) as arrays (Indexers).
  • İşleç, sınıfının örneklerine uygulanabilen ifade işleçlerini tanımlar (işleçler).Operators, which define the expression operators that can be applied to instances of the class (Operators).
  • Sınıf örneklerinin başlatılması için gereken eylemleri uygulayan örnek oluşturucular (örnek oluşturucular)Instance constructors, which implement the actions required to initialize instances of the class (Instance constructors)
  • Sınıf örneklerinin kalıcı olarak atılmadan önce gerçekleştirilecek eylemleri uygulayan yok ediciler (Yıkıcılar).Destructors, which implement the actions to be performed before instances of the class are permanently discarded (Destructors).
  • Sınıfının kendisini (statik oluşturucular) başlatmak için gereken eylemleri uygulayan statik oluşturucular.Static constructors, which implement the actions required to initialize the class itself (Static constructors).
  • , Sınıfının yerel olan türlerini temsil eden türler (Iç içe türler).Types, which represent the types that are local to the class (Nested types).

Yürütülebilir kod içerebilen Üyeler topluca sınıf türünün işlev üyeleri olarak bilinir.Members that can contain executable code are collectively known as the function members of the class type. Bir sınıf türünün işlev üyeleri, bu sınıf türünün Yöntemler, özellikler, olaylar, Dizin oluşturucular, işleçler, örnek oluşturucular, Yıkıcılar ve statik oluşturuculardır.The function members of a class type are the methods, properties, events, indexers, operators, instance constructors, destructors, and static constructors of that class type.

Class_declaration yeni bir bildirim alanı (Bildirimler) oluşturur ve hemen class_declaration tarafından bulunan class_member_declaration, bu bildirim alanına yeni üyeler getirir.A class_declaration creates a new declaration space (Declarations), and the class_member_declaration s immediately contained by the class_declaration introduce new members into this declaration space. Class_member_declaration s için aşağıdaki kurallar geçerlidir:The following rules apply to class_member_declaration s:

  • Örnek oluşturucular, Yıkıcılar ve statik oluşturucular, hemen kapsayan sınıf ile aynı ada sahip olmalıdır.Instance constructors, destructors and static constructors must have the same name as the immediately enclosing class. Tüm diğer üyelerin, hemen kapsayan sınıfın adından farklı adlara sahip olması gerekir.All other members must have names that differ from the name of the immediately enclosing class.
  • Bir sabit, alan, özellik, olay veya tür adı aynı sınıfta belirtilen diğer tüm üyelerin adlarından farklı olmalıdır.The name of a constant, field, property, event, or type must differ from the names of all other members declared in the same class.
  • Bir yöntemin adı aynı sınıfta belirtilen diğer tüm yöntemlerin adlarından farklı olmalıdır.The name of a method must differ from the names of all other non-methods declared in the same class. Ayrıca, bir yöntemin imzası (imzalar ve aşırı yükleme) aynı sınıfta belirtilen diğer tüm yöntemlerin imzalarından farklı olmalıdır ve aynı sınıfta belirtilen iki yöntem yalnızca ve ile farklı imzalara sahip olamaz ref out .In addition, the signature (Signatures and overloading) of a method must differ from the signatures of all other methods declared in the same class, and two methods declared in the same class may not have signatures that differ solely by ref and out.
  • Bir örnek oluşturucusunun imzası, aynı sınıfta belirtilen diğer tüm örnek oluşturucuların imzalarından farklı olmalıdır ve aynı sınıfta belirtilen iki oluşturucunun, yalnızca ve ile farklı imzaları bulunmayabilir ref out .The signature of an instance constructor must differ from the signatures of all other instance constructors declared in the same class, and two constructors declared in the same class may not have signatures that differ solely by ref and out.
  • Bir dizin oluşturucunun imzası aynı sınıfta belirtilen diğer tüm dizin oluşturucularının imzalarından farklı olmalıdır.The signature of an indexer must differ from the signatures of all other indexers declared in the same class.
  • Bir işlecin imzası aynı sınıfta belirtilen diğer tüm işleçlerin imzalarından farklı olmalıdır.The signature of an operator must differ from the signatures of all other operators declared in the same class.

Bir sınıf türünün devralınan üyeleri (Devralma) bir sınıfın bildirim alanının parçası değildir.The inherited members of a class type (Inheritance) are not part of the declaration space of a class. Bu nedenle, türetilmiş bir sınıfın devralınan üye ile aynı ad veya imzaya sahip bir üyeyi bildirmesine izin verilir (yani, devralınan üyeyi etkiler).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).

Örnek türüThe instance type

Her sınıf bildiriminde ilişkili bir bağlı tür (bağlı ve ilişkisiz türler), örnek türü vardır.Each class declaration has an associated bound type (Bound and unbound types), the instance type. Genel sınıf bildiriminde, örnek türü, her bir sağlanan tür bağımsız değişkeni karşılık gelen tür parametresi olan tür bildiriminden oluşturulmuş bir tür (oluşturulmuş türler) oluşturularak oluşturulur.For a generic class declaration, the instance type is formed by creating a constructed type (Constructed types) from the type declaration, with each of the supplied type arguments being the corresponding type parameter. Örnek türü tür parametrelerini kullandığından, yalnızca tür parametrelerinin kapsamda olduğu durumlarda kullanılabilir; diğer bir deyişle, sınıf bildiriminin içinde.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. Örnek türü, this sınıf bildiriminin içinde yazılmış kod için türüdür.The instance type is the type of this for code written inside the class declaration. Genel olmayan sınıflar için örnek türü yalnızca belirtilen sınıftır.For non-generic classes, the instance type is simply the declared class. Aşağıda, örnek türleriyle birlikte çeşitli sınıf bildirimleri gösterilmektedir:The following shows several class declarations along with their instance types:

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

Oluşturulmuş türlerin üyeleriMembers of constructed types

Oluşturulmuş bir türün devralınmamış üyeleri, üye bildirimindeki her bir type_parameter , oluşturulan türün karşılık gelen type_argument yerine koyarak alınır.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. Değiştirme işlemi, tür bildirimlerinin anlam anlamını temel alır ve yalnızca metinsel değiştirme değildir.The substitution process is based on the semantic meaning of type declarations, and is not simply textual substitution.

Örneğin, genel sınıf bildirimi verildiğindeFor example, given the generic class declaration

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) {...}
}

oluşturulan tür Gen<int[],IComparable<string>> aşağıdaki üyelere sahiptir:the constructed type Gen<int[],IComparable<string>> has the following members:

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) {...}

aGenel sınıf bildirimindeki üyenin türü Gen "iki boyutlu dizidir T ", bu nedenle a Yukarıdaki oluşturulan türdeki üyenin türü ", tek boyutlu bir dizi" veya "iki boyutlu dizi int " veya ' dir int[,][] .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 one-dimensional array of int", or int[,][].

Örnek işlevi üyeleri içinde, türü this kapsayan bildirimin örnek türüdür (örnek türü).Within instance function members, the type of this is the instance type (The instance type) of the containing declaration.

Bir genel sınıfın tüm üyeleri herhangi bir kapsayan sınıftan tür parametrelerini doğrudan veya oluşturulmuş bir türün bir parçası olarak kullanabilir.All members of a generic class can use type parameters from any enclosing class, either directly or as part of a constructed type. Çalışma zamanında belirli bir kapalı oluşturulmuş tür (açık ve kapalı türler) kullanıldığında, bir tür parametresinin her kullanımı, oluşturulan türe sağlanan gerçek tür bağımsız değişkeniyle değiştirilmiştir.When a particular closed constructed type (Open and closed types) is used at run-time, each use of a type parameter is replaced with the actual type argument supplied to the constructed type. Örnek:For example:

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
    }
}

DevralmaInheritance

Bir sınıf, kendi doğrudan temel sınıf türünün üyelerini devralır .A class inherits the members of its direct base class type. Devralma, bir sınıfın, temel sınıfın örnek oluşturucular, Yıkıcılar ve statik oluşturucular dışında dolaylı olarak kendi temel sınıf türünün tüm üyelerini içerdiği anlamına gelir.Inheritance means that a class implicitly contains all members of its direct base class type, except for the instance constructors, destructors and static constructors of the base class. Devralmanın bazı önemli yönleri şunlardır:Some important aspects of inheritance are:

  • Devralma geçişlidir.Inheritance is transitive. C, Öğesinden türetildiyse B ve öğesinden türetildiyse, ' de belirtilen üyelerin B A C B yanı sıra içinde belirtilen üyeleri devralır A .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.
  • Türetilmiş bir sınıf doğrudan temel sınıfını genişletir.A derived class extends its direct base class. Türetilmiş bir sınıf, devralananlara yeni üyeler ekleyebilir, ancak devralınmış bir üyenin tanımını kaldıramaz.A derived class can add new members to those it inherits, but it cannot remove the definition of an inherited member.
  • Örnek oluşturucular, Yıkıcılar ve statik oluşturucular devralınmaz, ancak diğer tüm Üyeler, belirtilen erişilebilirliği (üye erişimi) ne olursa olsun.Instance constructors, destructors, and static constructors are not inherited, but all other members are, regardless of their declared accessibility (Member access). Ancak, kendilerine ait olan erişilebilirliğe bağlı olarak, devralınan Üyeler türetilmiş bir sınıfta erişilebilir olmayabilir.However, depending on their declared accessibility, inherited members might not be accessible in a derived class.
  • Türetilmiş bir sınıf, aynı ad veya imzaya sahip yeni üyeler bildirerek devralınan üyeleri (Devralma yoluyla gizleme) de gizleyebilir .A derived class can hide (Hiding through inheritance) inherited members by declaring new members with the same name or signature. Ancak devralınan bir üyeyi gizlemenin o üyeyi kaldırmadığını unutmayın; yalnızca bu üyeyi doğrudan türetilmiş sınıf üzerinden erişilmez hale getirir.Note however that hiding an inherited member does not remove that member—it merely makes that member inaccessible directly through the derived class.
  • Bir sınıf örneği, sınıfta ve temel sınıflarında belirtilen tüm örnek alanlarının bir kümesini içerir ve bir türetilmiş sınıf türünden herhangi bir temel sınıf türünden herhangi birine bir örtük dönüştürme (örtük başvuru dönüştürmeleri) bulunur.An instance of a class contains a set of all instance fields declared in the class and its base classes, and an implicit conversion (Implicit reference conversions) exists from a derived class type to any of its base class types. Bu nedenle, bir türetilmiş sınıfın örneğine bir başvuru, temel sınıflarının herhangi birinin bir örneğine başvuru olarak kabul edilebilir.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.
  • Bir sınıf sanal yöntemleri, özellikleri ve Dizin oluşturucuyu bildirebilir ve türetilmiş sınıflar bu işlev üyelerinin uygulamasını geçersiz kılabilir.A class can declare virtual methods, properties, and indexers, and derived classes can override the implementation of these function members. Bu, sınıfların bir işlev üyesi çağrısı tarafından gerçekleştirilen eylemlerde çok biçimli davranışlar sergilemesine olanak sağlar. Bu işlev üyesinin çağrıldığı örnek çalışma zamanı türüne bağlı olarak değişir.This enables classes to exhibit polymorphic behavior wherein the actions performed by a function member invocation varies depending on the run-time type of the instance through which that function member is invoked.

Oluşturulmuş bir sınıf türünün devralınan üyesi, class_base belirtiminde karşılık gelen tür parametrelerinin her bir oluşumu için oluşturulan türün tür bağımsız değişkenlerini değiştirerek bulunan en hızlı temel sınıf türünün (temel sınıflar) üyeleridir.The inherited member of a constructed class type are the members of the immediate base class type (Base classes), which is found by substituting the type arguments of the constructed type for each occurrence of the corresponding type parameters in the class_base specification. Bu Üyeler sırasıyla, üye bildirimindeki her bir type_parameter için, class_base belirtiminin karşılık gelen type_argument yerine koyarak dönüştürülür.These members, in turn, are transformed by substituting, for each type_parameter in the member declaration, the corresponding type_argument of the class_base specification.

class B<U>
{
    public U F(long index) {...}
}

class D<T>: B<T[]>
{
    public T G(string s) {...}
}

Yukarıdaki örnekte, oluşturulan türün tür D<int> public int G(string s) parametresi için tür bağımsız değişkeni yerine devralınmamış devralınmış bir üyeye sahiptir int T .In the above example, 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> Ayrıca, Sınıf bildiriminden devralınan bir üyeye de sahiptir B .D<int> also has an inherited member from the class declaration B. Bu devralınan üye, ilk olarak temel B<int[]> D<int> int T sınıf belirtiminde için B<T[]> yerine koyarak temel sınıf türü belirlenerek belirlenir.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[]>. Daha sonra, bir tür bağımsız değişkeni olarak ' B int[] de, U devralınan üyeyi oluşturan ' de için değiştirilir public U F(long index) public int[] F(long index) .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).

Yeni değiştiriciThe new modifier

Bir class_member_declaration devralınan üyeyle aynı ada veya imzaya sahip bir üyeyi bildirmesine izin verilir.A class_member_declaration is permitted to declare a member with the same name or signature as an inherited member. Bu gerçekleştiğinde, türetilmiş sınıf üyesi temel sınıf üyesini gizleyecek şekilde söylenir.When this occurs, the derived class member is said to hide the base class member. Devralınan bir üyenin gizlenmesi bir hata sayılmaz, ancak derleyicinin bir uyarı vermesine neden olur.Hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning. Uyarıyı bastırmak için, türetilen sınıf üyesinin bildirimi, new türetilen üyenin temel üyeyi gizlemek için tasarlanan bir değiştirici içerebilir.To suppress the warning, the declaration of the derived class member can include a new modifier to indicate that the derived member is intended to hide the base member. Bu konu Devralma yoluyla gizlenerekdaha ayrıntılı bir şekilde ele alınmıştır.This topic is discussed further in Hiding through inheritance.

Bir new değiştirici devralınmış bir üyeyi gizlemez bir bildirime dahil edilir, bu etkiye bir uyarı verilir.If a new modifier is included in a declaration that doesn't hide an inherited member, a warning to that effect is issued. Bu uyarı, değiştirici kaldırılarak bastırılır new .This warning is suppressed by removing the new modifier.

Erişim değiştiricileriAccess modifiers

Bir class_member_declaration , olası beş tür erişilebilirliği (belirtilen erişilebilirlik) içerebilir: public , protected internal ,, protected internal veya private .A class_member_declaration can have any one of the five possible kinds of declared accessibility (Declared accessibility): public, protected internal, protected, internal, or private. protected internalBirleşim haricinde, birden fazla erişim değiştiricisi belirtmek için derleme zamanı hatası olur.Except for the protected internal combination, it is a compile-time error to specify more than one access modifier. Bir class_member_declaration erişim değiştiricileri içermiyorsa, private varsayılır.When a class_member_declaration does not include any access modifiers, private is assumed.

Anayent türleriConstituent types

Bir üyenin bildiriminde kullanılan türler, o üyenin bileşen türleri olarak adlandırılır.Types that are used in the declaration of a member are called the constituent types of that member. Olası yapısal türler, bir sabit, alan, özellik, olay veya dizin oluşturucunun türü, bir yöntemin veya işlecin dönüş türü ve bir yöntem, Dizin Oluşturucu, işleç veya örnek oluşturucusunun parametre türleri olabilir.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. Üyenin bileşen türleri en az o üyenin kendisi (Erişilebilirlik kısıtlamaları) olarak erişilebilir olmalıdır.The constituent types of a member must be at least as accessible as that member itself (Accessibility constraints).

Statik ve örnek üyeleriStatic and instance members

Bir sınıfın üyeleri *statik Üyeler _ veya _ örnek üyeleri *.Members of a class are either static members _ or _instance members**. Genel olarak, statik üyeleri nesnelere ait olan sınıf türlerine ve örnek üyelerine (sınıf türü örnekleri) ait olacak şekilde düşünmek yararlı olur.Generally speaking, it is useful to think of static members as belonging to class types and instance members as belonging to objects (instances of class types).

Bir alan, yöntem, özellik, olay, işleç veya Oluşturucu bildirimi bir static değiştirici içerdiğinde, statik bir üye bildirir.When a field, method, property, event, operator, or constructor declaration includes a static modifier, it declares a static member. Ayrıca, bir sabit veya tür bildirimi dolaylı olarak statik bir üye bildirir.In addition, a constant or type declaration implicitly declares a static member. Statik Üyeler aşağıdaki özelliklere sahiptir:Static members have the following characteristics:

  • Bir statik üyeye M formun member_access (üye erişimi) içinde başvuruluyorsa E.M , E içeren bir türü belirtmelidir M .When a static member M is referenced in a member_access (Member access) of the form E.M, E must denote a type containing M. Bir örneği göstermek için derleme zamanı hatasıdır E .It is a compile-time error for E to denote an instance.
  • Statik bir alan, belirli bir kapalı sınıf türünün tüm örnekleri tarafından paylaşılacak tam olarak bir depolama konumunu tanımlar.A static field identifies exactly one storage location to be shared by all instances of a given closed class type. Belirli bir kapalı sınıf türünün kaç örneğinin oluşturulduğuna bakılmaksızın, bir statik alanın yalnızca bir kopyası vardır.No matter how many instances of a given closed class type are created, there is only ever one copy of a static field.
  • Statik işlev üyesi (yöntem, özellik, olay, işleç veya Oluşturucu) belirli bir örnek üzerinde çalışmaz ve bu this tür bir işlev üyesinde başvurmak için derleme zamanı hatası olur.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.

Bir alan, yöntem, özellik, olay, Dizin Oluşturucu, Oluşturucu veya yıkıcı bildirimi bir değiştirici içermiyorsa, bir static örnek üyesi bildirir.When a field, method, property, event, indexer, constructor, or destructor declaration does not include a static modifier, it declares an instance member. (Bir örnek üyesi bazen statik olmayan bir üye olarak adlandırılır.) Örnek üyeleri aşağıdaki özelliklere sahiptir:(An instance member is sometimes called a non-static member.) Instance members have the following characteristics:

  • MFormun bir member_access (üye erişimi) içinde bir örnek üyesine başvurulması durumunda E.M , E içeren bir türün bir örneğini belirtmelidir M .When an instance member M is referenced in a member_access (Member access) of the form E.M, E must denote an instance of a type containing M. Bir tür belirtmek için bağlama zamanı hatası olur E .It is a binding-time error for E to denote a type.
  • Bir sınıfın her örneği, sınıfının tüm örnek alanlarını ayrı bir kümesini içerir.Every instance of a class contains a separate set of all instance fields of the class.
  • Bir örnek işlev üyesi (yöntem, özellik, Dizin Oluşturucu, örnek Oluşturucu veya yıkıcı), sınıfın belirli bir örneği üzerinde çalışır ve bu örneğe this (Bu erişim) olarak erişilebilir.An instance function member (method, property, indexer, instance constructor, or destructor) operates on a given instance of the class, and this instance can be accessed as this (This access).

Aşağıdaki örnekte statik ve örnek üyelerine erişim kuralları gösterilmektedir:The following example illustrates the rules for accessing static and instance members:

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
    }
}

FYöntemi bir örnek işlev üyesinde, hem örnek üyelerine hem de statik üyelere erişmek için bir simple_name (basit adlar) kullanılabileceğini gösterir.The F method shows that in an instance function member, a simple_name (Simple names) can be used to access both instance members and static members. GYöntemi, bir statik işlev üyesinde, bir simple_name aracılığıyla örnek üyesine erişmek için derleme zamanı hatası olduğunu gösterir.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. MainYöntemi, bir member_access (üye erişimi), örnek üyelerine örnekler aracılığıyla erişilmesi ve statik üyelere türler aracılığıyla erişilmesi gerekir.The Main method shows that in a member_access (Member access), instance members must be accessed through instances, and static members must be accessed through types.

İç içe geçmiş türlerNested types

Bir sınıf veya yapı bildiriminde tanımlanan bir türe *iç içe tür _ denir.A type declared within a class or struct declaration is called a *nested type _. Derleme birimi veya ad alanı içinde belirtilen bir tür _ iç içe olmayan"" türü olarak adlandırılır.A type that is declared within a compilation unit or namespace is called a _*non-nested type**.

ÖrnekteIn the example

using System;

class A
{
    class B
    {
        static void F() {
            Console.WriteLine("A.B.F");
        }
    }
}

sınıf B , sınıf içinde bildirildiği için iç içe bir tür A ve sınıf, A derleme birimi içinde bildirildiği için iç içe olmayan bir tür.class B is a nested type because it is declared within class A, and class A is a non-nested type because it is declared within a compilation unit.

Tam nitelikli adFully qualified name

İç içe bir tür için tam nitelikli ad (tam adlar), S.N S türün bildirildiği türün tam nitelikli adıdır N .The fully qualified name (Fully qualified names) for a nested type is S.N where S is the fully qualified name of the type in which type N is declared.

Tanımlanan erişilebilirlikDeclared accessibility

İç içe olmayan türler erişilebilirliği içerebilir public veya belirtebilir internal ve internal Varsayılan olarak erişilebilirliği bildirmişti.Non-nested types can have public or internal declared accessibility and have internal declared accessibility by default. İç içe türler, kapsayan türün bir sınıf veya yapı olmasına bağlı olarak, bu tanımlanmış erişilebilirlik ve bir veya daha fazla tanımlanmış erişilebilirlik biçimi içerebilir:Nested types can have these forms of declared accessibility too, plus one or more additional forms of declared accessibility, depending on whether the containing type is a class or struct:

  • Bir sınıfta bildirildiği iç içe yerleştirilmiş bir tür, belirtilen beş erişilebilirliği (, public protected internal ,, protected internal , veya private ) ve diğer sınıf üyeleri gibi, varsayılan olarak private tanımlanmış erişilebilirliği kullanabilirler.A nested type that is declared in a class can have any of five forms of declared accessibility (public, protected internal, protected, internal, or private) and, like other class members, defaults to private declared accessibility.
  • Bir yapıda tanımlanmış iç içe yerleştirilmiş bir tür, üç public farklı yapı erişilebilirliği (, internal , veya private ) ve diğer yapı üyeleri gibi, varsayılan olarak private belirtilen erişilebilirliği kullanabilirler.A nested type that is declared in a struct can have any of three forms of declared accessibility (public, internal, or private) and, like other struct members, defaults to private declared accessibility.

ÖrnekteThe example

public class List
{
    // Private data structure
    private class Node
    { 
        public object Data;
        public Node Next;

        public Node(object data, Node next) {
            this.Data = data;
            this.Next = next;
        }
    }

    private Node first = null;
    private Node last = null;

    // Public interface
    public void AddToFront(object o) {...}
    public void AddToBack(object o) {...}
    public object RemoveFromFront() {...}
    public object RemoveFromBack() {...}
    public int Count { get {...} }
}

özel bir iç içe sınıf bildirir Node .declares a private nested class Node.

LarınıHiding

İç içe yerleştirilmiş bir tür, temel üyeyi gizleyebilir (ad gizleyerek).A nested type may hide (Name hiding) a base member. newDeğiştiriciye iç içe geçmiş tür bildirimlerinde izin verilir, böylece gizleme açıkça ifade edilebilir.The new modifier is permitted on nested type declarations so that hiding can be expressed explicitly. ÖrnekteThe example

using System;

class Base
{
    public static void M() {
        Console.WriteLine("Base.M");
    }
}

class Derived: Base 
{
    new public class M 
    {
        public static void F() {
            Console.WriteLine("Derived.M.F");
        }
    }
}

class Test 
{
    static void Main() {
        Derived.M.F();
    }
}

Miçinde tanımlanan yöntemi gizleyen iç içe bir sınıfı gösterir M Base .shows a nested class M that hides the method M defined in Base.

Bu erişimthis access

İç içe bir tür ve kapsayan türü This_Access (Bu erişim) ile ilgili özel bir ilişkiye sahip değildir.A nested type and its containing type do not have a special relationship with regard to this_access (This access). Özellikle, this iç içe bir tür içinde, kapsayan türün örnek üyelerine başvurmak için kullanılamaz.Specifically, this within a nested type cannot be used to refer to instance members of the containing type. İç içe bir türün, kapsayan türün örnek üyelerine erişmesi gereken durumlarda, this kapsayan türün örneği için iç içe geçmiş türü için bir Oluşturucu bağımsız değişkeni olarak, erişim sağlanabilir.In cases where a nested type needs access to the instance members of its containing type, access can be provided by providing the this for the instance of the containing type as a constructor argument for the nested type. Aşağıdaki örnekThe following example

using System;

class C
{
    int i = 123;

    public void F() {
        Nested n = new Nested(this);
        n.G();
    }

    public class Nested
    {
        C this_c;

        public Nested(C c) {
            this_c = c;
        }

        public void G() {
            Console.WriteLine(this_c.i);
        }
    }
}

class Test
{
    static void Main() {
        C c = new C();
        c.F();
    }
}

Bu tekniği gösterir.shows this technique. Örnek C Nested this Nested üyelerine sonraki erişimi sağlamak için bir örneği oluşturur ve kendi oluşturucusunu geçirir C .An instance of C creates an instance of Nested and passes its own this to Nested's constructor in order to provide subsequent access to C's instance members.

Kapsayan türdeki özel ve korunan üyelere erişimAccess to private and protected members of the containing type

İç içe bir tür, içeren ve tarafından tanımlanan içerilen türün üyeleri de dahil olmak üzere, kapsayan türü için erişilebilen tüm üyelere erişebilir private protected .A nested type has access to all of the members that are accessible to its containing type, including members of the containing type that have private and protected declared accessibility. ÖrnekteThe example

using System;

class C 
{
    private static void F() {
        Console.WriteLine("C.F");
    }

    public class Nested 
    {
        public static void G() {
            F();
        }
    }
}

class Test 
{
    static void Main() {
        C.Nested.G();
    }
}

Ciç içe bir sınıf içeren bir sınıfı gösterir Nested .shows a class C that contains a nested class Nested. İçinde, Nested yöntemi G içinde tanımlanan statik yöntemi çağırır F ve özel olarak tanımlanmış C F erişilebilirliği vardır.Within Nested, the method G calls the static method F defined in C, and F has private declared accessibility.

İç içe yerleştirilmiş bir tür, kapsayan türünün temel türünde tanımlanan korumalı üyelere de erişebilir.A nested type also may access protected members defined in a base type of its containing type. ÖrnekteIn the example

using System;

class Base 
{
    protected void F() {
        Console.WriteLine("Base.F");
    }
}

class Derived: Base 
{
    public class Nested 
    {
        public void G() {
            Derived d = new Derived();
            d.F();        // ok
        }
    }
}

class Test 
{
    static void Main() {
        Derived.Nested n = new Derived.Nested();
        n.G();
    }
}

iç içe yerleştirilmiş sınıf, Derived.Nested F Derived Base öğesinin bir örneği aracılığıyla çağırarak temel sınıfında tanımlanan korumalı yönteme erişir Derived .the nested class Derived.Nested accesses the protected method F defined in Derived's base class, Base, by calling through an instance of Derived.

Genel sınıflarda iç içe türlerNested types in generic classes

Genel sınıf bildirimi, iç içe geçmiş tür bildirimleri içerebilir.A generic class declaration can contain nested type declarations. Kapsayan sınıfın tür parametreleri iç içe türler içinde kullanılabilir.The type parameters of the enclosing class can be used within the nested types. İç içe geçmiş tür bildirimi, yalnızca iç içe geçmiş tür için uygulanan ek tür parametreleri içerebilir.A nested type declaration can contain additional type parameters that apply only to the nested type.

Genel sınıf bildiriminde yer alan her tür bildirimi örtük olarak genel bir tür bildirimidir.Every type declaration contained within a generic class declaration is implicitly a generic type declaration. Genel bir tür içinde iç içe geçmiş bir türe başvuru yazarken, türü bağımsız değişkenleri dahil olmak üzere bulunan oluşturulmuş tür, adlandırılmış olmalıdır.When writing a reference to a type nested within a generic type, the containing constructed type, including its type arguments, must be named. Ancak, dış sınıfın içinden iç içe geçmiş tür, nitelendirme olmadan kullanılabilir; Dış sınıfın örnek türü, iç içe geçmiş türü oluşturulurken örtük olarak kullanılabilir.However, from within the outer class, the nested type can be used without qualification; the instance type of the outer class can be implicitly used when constructing the nested type. Aşağıdaki örnek, öğesinden oluşturulan oluşturulmuş bir türe başvurmak için üç farklı doğru yolu gösterir Inner ; ilk ikisi eşdeğerdir:The following example shows three different correct ways to refer to a constructed type created from Inner; the first two are equivalent:

class Outer<T>
{
    class Inner<U>
    {
        public static void F(T t, U u) {...}
    }

    static void F(T t) {
        Outer<T>.Inner<string>.F(t, "abc");      // These two statements have
        Inner<string>.F(t, "abc");               // the same effect

        Outer<int>.Inner<string>.F(3, "abc");    // This type is different

        Outer.Inner<string>.F(t, "abc");         // Error, Outer needs type arg
    }
}

Hatalı programlama stili olsa da, iç içe bir türdeki tür parametresi, dış türde belirtilen bir üyeyi veya tür parametresini gizleyebilir:Although it is bad programming style, a type parameter in a nested type can hide a member or type parameter declared in the outer type:

class Outer<T>
{
    class Inner<T>        // Valid, hides Outer's T
    {
        public T t;       // Refers to Inner's T
    }
}

Ayrılmış üye adlarıReserved member names

Temel C# çalışma zamanı uygulamasını kolaylaştırmak için, bir özellik, olay veya Dizin Oluşturucu olan her kaynak üye bildirimi için, uygulama, üye bildirimi türüne, adına ve türüne göre iki yöntem imzasını ayırmalıdır.To facilitate the underlying C# run-time implementation, for each source member declaration that is a property, event, or indexer, the implementation must reserve two method signatures based on the kind of the member declaration, its name, and its type. Bu, temeldeki çalışma zamanı uygulamasının bu ayırmaları kullanmasa bile, imzası bu ayrılmış imzalardan biriyle eşleşen bir üyeyi bildirmek için bir derleme zamanı hatasıdır.It is a compile-time error for a program to declare a member whose signature matches one of these reserved signatures, even if the underlying run-time implementation does not make use of these reservations.

Ayrılmış adlar bildirimleri sunmaz, bu nedenle üye aramasına katılmaz.The reserved names do not introduce declarations, thus they do not participate in member lookup. Ancak, bir bildirimin ilişkili ayrılmış yöntem imzaları devralmaya (Devralma) katılır ve new değiştiriciyle (Yeni değiştirici) gizlenebilir.However, a declaration's associated reserved method signatures do participate in inheritance (Inheritance), and can be hidden with the new modifier (The new modifier).

Bu adların ayırması üç amaca hizmet eder:The reservation of these names serves three purposes:

  • Temel uygulamanın C# dil özelliğine Get veya set erişimi için bir yöntem adı olarak sıradan bir tanımlayıcı kullanmasına izin vermek için.To allow the underlying implementation to use an ordinary identifier as a method name for get or set access to the C# language feature.
  • Diğer dillerin, C# dil özelliğine Get veya set erişimi için bir yöntem adı olarak sıradan bir tanımlayıcı kullanarak birlikte çalışabilme izni vermek için.To allow other languages to interoperate using an ordinary identifier as a method name for get or set access to the C# language feature.
  • Tek bir uygun derleyici tarafından kabul edilen kaynağın, ayrılmış üye adlarının özelliklerinin tüm C# uygulamalarında tutarlı olmasını sağlamaya yardımcı olmak için.To help ensure that the source accepted by one conforming compiler is accepted by another, by making the specifics of reserved member names consistent across all C# implementations.

Yıkıcı (Yıkıcılar) bildirimi de bir imzanın ayrılmasına neden olur (yokediciler için üye adları ayrılmıştır).The declaration of a destructor (Destructors) also causes a signature to be reserved (Member names reserved for destructors).

Özellikler için ayrılan üye adlarıMember names reserved for properties

Türünde bir özellik P (Özellikler) için T aşağıdaki imzalar ayrılmıştır:For a property P (Properties) of type T, the following signatures are reserved:

T get_P();
void set_P(T value);

Özellik salt okunurdur veya salt yazılır olsa bile her iki imza de ayrılır.Both signatures are reserved, even if the property is read-only or write-only.

ÖrnekteIn the example

using System;

class A
{
    public int P {
        get { return 123; }
    }
}

class B: A
{
    new public int get_P() {
        return 456;
    }

    new public void set_P(int value) {
    }
}

class Test
{
    static void Main() {
        B b = new B();
        A a = b;
        Console.WriteLine(a.P);
        Console.WriteLine(b.P);
        Console.WriteLine(b.get_P());
    }
}

bir sınıf A salt okunurdur bir özelliği tanımlar P , böylece imzaları ve yöntemleri için ayırırsınız get_P set_P .a class A defines a read-only property P, thus reserving signatures for get_P and set_P methods. Bir sınıf B ' dan türetilir A ve bu ayrılmış imzaların her ikisini birden gizler.A class B derives from A and hides both of these reserved signatures. Örnek, çıktıyı üretir:The example produces the output:

123
123
456

Olaylar için ayrılan üye adlarıMember names reserved for events

ETemsilci türünün bir olayı (olayları) için T aşağıdaki imzalar ayrılmıştır:For an event E (Events) of delegate type T, the following signatures are reserved:

void add_E(T handler);
void remove_E(T handler);

Dizin oluşturucular için ayrılan üye adlarıMember names reserved for indexers

Parametre-listesi olan türdeki bir Dizin Oluşturucu (Dizin oluşturucular) için T L aşağıdaki imzalar ayrılmıştır:For an indexer (Indexers) of type T with parameter-list L, the following signatures are reserved:

T get_Item(L);
void set_Item(L, T value);

Dizin Oluşturucu salt okunurdur veya salt yazılır olsa bile her iki imza da ayrılır.Both signatures are reserved, even if the indexer is read-only or write-only.

Ayrıca üye adının Item ayrılmış olması.Furthermore the member name Item is reserved.

Yok ediciler için ayrılan üye adlarıMember names reserved for destructors

Yıkıcı (Yıkıcılar) içeren bir sınıf için aşağıdaki imza ayrılmıştır:For a class containing a destructor (Destructors), the following signature is reserved:

void Finalize();

SabitlerConstants

*Sabiti _ sabit bir değeri temsil eden bir sınıf üyesidir: derleme zamanında hesaplanılabilen bir değer.A *constant _ is a class member that represents a constant value: a value that can be computed at compile-time. Bir _constant_declaration *, belirli bir türün bir veya daha fazla sabitlerini tanıtır.A _constant_declaration* introduces one or more constants of a given type.

constant_declaration
    : attributes? constant_modifier* 'const' type constant_declarators ';'
    ;

constant_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    ;

constant_declarators
    : constant_declarator (',' constant_declarator)*
    ;

constant_declarator
    : identifier '=' constant_expression
    ;

Bir constant_declaration bir dizi öznitelik (öznitelik), new değiştirici (Yeni değiştirici) ve dört erişim değiştiricisinin geçerli bir birleşimini (erişim değiştiricileri) içerebilir.A constant_declaration may include a set of attributes (Attributes), a new modifier (The new modifier), and a valid combination of the four access modifiers (Access modifiers). Öznitelikler ve değiştiriciler constant_declaration tarafından belirtilen tüm üyelere uygulanır.The attributes and modifiers apply to all of the members declared by the constant_declaration. Sabitler statik üye olarak kabul edilse de, constant_declaration gerektirmez veya static değiştiriciye izin vermez.Even though constants are considered static members, a constant_declaration neither requires nor allows a static modifier. Aynı değiştiricinin Sabit bildiriminde birden çok kez görünmesi hatadır.It is an error for the same modifier to appear multiple times in a constant declaration.

Constant_declaration türü , bildirim tarafından tanıtılan üyelerin türünü belirtir.The type of a constant_declaration specifies the type of the members introduced by the declaration. Türün ardından her biri yeni bir üye tanıtan constant_declarator s listesi bulunur.The type is followed by a list of constant_declarator s, each of which introduces a new member. Constant_declarator , üyeyi belirten bir tanımlayıcıdan sonra bir " = " belirteci, ardından üyenin değerini veren bir constant_expression (sabit ifadeler) ile oluşur.A constant_declarator consists of an identifier that names the member, followed by an "=" token, followed by a constant_expression (Constant expressions) that gives the value of the member.

Sabit bildiriminde belirtilen tür ,,,,,,,, sbyte byte short ushort int uint long ulong char , float ,, double decimal , bool , string , enum_type veya reference_type olmalıdır.The type specified in a constant declaration must be sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, string, an enum_type, or a reference_type. Her constant_expression , hedef türün bir değerini veya örtük bir dönüştürme (örtük dönüştürmeler) tarafından hedef türe dönüştürülebilen bir türü vermelidir.Each constant_expression must yield a value of the target type or of a type that can be converted to the target type by an implicit conversion (Implicit conversions).

Bir sabit türünün en az sabitin (Erişilebilirlik kısıtlamaları) olarak erişilebilir olması gerekir.The type of a constant must be at least as accessible as the constant itself (Accessibility constraints).

Bir sabit değeri simple_name (basit adlar) veya bir member_access (üye erişimi) kullanılarak bir ifadede elde edilir.The value of a constant is obtained in an expression using a simple_name (Simple names) or a member_access (Member access).

Bir sabit, bir constant_expression katılabilir.A constant can itself participate in a constant_expression. Bu nedenle, bir sabit, constant_expression gerektiren herhangi bir yapı içinde kullanılabilir.Thus, a constant may be used in any construct that requires a constant_expression. Bu yapılara örnek case olarak Etiketler, goto case deyimler, enum üye bildirimleri, öznitelikler ve diğer sabit bildirimler verilebilir.Examples of such constructs include case labels, goto case statements, enum member declarations, attributes, and other constant declarations.

Sabit ifadelerdeaçıklandığı gibi, constant_expression derleme zamanında tam olarak değerlendirilebilen bir ifadedir.As described in Constant expressions, a constant_expression is an expression that can be fully evaluated at compile-time. ' Den farklı bir reference_type null olmayan bir değer oluşturmanın tek yolu, string new işleci uygulamak ve new işleci bir constant_expression izin verilmediğinden, reference_type s dışındaki sabitler için tek olası değerdir string null .Since the only way to create a non-null value of a reference_type other than string is to apply the new operator, and since the new operator is not permitted in a constant_expression, the only possible value for constants of reference_type s other than string is null.

Sabit bir değer için sembolik bir ad istendiğinde, ancak bu değerin türü bir sabit bildirimde izin verilmediğinde veya değer derleme zamanında bir constant_expression tarafından hesaplanmadığında, readonly bunun yerine bir alan (salt okunur alan) kullanılabilir.When a symbolic name for a constant value is desired, but when the type of that value is not permitted in a constant declaration, or when the value cannot be computed at compile-time by a constant_expression, a readonly field (Readonly fields) may be used instead.

Birden çok sabiti bildiren bir sabit bildirim, aynı özniteliklere, Değiştiricilere ve türe sahip tek sabitlerin birden çok bildirimi ile eşdeğerdir.A constant declaration that declares multiple constants is equivalent to multiple declarations of single constants with the same attributes, modifiers, and type. Örneğin:For example

class A
{
    public const double X = 1.0, Y = 2.0, Z = 3.0;
}

eşdeğerdiris equivalent to

class A
{
    public const double X = 1.0;
    public const double Y = 2.0;
    public const double Z = 3.0;
}

Sabitler dairesel bir şekilde olmadığı sürece sabitlerin aynı program içindeki diğer sabitlere bağlı olmasına izin verilir.Constants are permitted to depend on other constants within the same program as long as the dependencies are not of a circular nature. Derleyici, sabit bildirimleri uygun sırada değerlendirmek için otomatik olarak düzenler.The compiler automatically arranges to evaluate the constant declarations in the appropriate order. ÖrnekteIn the example

class A
{
    public const int X = B.Z + 1;
    public const int Y = 10;
}

class B
{
    public const int Z = A.Y + 1;
}

derleyici ilk olarak değerlendirir, A.Y sonra, B.Z A.X ve değerlerini üretir, ve değerlerini değerlendirir 10 11 12 .the compiler first evaluates A.Y, then evaluates B.Z, and finally evaluates A.X, producing the values 10, 11, and 12. Sabit bildirimler diğer programlardaki sabitlere bağlı olabilir, ancak bu tür bağımlılıklar yalnızca tek bir yönde mümkündür.Constant declarations may depend on constants from other programs, but such dependencies are only possible in one direction. Yukarıdaki örneğe başvurarak, A ve B ayrı programlarda bildirilirse, ' nin bağlı olması ve A.X B.Z B.Z daha sonra bağımlı olması mümkün olacaktır A.Y .Referring to the example above, if A and B were declared in separate programs, it would be possible for A.X to depend on B.Z, but B.Z could then not simultaneously depend on A.Y.

AlanlarFields

*Field _, bir nesne veya sınıfla ilişkili bir değişkeni temsil eden bir üyesidir.A *field _ is a member that represents a variable associated with an object or class. Bir _field_declaration * belirli bir türün bir veya daha fazla alanını tanıtır.A _field_declaration* introduces one or more fields of a given type.

field_declaration
    : attributes? field_modifier* type variable_declarators ';'
    ;

field_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'static'
    | 'readonly'
    | 'volatile'
    | field_modifier_unsafe
    ;

variable_declarators
    : variable_declarator (',' variable_declarator)*
    ;

variable_declarator
    : identifier ('=' variable_initializer)?
    ;

variable_initializer
    : expression
    | array_initializer
    ;

Bir field_declaration bir öznitelikler kümesi (öznitelikler), bir new değiştirici (Yeni değiştirici), dört erişim değiştiricisinin geçerli bir birleşimi (erişim değiştiricileri) ve bir static değiştirici (statik ve örnek alanları) içerebilir.A field_declaration may include a set of attributes (Attributes), a new modifier (The new modifier), a valid combination of the four access modifiers (Access modifiers), and a static modifier (Static and instance fields). Ayrıca, bir field_declaration readonly değiştirici (salt okunur alanlar) veya volatile değiştirici (geçici alanlar) içerebilir, ancak ikisini birden içeremez.In addition, a field_declaration may include a readonly modifier (Readonly fields) or a volatile modifier (Volatile fields) but not both. Öznitelikler ve değiştiriciler field_declaration tarafından belirtilen tüm üyelere uygulanır.The attributes and modifiers apply to all of the members declared by the field_declaration. Aynı değiştiricinin bir alan bildiriminde birden çok kez görünmesi hatadır.It is an error for the same modifier to appear multiple times in a field declaration.

Field_declaration türü , bildirim tarafından tanıtılan üyelerin türünü belirtir.The type of a field_declaration specifies the type of the members introduced by the declaration. Türün ardından her biri yeni bir üye tanıtan variable_declarator s listesi bulunur.The type is followed by a list of variable_declarator s, each of which introduces a new member. Variable_declarator , bu üyeyi ve isteğe bağlı olarak bir "" belirteci ve bu üyenin ilk değerini veren bir = variable_initializer (değişken başlatıcıları) içeren bir tanımlayıcıdan oluşur.A variable_declarator consists of an identifier that names that member, optionally followed by an "=" token and a variable_initializer (Variable initializers) that gives the initial value of that member.

Alanın türü en az alanın kendisi (Erişilebilirlik kısıtlamaları) olarak erişilebilir olmalıdır.The type of a field must be at least as accessible as the field itself (Accessibility constraints).

Bir alanın değeri, simple_name (basit adlar) veya bir member_access (üye erişimi) kullanılarak bir ifadede elde edilir.The value of a field is obtained in an expression using a simple_name (Simple names) or a member_access (Member access). Salt okunur olmayan bir alanın değeri, atama (atama işleçleri) kullanılarak değiştirilir.The value of a non-readonly field is modified using an assignment (Assignment operators). Salt okunur olmayan bir alanın değeri, sonek artırma ve azaltma işleçleri (Sonek artışı ve azaltma işleçleri) ve önek artırma ve azaltma Işleçleri (önek artırma ve azaltma işleçleri) kullanılarak elde edilebilir ve değiştirilebilir.The value of a non-readonly field can be both obtained and modified using postfix increment and decrement operators (Postfix increment and decrement operators) and prefix increment and decrement operators (Prefix increment and decrement operators).

Birden çok alanı bildiren bir alan bildirimi, aynı özniteliklere, Değiştiricilere ve türe sahip tek alanlara ait birden çok bildirime eşdeğerdir.A field declaration that declares multiple fields is equivalent to multiple declarations of single fields with the same attributes, modifiers, and type. Örneğin:For example

class A
{
    public static int X = 1, Y, Z = 100;
}

eşdeğerdiris equivalent to

class A
{
    public static int X = 1;
    public static int Y;
    public static int Z = 100;
}

Statik ve örnek alanlarıStatic and instance fields

Bir alan bildirimi bir değiştirici içerdiğinde static , bildirim tarafından tanıtılan alanlar *static Fields _ ' dir.When a field declaration includes a static modifier, the fields introduced by the declaration are *static fields _. Hiçbir static değiştirici yoksa, bildirim tarafından tanıtılan alanlar *örnek alanlardır*.When no static modifier is present, the fields introduced by the declaration are instance fields. Statik alanlar ve örnek alanları, C# tarafından desteklenen çeşitli değişken (değişken) çeşitleridir ve bunlar sırasıyla statik değişkenler ve _ örnek değişkenleri * olarak adlandırılır.Static fields and instance fields are two of the several kinds of variables (Variables) supported by C#, and at times they are referred to as static variables and _*instance variables**, respectively.

Statik alan, belirli bir örneğin bir parçası değildir; Bunun yerine, kapalı bir türün (açık ve kapalı türler) tüm örnekleri arasında paylaşılır.A static field is not part of a specific instance; instead, it is shared amongst all instances of a closed type (Open and closed types). Kapalı bir sınıf türünün kaç örneğinin oluşturulduğuna bakılmaksızın, ilişkili uygulama etki alanı için yalnızca bir statik alan kopyası vardır.No matter how many instances of a closed class type are created, there is only ever one copy of a static field for the associated application domain.

Örnek:For example:

class C<V>
{
    static int count = 0;

    public C() {
        count++;
    }

    public static int Count {
        get { return count; }
    }
}

class Application
{
    static void Main() {
        C<int> x1 = new C<int>();
        Console.WriteLine(C<int>.Count);        // Prints 1

        C<double> x2 = new C<double>();
        Console.WriteLine(C<int>.Count);        // Prints 1

        C<int> x3 = new C<int>();
        Console.WriteLine(C<int>.Count);        // Prints 2
    }
}

Örnek alanı bir örneğe aittir.An instance field belongs to an instance. Özellikle, bir sınıfın her örneği, bu sınıfın tüm örnek alanlarının ayrı bir kümesini içerir.Specifically, every instance of a class contains a separate set of all the instance fields of that class.

Bir alana bir member_access (üye erişimi) bir statik alan ise, içeren bir E.M M E türü belirtmek M ve M bir örnek alanı ise, bir türü içeren bir örneği belirtmek zorunda M olması gerekir.When a field is referenced in a member_access (Member access) of the form E.M, if M is a static field, E must denote a type containing M, and if M is an instance field, E must denote an instance of a type containing M.

Statik ve örnek üyeleri arasındaki farklılıklar, statik ve örnek üyelerindedaha ayrıntılı bir şekilde ele alınmıştır.The differences between static and instance members are discussed further in Static and instance members.

ReadOnly alanlarıReadonly fields

Bir field_declaration readonly değiştirici içerdiğinde, bildirim tarafından tanıtılan alanlar salt okunur alanlardır.When a field_declaration includes a readonly modifier, the fields introduced by the declaration are readonly fields. Salt okunur alanlara doğrudan atamalar yalnızca bu bildirimin bir parçası veya aynı sınıftaki bir örnek Oluşturucu ya da statik oluşturucu içinde olabilir.Direct assignments to readonly fields can only occur as part of that declaration or in an instance constructor or static constructor in the same class. (Salt okunur bir alan, bu bağlamlarda birden çok kez atanabilir.) Özellikle, bir alana doğrudan atamalara readonly yalnızca aşağıdaki bağlamlarda izin verilir:(A readonly field can be assigned to multiple times in these contexts.) Specifically, direct assignments to a readonly field are permitted only in the following contexts:

  • Alanı tanıtan variable_declarator (bildirime bir variable_initializer ekleyerek).In the variable_declarator that introduces the field (by including a variable_initializer in the declaration).
  • Bir örnek alanı için, alan bildirimini içeren sınıfın örnek oluşturucularında; statik bir alan için, alan bildirimini içeren sınıfın statik oluşturucusunda.For an instance field, in the instance constructors of the class that contains the field declaration; for a static field, in the static constructor of the class that contains the field declaration. Bunlar ayrıca, bir readonly alanı veya parametresi olarak geçirmek için geçerli olduğu tek bağlamlardır out ref .These are also the only contexts in which it is valid to pass a readonly field as an out or ref parameter.

Bir readonly alana atamaya veya out diğer bağlamdaki bir veya parametresi olarak geçirmeye çalışılması ref derleme zamanı hatasıdır.Attempting to assign to a readonly field or pass it as an out or ref parameter in any other context is a compile-time error.

Sabitler için statik salt okunur alanlar kullanmaUsing static readonly fields for constants

Bir static readonly alan, bir sabit değer için simgesel ad istendiği, ancak değer türüne bildirimde izin verilmediğinde const veya değer derleme zamanında hesaplanmadığında faydalıdır.A static readonly field is useful when a symbolic name for a constant value is desired, but when the type of the value is not permitted in a const declaration, or when the value cannot be computed at compile-time. ÖrnekteIn the example

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);

    private byte red, green, blue;

    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

Black,, White , Red Green ve üyeleri, Blue const değerleri derleme zamanında hesaplanamadığından üye olarak bildirilemez.the Black, White, Red, Green, and Blue members cannot be declared as const members because their values cannot be computed at compile-time. Ancak, static readonly bunun yerine bunları bildirmek çok aynı etkiye sahiptir.However, declaring them static readonly instead has much the same effect.

Sabitler ve statik salt okunur alanların sürümü oluşturmaVersioning of constants and static readonly fields

Sabitler ve salt okunur alanlarında farklı ikili sürüm oluşturma semantiği vardır.Constants and readonly fields have different binary versioning semantics. Bir ifade bir sabit değere başvurduğunda, sabit değer derleme zamanında elde edilir, ancak bir ifade salt okunur bir alana başvurduğunda alanın değeri çalışma zamanına kadar elde edilmez.When an expression references a constant, the value of the constant is obtained at compile-time, but when an expression references a readonly field, the value of the field is not obtained until run-time. İki ayrı programda oluşan bir uygulamayı düşünün:Consider an application that consists of two separate programs:

using System;

namespace Program1
{
    public class Utils
    {
        public static readonly int X = 1;
    }
}

namespace Program2
{
    class Test
    {
        static void Main() {
            Console.WriteLine(Program1.Utils.X);
        }
    }
}

Program1Ve Program2 ad alanları ayrı olarak derlenen iki programı gösterir.The Program1 and Program2 namespaces denote two programs that are compiled separately. Program1.Utils.XStatik bir salt okunur alan olarak bildirildiği için, deyimin çıktı değeri Console.WriteLine derleme zamanında bilinmiyor, ancak bunun yerine çalışma zamanında elde edilir.Because Program1.Utils.X is declared as a static readonly field, the value output by the Console.WriteLine statement is not known at compile-time, but rather is obtained at run-time. Bu nedenle, değeri X değiştirilirse ve yeniden Program1 derlense, Console.WriteLine ifade yeniden derlenmemişse bile yeni değeri çıktı olarak çıkar Program2 .Thus, if the value of X is changed and Program1 is recompiled, the Console.WriteLine statement will output the new value even if Program2 isn't recompiled. Ancak, X bir sabit değer vardı, değeri derlenmiş durumda X alınır Program2 ve yeniden Program1 derlenene kadar ' deki değişikliklerden etkilenmemiştir Program2 .However, had X been a constant, the value of X would have been obtained at the time Program2 was compiled, and would remain unaffected by changes in Program1 until Program2 is recompiled.

Geçici alanlarVolatile fields

Bir field_declaration volatile değiştirici içerdiğinde, bu bildirim tarafından tanıtılan alanlar geçici alanlardır.When a field_declaration includes a volatile modifier, the fields introduced by that declaration are volatile fields.

Geçici olmayan alanlar için, yönergeleri yeniden sıralamak için en iyi duruma getirme teknikleri, lock_statement (kilit beyanı) tarafından sağlanmış gibi eşitleme olmadan alanlara erişen çok iş parçacıklı programlarda beklenmedik ve öngörülemeyen sonuçlara yol açabilir.For non-volatile fields, optimization techniques that reorder instructions can lead to unexpected and unpredictable results in multi-threaded programs that access fields without synchronization such as that provided by the lock_statement (The lock statement). Bu iyileştirmeler derleyici tarafından, çalışma zamanı sistemine veya donanımla gerçekleştirilebilir.These optimizations can be performed by the compiler, by the run-time system, or by hardware. Geçici alanlar için, bu tür yeniden sıralama iyileştirmeleri kısıtlanmıştır:For volatile fields, such reordering optimizations are restricted:

  • Geçici bir alan okuma, geçici okuma olarak adlandırılır.A read of a volatile field is called a volatile read. Geçici okuma "alma semantiğini" içerir; diğer bir deyişle, yönerge dizisinde bundan sonra meydana gelen tüm bellek başvurularından önce gerçekleşmesi garanti edilir.A volatile read has "acquire semantics"; that is, it is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence.
  • Geçici bir alan yazma, geçici yazma olarak adlandırılır.A write of a volatile field is called a volatile write. Geçici yazma "yayın semantiğini" içerir; diğer bir deyişle, yönerge dizisindeki yazma yönergesinden önce herhangi bir bellek başvurularından sonra gerçekleşmesi garanti edilir.A volatile write has "release semantics"; that is, it is guaranteed to happen after any memory references prior to the write instruction in the instruction sequence.

Bu kısıtlamalar, tüm iş parçacıklarının gerçekleştirilen diğer bir iş parçacığı tarafından gerçekleştirilen geçici yazmaları gözlemleyecek şekilde tüm iş parçacıkları tarafından gerçekleştirildiğinden emin olur.These restrictions ensure that all threads will observe volatile writes performed by any other thread in the order in which they were performed. Tüm yürütme iş parçacıklarında görüldüğü şekilde, geçici yazma işlemlerinin tek toplam sıralamasını sağlamak için uygun bir uygulama gerekmez.A conforming implementation is not required to provide a single total ordering of volatile writes as seen from all threads of execution. Geçici bir alanın türü aşağıdakilerden biri olmalıdır:The type of a volatile field must be one of the following:

  • Bir reference_type.A reference_type.
  • Türü,,,,, byte sbyte short ushort int uint , char , float , bool , System.IntPtr , veya System.UIntPtr .The type byte, sbyte, short, ushort, int, uint, char, float, bool, System.IntPtr, or System.UIntPtr.
  • ,,,, Veya sabit listesi temel türüne sahip bir enum_type byte sbyte short ushort int uint .An enum_type having an enum base type of byte, sbyte, short, ushort, int, or uint.

ÖrnekteThe example

using System;
using System.Threading;

class Test
{
    public static int result;   
    public static volatile bool finished;

    static void Thread2() {
        result = 143;    
        finished = true; 
    }

    static void Main() {
        finished = false;

        // Run Thread2() in a new thread
        new Thread(new ThreadStart(Thread2)).Start();

        // Wait for Thread2 to signal that it has a result by setting
        // finished to true.
        for (;;) {
            if (finished) {
                Console.WriteLine("result = {0}", result);
                return;
            }
        }
    }
}

çıktıyı üretir:produces the output:

result = 143

Bu örnekte, yöntemi Main yöntemini çalıştıran yeni bir iş parçacığı başlatır Thread2 .In this example, the method Main starts a new thread that runs the method Thread2. Bu yöntem, bir değeri geçici olmayan bir alana depolar result , ardından true geçici alanda depolar finished .This method stores a value into a non-volatile field called result, then stores true in the volatile field finished. Ana iş parçacığı alanın finished olarak ayarlanması için bekler true , sonra alanı okur result .The main thread waits for the field finished to be set to true, then reads the field result. Bu yana finished bildirildiği için volatile , ana iş parçacığının alandan değeri okuması gerekir 143 result .Since finished has been declared volatile, the main thread must read the value 143 from the field result. Alan bildirilmemiş ise finished volatile , deponun result mağazadan sonra ana iş parçacığında görünür olması finished ve bu nedenle ana iş parçacığının alandan değeri okuması için izin verilebilir 0 result .If the field finished had not been declared volatile, then it would be permissible for the store to result to be visible to the main thread after the store to finished, and hence for the main thread to read the value 0 from the field result. finishedAlan olarak bildirmek, volatile Bu tür tutarsızlığın yapılmasını engeller.Declaring finished as a volatile field prevents any such inconsistency.

Alan başlatmaField initialization

Bir alanın başlangıçtaki değeri, bir statik alan veya örnek alanı olsun, alanın türünün varsayılan değeridir (varsayılan değerlerdir).The initial value of a field, whether it be a static field or an instance field, is the default value (Default values) of the field's type. Bu varsayılan başlatma gerçekleştirilmeden önce bir alanın değerini gözlemlemek mümkün değildir ve bir alan bu nedenle hiçbir şekilde "başlatılmamış" olur.It is not possible to observe the value of a field before this default initialization has occurred, and a field is thus never "uninitialized". ÖrnekteThe example

using System;

class Test
{
    static bool b;
    int i;

    static void Main() {
        Test t = new Test();
        Console.WriteLine("b = {0}, i = {1}", b, t.i);
    }
}

çıktıyı üretirproduces the output

b = False, i = 0

bve i her ikisi de otomatik olarak varsayılan değerlere başlatılmıştı.because b and i are both automatically initialized to default values.

Değişken başlatıcılarıVariable initializers

Alan bildirimlerinde variable_initializer s bulunabilir.Field declarations may include variable_initializer s. Statik alanlar için, değişken başlatıcıları sınıf başlatma sırasında yürütülen atama ifadelerine karşılık gelir.For static fields, variable initializers correspond to assignment statements that are executed during class initialization. Örnek alanları için, değişken başlatıcıları, sınıfının bir örneği oluşturulduğunda yürütülen atama ifadelerine karşılık gelir.For instance fields, variable initializers correspond to assignment statements that are executed when an instance of the class is created.

ÖrnekteThe example

using System;

class Test
{
    static double x = Math.Sqrt(2.0);
    int i = 100;
    string s = "Hello";

    static void Main() {
        Test a = new Test();
        Console.WriteLine("x = {0}, i = {1}, s = {2}", x, a.i, a.s);
    }
}

çıktıyı üretirproduces the output

x = 1.4142135623731, i = 100, s = Hello

xstatik alan başlatıcılarının yürütmesi ve atamaları i s , örnek alanı başlatıcıları çalıştırıldığında meydana gelir.because an assignment to x occurs when static field initializers execute and assignments to i and s occur when the instance field initializers execute.

Alan başlatma bölümünde açıklanan varsayılan değer başlatma, değişken başlatıcıları olan alanlar da dahil olmak üzere tüm alanlar için gerçekleşir.The default value initialization described in Field initialization occurs for all fields, including fields that have variable initializers. Bu nedenle, bir sınıf başlatıldığında, bu sınıftaki tüm statik alanlar ilk olarak varsayılan değerlerine başlatılır ve statik alan başlatıcıları, metinsel sırada yürütülür.Thus, when a class is initialized, all static fields in that class are first initialized to their default values, and then the static field initializers are executed in textual order. Benzer şekilde, bir sınıf örneği oluşturulduğunda, söz konusu örnekteki tüm örnek alanları ilk olarak varsayılan değerlerine başlatılır ve sonra örnek alanı başlatıcıları, metinsel sırada yürütülür.Likewise, when an instance of a class is created, all instance fields in that instance are first initialized to their default values, and then the instance field initializers are executed in textual order.

Değişken başlatıcıların varsayılan değer durumunda gözlenecek statik alanlar mümkündür.It is possible for static fields with variable initializers to be observed in their default value state. Ancak, bu stil önemli bir şekilde önerilmez.However, this is strongly discouraged as a matter of style. ÖrnekteThe example

using System;

class Test
{
    static int a = b + 1;
    static int b = a + 1;

    static void Main() {
        Console.WriteLine("a = {0}, b = {1}", a, b);
    }
}

Bu davranışı sergiler.exhibits this behavior. A ve b 'nin dairesel tanımlarına rağmen program geçerli olur.Despite the circular definitions of a and b, the program is valid. Çıkışa neden olurIt results in the output

a = 1, b = 2

statik alanlar ve, a b 0 başlatıcıları yürütülmeden önce (için varsayılan değer) olarak başlatılır int .because the static fields a and b are initialized to 0 (the default value for int) before their initializers are executed. Başlatıcısı a çalıştırıldığında değeri sıfır olduğunda, b a olarak başlatılır 1 .When the initializer for a runs, the value of b is zero, and so a is initialized to 1. Başlatıcısı b çalıştırıldığında, değeri a zaten olur 1 ve b olarak başlatılır 2 .When the initializer for b runs, the value of a is already 1, and so b is initialized to 2.

Statik alan başlatmaStatic field initialization

Bir sınıfın statik alan değişkeni başlatıcıları, sınıf bildiriminde göründükleri metin sırasına göre yürütülen atama dizisine karşılık gelir.The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. Sınıfında statik bir Oluşturucu (statik oluşturucular) varsa, statik alan başlatıcılarının yürütülmesi bu statik oluşturucunun yürütülmesi için hemen önce gerçekleşir.If a static constructor (Static constructors) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Aksi takdirde, statik alan başlatıcıları, bu sınıfın statik alanı ilk kullanılmadan önce uygulamayla ilgili bir süre içinde yürütülür.Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class. ÖrnekteThe example

using System;

class Test 
{ 
    static void Main() {
        Console.WriteLine("{0} {1}", B.Y, A.X);
    }

    public static int F(string s) {
        Console.WriteLine(s);
        return 1;
    }
}

class A
{
    public static int X = Test.F("Init A");
}

class B
{
    public static int Y = Test.F("Init B");
}

çıktıyı üretebilir:might produce either the output:

Init A
Init B
1 1

veya çıkış:or the output:

Init B
Init A
1 1

Xbaşlatıcısının ve Y başlatıcısının yürütülmesi sırayla gerçekleşebileceğinden, bu alanlar yalnızca bu alanlara başvurularından önce gerçekleşirler.because the execution of X's initializer and Y's initializer could occur in either order; they are only constrained to occur before the references to those fields. Ancak, örnekte:However, in the example:

using System;

class Test
{
    static void Main() {
        Console.WriteLine("{0} {1}", B.Y, A.X);
    }

    public static int F(string s) {
        Console.WriteLine(s);
        return 1;
    }
}

class A
{
    static A() {}

    public static int X = Test.F("Init A");
}

class B
{
    static B() {}

    public static int Y = Test.F("Init B");
}

çıkışın olması gerekir:the output must be:

Init B
Init A
1 1

statik oluşturucuların çalıştırıldığı zaman için kurallar ( statik oluşturuculardatanımlandığı gibi), bu B statik oluşturucuyu (ve bu nedenle B statik alan başlatıcıları) A statik oluşturucu ve alan başlatıcılarından önce çalıştırması gerekir.because the rules for when static constructors execute (as defined in Static constructors) provide that B's static constructor (and hence B's static field initializers) must run before A's static constructor and field initializers.

Örnek alanı başlatmaInstance field initialization

Bir sınıfın örnek alanı değişken başlatıcıları, bu sınıfın örnek oluşturucularından (Oluşturucu başlatıcıların) herhangi birine girişte hemen yürütülen atama dizisine karşılık gelir.The instance field variable initializers of a class correspond to a sequence of assignments that are executed immediately upon entry to any one of the instance constructors (Constructor initializers) of that class. Değişken başlatıcıları, sınıf bildiriminde göründükleri metin sırasına göre yürütülür.The variable initializers are executed in the textual order in which they appear in the class declaration. Sınıf örneği oluşturma ve başlatma işlemi, örnek oluşturuculardadaha ayrıntılı olarak açıklanmıştır.The class instance creation and initialization process is described further in Instance constructors.

Örnek alanı için değişken Başlatıcısı oluşturulan örneğe başvuramaz.A variable initializer for an instance field cannot reference the instance being created. Bu nedenle, bir değişken başlatıcısında başvurmak için derleme zamanı hatası this , bir değişken başlatıcısı için bir simple_name aracılığıyla herhangi bir örnek üyesine başvuruda bulunmak üzere bir derleme zamanı hatası olur.Thus, it is a compile-time error to reference this in a variable initializer, as it is a compile-time error for a variable initializer to reference any instance member through a simple_name. ÖrnekteIn the example

class A
{
    int x = 1;
    int y = x + 1;        // Error, reference to instance member of this
}

için değişken başlatıcısı, y oluşturulmakta olan Örneğin bir üyesine başvurduğundan derleme zamanı hatası ile sonuçlanır.the variable initializer for y results in a compile-time error because it references a member of the instance being created.

YöntemlerMethods

*Yöntemi _ bir nesne veya sınıf tarafından gerçekleştirilebilecek bir hesaplama veya eylem uygulayan bir üyedir.A *method _ is a member that implements a computation or action that can be performed by an object or class. Yöntemler _method_declaration * s kullanılarak bildirilmiştir:Methods are declared using _method_declaration*s:

method_declaration
    : method_header method_body
    ;

method_header
    : attributes? method_modifier* 'partial'? return_type member_name type_parameter_list?
      '(' formal_parameter_list? ')' type_parameter_constraints_clause*
    ;

method_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'static'
    | 'virtual'
    | 'sealed'
    | 'override'
    | 'abstract'
    | 'extern'
    | 'async'
    | method_modifier_unsafe
    ;

return_type
    : type
    | 'void'
    ;

member_name
    : identifier
    | interface_type '.' identifier
    ;

method_body
    : block
    | '=>' expression ';'
    | ';'
    ;

Bir method_declaration bir öznitelikler kümesi (öznitelikler) ve dört erişim değiştiricisinin (erişim değiştiricileri), ( new Yeni değiştirici), static (statik ve örnek yöntemleri), ( virtual sanal yöntemler), ( override geçersiz kılma yöntemleri), (korumalı Yöntemler), (soyut yöntemler sealed ) abstract ve extern (dış Yöntemler) değiştiricilerin geçerli bir bileşimini içerebilir.A method_declaration may include a set of attributes (Attributes) and a valid combination of the four access modifiers (Access modifiers), the new (The new modifier), static (Static and instance methods), virtual (Virtual methods), override (Override methods), sealed (Sealed methods), abstract (Abstract methods), and extern (External methods) modifiers.

Aşağıdakilerin tümü doğru ise bir bildirimin geçerli bir değiştiriciler birleşimi vardır:A declaration has a valid combination of modifiers if all of the following are true:

  • Bildirim, geçerli bir erişim değiştiricileri (erişim değiştiricileri) birleşimini içerir.The declaration includes a valid combination of access modifiers (Access modifiers).
  • Bildirim, aynı değiştiriciyi birden çok kez içermez.The declaration does not include the same modifier multiple times.
  • Bildirim aşağıdaki değiştiricilerin en çok birini içerir: static , virtual ve override .The declaration includes at most one of the following modifiers: static, virtual, and override.
  • Bildirim aşağıdaki değiştiricilerin en çok birini içerir: new ve override .The declaration includes at most one of the following modifiers: new and override.
  • Bildirim abstract değiştiricisini içeriyorsa, bildirim aşağıdaki değiştiricilerin hiçbirini içermez: static , virtual , sealed veya extern .If the declaration includes the abstract modifier, then the declaration does not include any of the following modifiers: static, virtual, sealed or extern.
  • Bildirim private değiştiricisini içeriyorsa, bildirim aşağıdaki değiştiricilerin hiçbirini içermez: virtual , override , veya abstract .If the declaration includes the private modifier, then the declaration does not include any of the following modifiers: virtual, override, or abstract.
  • Bildirim sealed değiştiricisini içeriyorsa, bildirim de override değiştirici içerir.If the declaration includes the sealed modifier, then the declaration also includes the override modifier.
  • Bildirim partial değiştiricisini içeriyorsa, şu değiştiricilerin hiçbirini içermez: new , public ,, protected internal , private , virtual , sealed , override , abstract veya extern .If the declaration includes the partial modifier, then it does not include any of the following modifiers: new, public, protected, internal, private, virtual, sealed, override, abstract, or extern.

Değiştiriciye sahip bir yöntem async zaman uyumsuz işlevdir ve zaman uyumsuz işlevlerdeaçıklanan kuralları izler.A method that has the async modifier is an async function and follows the rules described in Async functions.

Bir yöntem bildiriminin return_type , yöntemi tarafından hesaplanan ve döndürülen değerin türünü belirtir.The return_type of a method declaration specifies the type of the value computed and returned by the method. Return_type , void yöntemin bir değer döndürmemelidir.The return_type is void if the method does not return a value. Bildirim partial değiştiricisini içeriyorsa, dönüş türü olmalıdır void .If the declaration includes the partial modifier, then the return type must be void.

MEMBER_NAME , yöntemin adını belirtir.The member_name specifies the name of the method. Yöntem açık arabirim üyesi uygulaması (Açık arabirim üyesi uygulamalar) değilse, MEMBER_NAME yalnızca bir tanıtıcıdır.Unless the method is an explicit interface member implementation (Explicit interface member implementations), the member_name is simply an identifier. Açık arabirim üyesi uygulama için MEMBER_NAME , bir interface_type ve ardından bir . tanımlayıcı ile oluşur.For an explicit interface member implementation, the member_name consists of an interface_type followed by a "." and an identifier.

İsteğe bağlı type_parameter_list , yöntemin tür parametrelerini belirtir (tür parametreleri).The optional type_parameter_list specifies the type parameters of the method (Type parameters). Bir type_parameter_list belirtilirse, yöntem *genel bir yöntem _ ' dir.If a type_parameter_list is specified the method is a *generic method _. Metotta bir extern değiştirici varsa, bir _type_parameter_list * belirtilemez.If the method has an extern modifier, a _type_parameter_list* cannot be specified.

İsteğe bağlı formal_parameter_list yönteminin parametrelerini belirtir (Yöntem parametreleri).The optional formal_parameter_list specifies the parameters of the method (Method parameters).

İsteğe bağlı type_parameter_constraints_clause, bağımsız tür parametrelerinde (tür parametresi kısıtlamaları) kısıtlamaları belirtir ve yalnızca bir type_parameter_list sağlandıysa ve yöntemin bir değiştiricisi yoksa belirtilebilir override .The optional type_parameter_constraints_clause s specify constraints on individual type parameters (Type parameter constraints) and may only be specified if a type_parameter_list is also supplied, and the method does not have an override modifier.

Return_type ve bir yöntemin formal_parameter_list başvuruda bulunulan türlerin her biri, metodun kendisi (Erişilebilirlik kısıtlamaları) olarak en az erişilebilir olmalıdır.The return_type and each of the types referenced in the formal_parameter_list of a method must be at least as accessible as the method itself (Accessibility constraints).

Method_body noktalı virgül, deyim gövdesi _ veya bir _ifade gövdesi*.The method_body is either a semicolon, a statement body _ or an _expression body*. Deyim gövdesi, yöntemi çağrıldığında yürütülecek deyimleri belirten bir _block * oluşur.A statement body consists of a _block*, which specifies the statements to execute when the method is invoked. Bir ifade gövdesi => , sonrasında bir ifade ve noktalı virgül ile oluşur ve yöntem çağrıldığında gerçekleştirilecek tek bir ifadeyi gösterir.An expression body consists of => followed by an expression and a semicolon, and denotes a single expression to perform when the method is invoked.

abstractVe extern yöntemleri için method_body yalnızca noktalı virgülden oluşur.For abstract and extern methods, the method_body consists simply of a semicolon. partialYöntemler için method_body noktalı virgül, blok gövdesinden veya bir ifade gövdesinden oluşabilir.For partial methods the method_body may consist of either a semicolon, a block body or an expression body. Diğer tüm yöntemler için method_body bir blok gövdesi ya da bir ifade gövdesidir.For all other methods, the method_body is either a block body or an expression body.

Method_body noktalı virgül içeriyorsa, bildirim async değiştiriciyi içermeyebilir.If the method_body consists of a semicolon, then the declaration may not include the async modifier.

Ad, tür parametre listesi ve bir yöntemin biçimsel parametre listesi metodun imzasını (imzalar ve aşırı yükleme) tanımlar.The name, the type parameter list and the formal parameter list of a method define the signature (Signatures and overloading) of the method. Özellikle, bir yöntemin imzası adından, tür parametrelerinin sayısından ve biçimsel parametrelerinin sayısı, değiştiricilerinden ve türlerinden oluşur.Specifically, the signature of a method consists of its name, the number of type parameters and the number, modifiers, and types of its formal parameters. Bu amaçlar için, bir biçimsel parametre türünde oluşan yöntemin tür parametresi, kendi adı tarafından değil, yönteminin tür bağımsız değişkeni listesindeki sıra konumuna göre tanımlanır. Dönüş türü yöntemin imzasının bir parçası değildir, ya da tür parametrelerinin ya da biçimsel parametrelerin adları değildir.For these purposes, any type parameter of the method that occurs in the type of a formal parameter is identified not by its name, but by its ordinal position in the type argument list of the method.The return type is not part of a method's signature, nor are the names of the type parameters or the formal parameters.

Bir yöntemin adı aynı sınıfta belirtilen diğer tüm yöntemlerin adlarından farklı olmalıdır.The name of a method must differ from the names of all other non-methods declared in the same class. Ayrıca, bir yöntemin imzası aynı sınıfta belirtilen diğer tüm yöntemlerin imzalarından farklı olmalıdır ve aynı sınıfta belirtilen iki yöntem yalnızca ve ile farklı imzalara sahip olamaz ref out .In addition, the signature of a method must differ from the signatures of all other methods declared in the same class, and two methods declared in the same class may not have signatures that differ solely by ref and out.

Yöntemin type_parameter s method_declaration tamamında kapsam içinde yer alabilir ve bu kapsam genelinde return_type, method_body ve type_parameter_constraints_clause, ancak özniteliklerde olmayan türleri oluşturmak için kullanılabilir.The method's type_parameter s are in scope throughout the method_declaration, and can be used to form types throughout that scope in return_type, method_body, and type_parameter_constraints_clause s but not in attributes.

Tüm biçimsel parametrelerin ve tür parametrelerinin adları farklı olmalıdır.All formal parameters and type parameters must have different names.

Yöntem parametreleriMethod parameters

Bir yöntemin parametreleri, varsa, yöntemin formal_parameter_list tarafından tanımlanır.The parameters of a method, if any, are declared by the method's formal_parameter_list.

formal_parameter_list
    : fixed_parameters
    | fixed_parameters ',' parameter_array
    | parameter_array
    ;

fixed_parameters
    : fixed_parameter (',' fixed_parameter)*
    ;

fixed_parameter
    : attributes? parameter_modifier? type identifier default_argument?
    ;

default_argument
    : '=' expression
    ;

parameter_modifier
    : 'ref'
    | 'out'
    | 'this'
    ;

parameter_array
    : attributes? 'params' array_type identifier
    ;

Biçimsel parametre listesi bir veya daha fazla virgülle ayrılmış parametrelerden oluşur ve bunlardan yalnızca sonuncusu parameter_array olabilir.The formal parameter list consists of one or more comma-separated parameters of which only the last may be a parameter_array.

Fixed_parameter , isteğe bağlı bir öznitelik kümesi (öznitelikler), isteğe bağlı ref out veya this değiştirici, bir tür, tanımlayıcı ve isteğe bağlı default_argument oluşur.A fixed_parameter consists of an optional set of attributes (Attributes), an optional ref, out or this modifier, a type, an identifier and an optional default_argument. Her fixed_parameter , verilen türdeki bir parametreyi verilen ada bildirir.Each fixed_parameter declares a parameter of the given type with the given name. thisDeğiştirici yöntemi bir genişletme yöntemi olarak belirler ve yalnızca bir statik metodun ilk parametresinde kullanılabilir.The this modifier designates the method as an extension method and is only allowed on the first parameter of a static method. Uzantı yöntemleri uzantı yöntemlerindedaha ayrıntılı olarak açıklanmıştır.Extension methods are further described in Extension methods.

Default_argument bir fixed_parameter , *isteğe bağlı bir parametre olan , ancak *default_argument* olmayan bir fixed_parameter * gerekli bir parametredir.A fixed_parameter with a default_argument is known as an optional parameter _, whereas a _fixed_parameter without a default_argument is a *required parameter. Gerekli bir parametre, bir _formal_parameter_list * içinde isteğe bağlı bir parametreden sonra görünmeyebilir.A required parameter may not appear after an optional parameter in a _formal_parameter_list*.

Bir ref veya out parametresi default_argument olamaz.A ref or out parameter cannot have a default_argument. Bir default_argument ifade aşağıdakilerden biri olmalıdır:The expression in a default_argument must be one of the following:

  • bir constant_expressiona constant_expression
  • form new S() S bir değer türü olan bir ifadean expression of the form new S() where S is a value type
  • form default(S) S bir değer türü olan bir ifadean expression of the form default(S) where S is a value type

İfade , bir kimlikle örtük olarak dönüştürülebilir veya parametrenin türüne null olabilen dönüştürmeye sahip olmalıdır.The expression must be implicitly convertible by an identity or nullable conversion to the type of the parameter.

Bir uygulama kısmi yöntem bildiriminde (kısmi Yöntemler) isteğe bağlı parametreler oluşursa, açık bir arabirim üye uygulaması (Açık arabirim üyesi uygulamalar) veya tek parametreli Dizin Oluşturucu bildiriminde (Dizin oluşturucular), bu Üyeler asla bağımsız değişkenlerin atlanmasına izin vermek için hiçbir şekilde çağrılabileceğinden, derleyici bir uyarı vermelidir.If optional parameters occur in an implementing partial method declaration (Partial methods) , an explicit interface member implementation (Explicit interface member implementations) or in a single-parameter indexer declaration (Indexers) the compiler should give a warning, since these members can never be invoked in a way that permits arguments to be omitted.

Parameter_array , isteğe bağlı bir öznitelik kümesi (öznitelikler), params değiştirici, bir array_type ve bir tanımlayıcı kümesinden oluşur.A parameter_array consists of an optional set of attributes (Attributes), a params modifier, an array_type, and an identifier. Bir parametre dizisi verilen bir ada sahip belirtilen dizi türünün tek bir parametresini bildirir.A parameter array declares a single parameter of the given array type with the given name. Bir parametre dizisinin array_type , tek boyutlu bir dizi türü (dizi türleri) olmalıdır.The array_type of a parameter array must be a single-dimensional array type (Array types). Bir yöntem çağrısında, bir parametre dizisi verilen dizi türünün tek bir bağımsız değişkeninin belirtilmesine izin verir veya dizi öğe türünde sıfır veya daha fazla bağımsız değişken belirtilmesine izin verir.In a method invocation, a parameter array permits either a single argument of the given array type to be specified, or it permits zero or more arguments of the array element type to be specified. Parametre dizileri, parametre dizileriiçinde daha ayrıntılı olarak açıklanmıştır.Parameter arrays are described further in Parameter arrays.

Bir parameter_array isteğe bağlı bir parametreden sonra gerçekleşebilir, ancak varsayılan bir değere sahip olamaz. bunun yerine parameter_array bağımsız değişkenlerin atlanmasından sonra boş bir dizi oluşturulmasına neden olur.A parameter_array may occur after an optional parameter, but cannot have a default value -- the omission of arguments for a parameter_array would instead result in the creation of an empty array.

Aşağıdaki örnek farklı parametre türlerini göstermektedir:The following example illustrates different kinds of parameters:

public void M(
    ref int      i,
    decimal      d,
    bool         b = false,
    bool?        n = false,
    string       s = "Hello",
    object       o = null,
    T            t = default(T),
    params int[] a
) { }

İçin formal_parameter_list , M i gerekli bir başvuru parametresidir,,,, d b s o ve t isteğe bağlı değer parametreleridir ve a bir parametre dizisidir.In the formal_parameter_list for M, i is a required ref parameter, d is a required value parameter, b, s, o and t are optional value parameters and a is a parameter array.

Yöntem bildirimi parametreler, tür parametreleri ve yerel değişkenler için ayrı bir bildirim alanı oluşturur.A method declaration creates a separate declaration space for parameters, type parameters and local variables. Adlar, bu bildirim alanına tür parametresi listesi ve yöntemin biçimsel parametre listesi ve yöntemin bloğundaki yerel değişken bildirimleri tarafından tanıtılmıştır.Names are introduced into this declaration space by the type parameter list and the formal parameter list of the method and by local variable declarations in the block of the method. Bir yöntem bildirim alanının iki üyesinin aynı ada sahip olması için bir hatadır.It is an error for two members of a method declaration space to have the same name. Aynı ada sahip öğeleri içermesi için bir iç içe geçmiş bildirim alanının yöntem bildirim alanı ve yerel değişken bildirim alanı için bir hatadır.It is an error for the method declaration space and the local variable declaration space of a nested declaration space to contain elements with the same name.

Yöntem çağırma (Yöntem etkinleştirmeleri), bu çağrıya özgü bir kopya oluşturur; Bu, biçimsel parametreler ve yöntemin yerel değişkenleri ve çağrının bağımsız değişken listesi, yeni oluşturulan biçimsel parametrelere değerler veya değişken başvuruları atar.A method invocation (Method invocations) creates a copy, specific to that invocation, of the formal parameters and local variables of the method, and the argument list of the invocation assigns values or variable references to the newly created formal parameters. Bir yöntem bloğunun içinde, biçimsel parametrelere simple_name ifadelerinde tanımlayıcıları (basit adlar) tarafından başvurulabilir.Within the block of a method, formal parameters can be referenced by their identifiers in simple_name expressions (Simple names).

Dört tür biçimsel parametre vardır:There are four kinds of formal parameters:

  • Herhangi bir değiştirici olmadan bildirildiği değer parametreleri.Value parameters, which are declared without any modifiers.
  • Değiştiriciyle belirtilen başvuru parametreleri ref .Reference parameters, which are declared with the ref modifier.
  • Değiştirici ile belirtilen çıkış parametreleri out .Output parameters, which are declared with the out modifier.
  • Değiştiriciyle belirtilen parametre dizileri params .Parameter arrays, which are declared with the params modifier.

İmzalar ve aşırı yüklemebölümünde açıklandığı gibi, ref ve out değiştiricileri yöntemin imzasının bir parçasıdır, ancak params değiştirici değildir.As described in Signatures and overloading, the ref and out modifiers are part of a method's signature, but the params modifier is not.

Değer parametreleriValue parameters

Değiştirici olmadan belirtilen bir parametre bir değer parametresidir.A parameter declared with no modifiers is a value parameter. Değer parametresi, yöntem çağrısında sağlanan karşılık gelen bağımsız değişkenden ilk değerini alan yerel bir değişkene karşılık gelir.A value parameter corresponds to a local variable that gets its initial value from the corresponding argument supplied in the method invocation.

Bir biçimsel parametre bir değer parametresi olduğunda, bir yöntem çağrısında karşılık gelen bağımsız değişken, biçimsel parametre türüne örtük olarak dönüştürülebilir (örtük dönüştürmeler) bir ifade olmalıdır.When a formal parameter is a value parameter, the corresponding argument in a method invocation must be an expression that is implicitly convertible (Implicit conversions) to the formal parameter type.

Bir yöntem bir değer parametresine yeni değerler atamaya izin verilir.A method is permitted to assign new values to a value parameter. Bu atamalar yalnızca değer parametresi tarafından temsil edilen yerel depolama konumunu etkiler — Yöntem çağrısında verilen gerçek bağımsız değişkeni üzerinde hiçbir etkisi yoktur.Such assignments only affect the local storage location represented by the value parameter—they have no effect on the actual argument given in the method invocation.

Başvuru parametreleriReference parameters

Değiştirici ile belirtilen bir parametre ref bir başvuru parametresidir.A parameter declared with a ref modifier is a reference parameter. Değer parametresinden farklı olarak, başvuru parametresi yeni bir depolama konumu oluşturmaz.Unlike a value parameter, a reference parameter does not create a new storage location. Bunun yerine, başvuru parametresi, yöntem çağrısında bağımsız değişken olarak verilen değişkenle aynı depolama konumunu temsil eder.Instead, a reference parameter represents the same storage location as the variable given as the argument in the method invocation.

Bir biçimsel parametre bir başvuru parametresi olduğunda, bir yöntem çağrısında karşılık gelen bağımsız değişken, ref biçimsel parametre ile aynı türdeki bir variable_reference (kesin atamayı belirlemek için kesin kurallar) ve ardından anahtar sözcüğünden oluşmalıdır.When a formal parameter is a reference parameter, the corresponding argument in a method invocation must consist of the keyword ref followed by a variable_reference (Precise rules for determining definite assignment) of the same type as the formal parameter. Bir değişken başvuru parametresi olarak geçirilebilmesi için kesinlikle atanmalı.A variable must be definitely assigned before it can be passed as a reference parameter.

Bir yöntem içinde, başvuru parametresi her zaman kesinlikle atanmış olarak değerlendirilir.Within a method, a reference parameter is always considered definitely assigned.

Yineleyici (yineleyiciler) olarak belirtilen bir yöntemin başvuru parametreleri olamaz.A method declared as an iterator (Iterators) cannot have reference parameters.

ÖrnekteThe example

using System;

class Test
{
    static void Swap(ref int x, ref int y) {
        int temp = x;
        x = y;
        y = temp;
    }

    static void Main() {
        int i = 1, j = 2;
        Swap(ref i, ref j);
        Console.WriteLine("i = {0}, j = {1}", i, j);
    }
}

çıktıyı üretirproduces the output

i = 2, j = 1

İçinde çağrısı için Swap Main , x temsil eder i ve y temsil eder j .For the invocation of Swap in Main, x represents i and y represents j. Bu nedenle, çağırma, ve değerlerini değiştirme etkisine sahiptir i j .Thus, the invocation has the effect of swapping the values of i and j.

Başvuru parametreleri alan bir yöntemde, birden fazla ad aynı depolama konumunu temsil etmek mümkündür.In a method that takes reference parameters it is possible for multiple names to represent the same storage location. ÖrnekteIn the example

class A
{
    string s;

    void F(ref string a, ref string b) {
        s = "One";
        a = "Two";
        b = "Three";
    }

    void G() {
        F(ref s, ref s);
    }
}

içinde çağrısı, F G ve için bir başvuru geçirir s a b .the invocation of F in G passes a reference to s for both a and b. Bu nedenle, bu çağrı için adlar, s a ve b tümü aynı depolama konumuna başvurur ve üç atama, örnek alanını değiştirir s .Thus, for that invocation, the names s, a, and b all refer to the same storage location, and the three assignments all modify the instance field s.

Çıktı parametreleriOutput parameters

Değiştirici ile belirtilen bir parametre bir out çıkış parametresidir.A parameter declared with an out modifier is an output parameter. Bir başvuru parametresine benzer şekilde, çıkış parametresi yeni bir depolama konumu oluşturmaz.Similar to a reference parameter, an output parameter does not create a new storage location. Bunun yerine, bir çıktı parametresi, yöntem çağrısında bağımsız değişken olarak verilen değişkenle aynı depolama konumunu temsil eder.Instead, an output parameter represents the same storage location as the variable given as the argument in the method invocation.

Bir biçimsel parametre bir çıkış parametresi olduğunda, bir yöntem çağrısında karşılık gelen bağımsız değişken, out biçimsel parametre ile aynı türdeki bir variable_reference (kesin atamayı belirlemek için kesin kurallar) ve ardından anahtar sözcüğünden oluşmalıdır.When a formal parameter is an output parameter, the corresponding argument in a method invocation must consist of the keyword out followed by a variable_reference (Precise rules for determining definite assignment) of the same type as the formal parameter. Bir değişken, çıkış parametresi olarak geçirilebilmesi için kesinlikle atanmamalıdır, ancak bir değişkenin çıkış parametresi olarak geçirildiği bir çağrıdan sonra, değişken kesinlikle atanmış olarak değerlendirilir.A variable need not be definitely assigned before it can be passed as an output parameter, but following an invocation where a variable was passed as an output parameter, the variable is considered definitely assigned.

Bir yöntem içinde, yerel bir değişken gibi, bir çıkış parametresi başlangıçta atanmamış olarak kabul edilir ve değeri kullanılmadan önce kesinlikle atanmalıdır.Within a method, just like a local variable, an output parameter is initially considered unassigned and must be definitely assigned before its value is used.

Metodun her çıkış parametresi, yöntemin döndürüldüğünden önce kesinlikle atanmalıdır.Every output parameter of a method must be definitely assigned before the method returns.

Kısmi Yöntem (kısmi Yöntemler) veya yineleyici (yineleyiciler) olarak belirtilen bir yöntem çıkış parametrelerine sahip olamaz.A method declared as a partial method (Partial methods) or an iterator (Iterators) cannot have output parameters.

Çıkış parametreleri genellikle birden çok dönüş değeri üreten yöntemlerde kullanılır.Output parameters are typically used in methods that produce multiple return values. Örnek:For example:

using System;

class Test
{
    static void SplitPath(string path, out string dir, out string name) {
        int i = path.Length;
        while (i > 0) {
            char ch = path[i - 1];
            if (ch == '\\' || ch == '/' || ch == ':') break;
            i--;
        }
        dir = path.Substring(0, i);
        name = path.Substring(i);
    }

    static void Main() {
        string dir, name;
        SplitPath("c:\\Windows\\System\\hello.txt", out dir, out name);
        Console.WriteLine(dir);
        Console.WriteLine(name);
    }
}

Örnek, çıktıyı üretir:The example produces the output:

c:\Windows\System\
hello.txt

dirVe name değişkenlerinin geçirilmeden önce atanmamış olabileceğini SplitPath ve çağrının ardından kesinlikle atandığına göz önünde bulundurmanız gerekir.Note that the dir and name variables can be unassigned before they are passed to SplitPath, and that they are considered definitely assigned following the call.

Parametre dizileriParameter arrays

Değiştirici ile belirtilen bir parametre params bir parametre dizisidir.A parameter declared with a params modifier is a parameter array. Bir biçimsel parametre listesi bir parametre dizisi içeriyorsa, listedeki son parametre olmalıdır ve tek boyutlu dizi türünde olmalıdır.If a formal parameter list includes a parameter array, it must be the last parameter in the list and it must be of a single-dimensional array type. Örneğin, türleri string[] ve string[][] Parametre dizisinin türü olarak kullanılabilir, ancak tür string[,] olamaz.For example, the types string[] and string[][] can be used as the type of a parameter array, but the type string[,] can not. Değiştiriciyi params değiştiriciler ve ile birleştirmek mümkün değildir ref out .It is not possible to combine the params modifier with the modifiers ref and out.

Bir parametre dizisi bağımsız değişkenlerin bir yöntem çağrısında iki yöntemden biriyle belirtilmesine izin verir:A parameter array permits arguments to be specified in one of two ways in a method invocation:

  • Bir parametre dizisi için verilen bağımsız değişken, parametre dizisi türüne örtük olarak dönüştürülebilir (örtük dönüştürmeler) tek bir ifade olabilir.The argument given for a parameter array can be a single expression that is implicitly convertible (Implicit conversions) to the parameter array type. Bu durumda, parametre dizisi tam olarak bir değer parametresi gibi davranır.In this case, the parameter array acts precisely like a value parameter.
  • Alternatif olarak, çağırma parametre dizisi için sıfır veya daha fazla bağımsız değişken belirtebilir, burada her bağımsız değişken parametre dizisinin öğe türüne örtük olarak dönüştürülebilir (örtük dönüştürmeler) bir ifadedir.Alternatively, the invocation can specify zero or more arguments for the parameter array, where each argument is an expression that is implicitly convertible (Implicit conversions) to the element type of the parameter array. Bu durumda, çağırma parametre dizisi türünde bağımsız değişken sayısına karşılık gelen bir örnek oluşturur, dizi örneğinin öğelerini verilen bağımsız değişken değerleriyle başlatır ve yeni oluşturulan dizi örneğini gerçek bağımsız değişken olarak kullanır.In this case, the invocation creates an instance of the parameter array type with a length corresponding to the number of arguments, initializes the elements of the array instance with the given argument values, and uses the newly created array instance as the actual argument.

Bir çağırmada değişken sayıda bağımsız değişkene izin verilmesi dışında, bir parametre dizisi tam olarak aynı türdeki bir değer parametresine (değer parametreleri) eşdeğerdir.Except for allowing a variable number of arguments in an invocation, a parameter array is precisely equivalent to a value parameter (Value parameters) of the same type.

ÖrnekteThe example

using System;

class Test
{
    static void F(params int[] args) {
        Console.Write("Array contains {0} elements:", args.Length);
        foreach (int i in args) 
            Console.Write(" {0}", i);
        Console.WriteLine();
    }

    static void Main() {
        int[] arr = {1, 2, 3};
        F(arr);
        F(10, 20, 30, 40);
        F();
    }
}

çıktıyı üretirproduces the output

Array contains 3 elements: 1 2 3
Array contains 4 elements: 10 20 30 40
Array contains 0 elements:

İlk çağırma, F diziyi a bir değer parametresi olarak geçirir.The first invocation of F simply passes the array a as a value parameter. İkinci çağırma, F otomatik olarak int[] verilen öğe değerleriyle dört öğe oluşturur ve bu dizi örneğini bir değer parametresi olarak geçirir.The second invocation of F automatically creates a four-element int[] with the given element values and passes that array instance as a value parameter. Benzer şekilde, üçüncü çağırma F bir sıfır öğesi oluşturur int[] ve bu örneği bir değer parametresi olarak geçirir.Likewise, the third invocation of F creates a zero-element int[] and passes that instance as a value parameter. İkinci ve üçüncü etkinleştirmeleri yazma ile tam olarak eşdeğerdir:The second and third invocations are precisely equivalent to writing:

F(new int[] {10, 20, 30, 40});
F(new int[] {});

Aşırı yükleme çözümlemesi gerçekleştirirken, parametre dizisi olan bir yöntem normal biçiminde veya genişletilmiş biçiminde (uygulanabilir işlev üyesi) uygulanabilir.When performing overload resolution, a method with a parameter array may be applicable either in its normal form or in its expanded form (Applicable function member). Bir yöntemin genişletilmiş biçimi yalnızca, metodun normal formu geçerli değilse ve genişletilmiş formla aynı imzaya sahip geçerli bir yöntem aynı türde zaten bildirilmemiş ise kullanılabilir.The expanded form of a method is available only if the normal form of the method is not applicable and only if an applicable method with the same signature as the expanded form is not already declared in the same type.

ÖrnekteThe example

using System;

class Test
{
    static void F(params object[] a) {
        Console.WriteLine("F(object[])");
    }

    static void F() {
        Console.WriteLine("F()");
    }

    static void F(object a0, object a1) {
        Console.WriteLine("F(object,object)");
    }

    static void Main() {
        F();
        F(1);
        F(1, 2);
        F(1, 2, 3);
        F(1, 2, 3, 4);
    }
}

çıktıyı üretirproduces the output

F();
F(object[]);
F(object,object);
F(object[]);
F(object[]);

Örnekte, bir parametre dizisi ile yönteminin mümkün olan genişletilmiş biçimlerinden ikisi, normal yöntemler olarak sınıfında zaten yer alır.In the example, two of the possible expanded forms of the method with a parameter array are already included in the class as regular methods. Bu genişletilmiş formlar bu nedenle aşırı yükleme çözümlemesi gerçekleştirilirken değerlendirilmez ve ilk ve üçüncü yöntem etkinleştirmeleri bu nedenle normal yöntemleri seçer.These expanded forms are therefore not considered when performing overload resolution, and the first and third method invocations thus select the regular methods. Bir sınıf bir parametre dizisi olan bir yöntem bildiriyorsa, genişletilmiş formlardan bazılarını düzenli yöntemler olarak da içermesi yaygın olmayan bir durumdur.When a class declares a method with a parameter array, it is not uncommon to also include some of the expanded forms as regular methods. Bunu yaparak, parametre dizisi olan bir yöntemin genişletilmiş formu çağrıldığında oluşan bir dizi örneğinin ayrılmasını önlemek mümkündür.By doing so it is possible to avoid the allocation of an array instance that occurs when an expanded form of a method with a parameter array is invoked.

Bir parametre dizisinin türü olduğunda object[] , yöntemin normal biçimi ve tek bir parametre için expsona formu arasında olası bir belirsizlik oluşur object .When the type of a parameter array is object[], a potential ambiguity arises between the normal form of the method and the expended form for a single object parameter. Belirsizliğin nedeni, object[] kendisinin örtülü olarak türüne dönüştürülebilir olmasının nedenidir object .The reason for the ambiguity is that an object[] is itself implicitly convertible to type object. Bununla birlikte, belirsizlik bir sorun değildir, ancak gerekirse bir atama eklenebilir.The ambiguity presents no problem, however, since it can be resolved by inserting a cast if needed.

ÖrnekteThe example

using System;

class Test
{
    static void F(params object[] args) {
        foreach (object o in args) {
            Console.Write(o.GetType().FullName);
            Console.Write(" ");
        }
        Console.WriteLine();
    }

    static void Main() {
        object[] a = {1, "Hello", 123.456};
        object o = a;
        F(a);
        F((object)a);
        F(o);
        F((object[])o);
    }
}

çıktıyı üretirproduces the output

System.Int32 System.String System.Double
System.Object[]
System.Object[]
System.Int32 System.String System.Double

' Nin ilk ve son etkinleştirmeleri içinde F , F bağımsız değişken türünden parametre türüne (her ikisi de tür) örtük bir dönüştürme olduğundan, normal biçimi geçerlidir object[] .In the first and last invocations of F, the normal form of F is applicable because an implicit conversion exists from the argument type to the parameter type (both are of type object[]). Bu nedenle, aşırı yükleme çözümlemesi normal biçimini seçer F ve bağımsız değişken normal bir değer parametresi olarak geçirilir.Thus, overload resolution selects the normal form of F, and the argument is passed as a regular value parameter. İkinci ve üçüncü etkinleştirmeleri içinde, F bağımsız değişken türünden parametre türüne örtük dönüştürme olmadığından, normal biçimi Uygulanamaz (tür object örtük olarak türüne dönüştürülemez object[] ).In the second and third invocations, the normal form of F is not applicable because no implicit conversion exists from the argument type to the parameter type (type object cannot be implicitly converted to type object[]). Ancak, genişletilmiş biçimi F geçerlidir, bu nedenle aşırı yükleme çözümlemesi tarafından seçilir.However, the expanded form of F is applicable, so it is selected by overload resolution. Sonuç olarak, bir tek öğe, object[] çağrı tarafından oluşturulur ve dizideki tek öğe, verilen bağımsız değişken değeri (kendisi bir başvurusu olan) ile başlatılır object[] .As a result, a one-element object[] is created by the invocation, and the single element of the array is initialized with the given argument value (which itself is a reference to an object[]).

Statik ve örnek yöntemleriStatic and instance methods

Bir yöntem bildirimi bir değiştirici içerdiğinde static , bu yöntem bir statik yöntem olarak kabul edilir.When a method declaration includes a static modifier, that method is said to be a static method. Değiştirici yoksa static , yöntem bir örnek yöntemi olarak kabul edilir.When no static modifier is present, the method is said to be an instance method.

Statik bir yöntem belirli bir örnek üzerinde çalışmaz ve statik bir yöntemde başvurmak için derleme zamanı hatası olur this .A static method does not operate on a specific instance, and it is a compile-time error to refer to this in a static method.

Bir örnek yöntemi bir sınıfın belirli bir örneği üzerinde çalışır ve bu örneğe this (Bu erişim) olarak erişilebilir.An instance method operates on a given instance of a class, and that instance can be accessed as this (This access).

Bir yönteme, formun bir member_access (üye erişimi) başvurduğu zaman, bir E.M M statik yöntem ise E içeren bir türü belirtmelidir M ve eğer M bir örnek yöntemi ise, içeren bir E türün örneğini belirtmelidir M .When a method is referenced in a member_access (Member access) of the form E.M, if M is a static method, E must denote a type containing M, and if M is an instance method, E must denote an instance of a type containing M.

Statik ve örnek üyeleri arasındaki farklılıklar, statik ve örnek üyelerindedaha ayrıntılı bir şekilde ele alınmıştır.The differences between static and instance members are discussed further in Static and instance members.

Sanal yöntemlerVirtual methods

Bir örnek yöntemi bildirimi bir değiştirici içerdiğinde virtual , bu yöntem sanal bir yöntem olarak kabul edilir.When an instance method declaration includes a virtual modifier, that method is said to be a virtual method. Değiştirici yoksa virtual , yöntemi sanal olmayan bir yöntem olarak kabul edilir.When no virtual modifier is present, the method is said to be a non-virtual method.

Sanal olmayan bir yöntemin uygulanması değişmez: uygulamanın bildirildiği sınıfın bir örneğinde veya türetilmiş bir sınıfın örneği üzerinde çağrılmasından bağımsız olarak, uygulama aynı olur.The implementation of a non-virtual method is invariant: The implementation is the same whether the method is invoked on an instance of the class in which it is declared or an instance of a derived class. Buna karşılık, sanal bir yöntemin uygulanması türetilmiş sınıflar tarafından değiştirilmiş olabilir.In contrast, the implementation of a virtual method can be superseded by derived classes. Devralınan bir sanal yöntemin uygulanmasını yerine geçen işlem, bu yöntemi geçersiz kılma (geçersiz kılma yöntemleri) olarak bilinir.The process of superseding the implementation of an inherited virtual method is known as overriding that method (Override methods).

Bir sanal yöntem çağrısında, çağrının gerçekleştiği örneğin *çalışma zamanı türü _, çağrılacak gerçek Yöntem uygulamasını belirler.In a virtual method invocation, the *run-time type _ of the instance for which that invocation takes place determines the actual method implementation to invoke. Sanal olmayan bir yöntem çağrısında, örneğin _ *derleme zamanı türü**, belirleme faktördür.In a non-virtual method invocation, the _ compile-time type* of the instance is the determining factor. Kesin koşullarda, adlı bir yöntem N A derleme zamanı türü ve bir çalışma zamanı türü olan bir örnek üzerinde bağımsız değişken listesiyle çağrıldığında C (ya da ' R R C den türetilen bir sınıf C ), çağırma aşağıdaki gibi işlenir:In precise terms, when a method named N is invoked with an argument list A on an instance with a compile-time type C and a run-time type R (where R is either C or a class derived from C), the invocation is processed as follows:

  • İlk olarak, C N içinde belirtilen A M ve tarafından devralınan Yöntemler kümesinden belirli bir yöntemi seçmek için C ,, ve ' a yeniden yükleme çözümlemesi uygulanır.First, overload resolution is applied to C, N, and A, to select a specific method M from the set of methods declared in and inherited by C. Bu, Yöntem etkinleştirmeleribölümünde açıklanmaktadır.This is described in Method invocations.
  • Sonra, M sanal olmayan bir yöntem M çağrılırsa çağrılır.Then, if M is a non-virtual method, M is invoked.
  • Aksi takdirde, M sanal bir yöntemdir ve ' ın en iyi türetilmiş uygulamasıyla M R çağrılır.Otherwise, M is a virtual method, and the most derived implementation of M with respect to R is invoked.

Bir sınıf tarafından tanımlanan veya devralan her sanal yöntem için, yönteminin bu sınıfa göre en çok türetilmiş bir uygulamasını vardır.For every virtual method declared in or inherited by a class, there exists a most derived implementation of the method with respect to that class. Bir sınıfa göre bir sanal yöntemin en çok türetilmiş uygulanması M R aşağıdaki şekilde belirlenir:The most derived implementation of a virtual method M with respect to a class R is determined as follows:

  • RGiriş virtual bildirimini içeriyorsa M , bu, ' nin en fazla türetilmiş uygulamasıdır M .If R contains the introducing virtual declaration of M, then this is the most derived implementation of M.
  • Aksi takdirde, ' ı R içeriyorsa override M , en çok türetilen uygulamasıdır M .Otherwise, if R contains an override of M, then this is the most derived implementation of M.
  • Aksi takdirde, ' ın en iyi türetilmiş uygulamasının, M R M doğrudan taban sınıfına göre en çok türetilen uygulamasıyla aynı olması gerekir R .Otherwise, the most derived implementation of M with respect to R is the same as the most derived implementation of M with respect to the direct base class of R.

Aşağıdaki örnek, sanal ve sanal olmayan Yöntemler arasındaki farkları göstermektedir:The following example illustrates the differences between virtual and non-virtual methods:

using System;

class A
{
    public void F() { Console.WriteLine("A.F"); }

    public virtual void G() { Console.WriteLine("A.G"); }
}

class B: A
{
    new public void F() { Console.WriteLine("B.F"); }

    public override void G() { Console.WriteLine("B.G"); }
}

class Test
{
    static void Main() {
        B b = new B();
        A a = b;
        a.F();
        b.F();
        a.G();
        b.G();
    }
}

Örnekte, A sanal olmayan bir yöntemi F ve sanal bir yöntemi tanıtır G .In the example, A introduces a non-virtual method F and a virtual method G. Sınıfı B Yeni bir sanal olmayan yöntem tanıtır F , böylece devralınmış F öğesini gizler ve ayrıca devralınan yöntemi geçersiz kılar G .The class B introduces a new non-virtual method F, thus hiding the inherited F, and also overrides the inherited method G. Örnek, çıktıyı üretir:The example produces the output:

A.F
B.F
B.G
B.G

Deyimin a.G() çağırdığına dikkat edin B.G A.G .Notice that the statement a.G() invokes B.G, not A.G. Bunun nedeni, örneğin derleme zamanı türü (yani) değil, örneğin çalışma zamanı türünün (yani) B A , çağrılacak gerçek Yöntem uygulamasını belirler.This is because the run-time type of the instance (which is B), not the compile-time type of the instance (which is A), determines the actual method implementation to invoke.

Yöntemlerin devralınan yöntemleri gizleyebildiğinden, bir sınıfın aynı imzaya sahip çeşitli sanal yöntemler içermesi mümkündür.Because methods are allowed to hide inherited methods, it is possible for a class to contain several virtual methods with the same signature. Bu, bir belirsizlik sorunu sunmaz, ancak en çok türetilen Yöntem gizlenir.This does not present an ambiguity problem, since all but the most derived method are hidden. ÖrnekteIn the example

using System;

class A
{
    public virtual void F() { Console.WriteLine("A.F"); }
}

class B: A
{
    public override void F() { Console.WriteLine("B.F"); }
}

class C: B
{
    new public virtual void F() { Console.WriteLine("C.F"); }
}

class D: C
{
    public override void F() { Console.WriteLine("D.F"); }
}

class Test
{
    static void Main() {
        D d = new D();
        A a = d;
        B b = d;
        C c = d;
        a.F();
        b.F();
        c.F();
        d.F();
    }
}

Cve D sınıfları aynı imzaya sahip iki sanal yöntem içerir: tarafından tanıtılan diğeri A tarafından tanıtılan C .the C and D classes contain two virtual methods with the same signature: The one introduced by A and the one introduced by C. Tarafından tanıtılan Yöntem C öğesinden devralınan yöntemi gizler A .The method introduced by C hides the method inherited from A. Bu nedenle, içindeki geçersiz kılma bildirimi D tarafından tanıtılan yöntemi geçersiz kılar C ve D tarafından tanıtılan yöntemi geçersiz kılmak mümkün değildir A .Thus, the override declaration in D overrides the method introduced by C, and it is not possible for D to override the method introduced by A. Örnek, çıktıyı üretir:The example produces the output:

B.F
B.F
D.F
D.F

Bir örneğine, D yöntemin gizlenmediği daha az türetilmiş bir tür aracılığıyla erişerek gizli sanal yöntemi çağırmak mümkün olduğunu unutmayın.Note that it is possible to invoke the hidden virtual method by accessing an instance of D through a less derived type in which the method is not hidden.

Geçersiz kılma yöntemleriOverride methods

Bir örnek yöntemi bildirimi bir değiştirici içerdiğinde override , yöntemi bir geçersiz kılma yöntemi olarak kabul edilir.When an instance method declaration includes an override modifier, the method is said to be an override method. Bir geçersiz kılma yöntemi, aynı imzaya sahip devralınmış bir sanal yöntemi geçersiz kılar.An override method overrides an inherited virtual method with the same signature. Sanal bir yöntem bildiriminde yeni bir yöntem tanıtıldığı halde, bir geçersiz kılma yöntemi bildirimi, bu yöntemin yeni bir uygulamasını sağlayarak, var olan bir devralınmış sanal yöntemi uzmanlık eder.Whereas a virtual method declaration introduces a new method, an override method declaration specializes an existing inherited virtual method by providing a new implementation of that method.

Bir bildirim tarafından geçersiz kılınan yöntem override geçersiz kılınan temel yöntem olarak bilinir.The method overridden by an override declaration is known as the overridden base method. Bir sınıfta bildirildiği bir geçersiz kılma yöntemi için M C , geçersiz kılınan temel sınıf türü, öğesinin C doğrudan temel sınıf türünden başlayıp, C her bir ardışık doğrudan temel sınıf türüne göre belirlenir ve bu, belirli bir temel sınıf türüne kadar, bir M bağımsız değişken türü yerine aynı imzaya sahip olan en az bir erişilebilir yöntem bulunur.For an override method M declared in a class C, the overridden base method is determined by examining each base class type of C, starting with the direct base class type of C and continuing with each successive direct base class type, until in a given base class type at least one accessible method is located which has the same signature as M after substitution of type arguments. Geçersiz kılınan temel yöntemi bulma amaçları doğrultusunda, bir yöntem, varsa, varsa, varsa, varsa public protected protected internal veya varsa veya internal aynı programda olarak bildirilirse C , erişilebilir olarak değerlendirilir.For the purposes of locating the overridden base method, a method is considered accessible if it is public, if it is protected, if it is protected internal, or if it is internal and declared in the same program as C.

Bir geçersiz kılma bildirimi için aşağıdakilerin tümü doğru değilse bir derleme zamanı hatası oluşur:A compile-time error occurs unless all of the following are true for an override declaration:

  • Geçersiz kılınan bir temel yöntem yukarıda açıklandığı gibi bulunabilir.An overridden base method can be located as described above.
  • Yalnızca bir tür geçersiz kılınan temel yöntem vardır.There is exactly one such overridden base method. Bu kısıtlama yalnızca temel sınıf türü, tür bağımsız değişkenlerinin yerine geçen iki yöntemin imzasını yaptığı oluşturulmuş bir tür ise etkindir.This restriction has effect only if the base class type is a constructed type where the substitution of type arguments makes the signature of two methods the same.
  • Geçersiz kılınan taban yöntemi bir sanal, Özet veya geçersiz kılma yöntemidir.The overridden base method is a virtual, abstract, or override method. Diğer bir deyişle, geçersiz kılınan taban yöntemi statik veya sanal olmayan olamaz.In other words, the overridden base method cannot be static or non-virtual.
  • Geçersiz kılınan taban yöntemi Sealed bir yöntem değil.The overridden base method is not a sealed method.
  • Override yöntemi ve geçersiz kılınan taban yöntemi aynı dönüş türüne sahip.The override method and the overridden base method have the same return type.
  • Geçersiz kılma bildirimi ve geçersiz kılınan taban yöntemi, aynı tanımlanmış erişilebilirliğe sahiptir.The override declaration and the overridden base method have the same declared accessibility. Diğer bir deyişle, geçersiz kılma bildirimi sanal yöntemin erişilebilirliğini değiştiremezler.In other words, an override declaration cannot change the accessibility of the virtual method. Ancak, geçersiz kılınan temel yöntem, iç, geçersiz kılma yöntemini içeren derlemeden farklı bir derlemede bildirilirse, geçersiz kılma yönteminin tanımlanmış erişilebilirlik korunması gerekir.However, if the overridden base method is protected internal and it is declared in a different assembly than the assembly containing the override method then the override method's declared accessibility must be protected.
  • Geçersiz kılma bildirimi tür-parametresi-kısıtlamalar-tümceleri belirtmiyor.The override declaration does not specify type-parameter-constraints-clauses. Bunun yerine, kısıtlamalar geçersiz kılınan temel yöntemden devralınır.Instead the constraints are inherited from the overridden base method. Geçersiz kılınan yöntemde tür parametreleri olan kısıtlamaların devralınan kısıtlamadaki tür bağımsız değişkenleriyle değiştirilmesini unutmayın.Note that constraints that are type parameters in the overridden method may be replaced by type arguments in the inherited constraint. Bu, değer türleri veya korumalı türler gibi açıkça belirtildiğinde yasal olmayan kısıtlamalara yol açabilir.This can lead to constraints that are not legal when explicitly specified, such as value types or sealed types.

Aşağıdaki örnek, geçersiz kılma kurallarının genel sınıflar için nasıl çalıştığını göstermektedir:The following example demonstrates how the overriding rules work for generic classes:

abstract class C<T>
{
    public virtual T F() {...}
    public virtual C<T> G() {...}
    public virtual void H(C<T> x) {...}
}

class D: C<string>
{
    public override string F() {...}            // Ok
    public override C<string> G() {...}         // Ok
    public override void H(C<T> x) {...}        // Error, should be C<string>
}

class E<T,U>: C<U>
{
    public override U F() {...}                 // Ok
    public override C<U> G() {...}              // Ok
    public override void H(C<T> x) {...}        // Error, should be C<U>
}

Geçersiz kılma bildirimi, geçersiz kılınan temel yönteme base_access (taban erişimi) ile erişebilir.An override declaration can access the overridden base method using a base_access (Base access). ÖrnekteIn the example

class A
{
    int x;

    public virtual void PrintFields() {
        Console.WriteLine("x = {0}", x);
    }
}

class B: A
{
    int y;

    public override void PrintFields() {
        base.PrintFields();
        Console.WriteLine("y = {0}", y);
    }
}

base.PrintFields()' deki çağırma, B PrintFields içinde belirtilen metodu çağırır A .the base.PrintFields() invocation in B invokes the PrintFields method declared in A. Base_access sanal çağırma mekanizmasını devre dışı bırakır ve temel yöntemi sanal olmayan bir yöntem olarak değerlendirir.A base_access disables the virtual invocation mechanism and simply treats the base method as a non-virtual method. Yapılan çağrının B yazıldığı, ' ın ((A)this).PrintFields() PrintFields B A PrintFields sanal ve çalışma zamanı türü ((A)this) olduğu B için ' de bildirildiği yöntemi özyinelemeli olarak çağırır.Had the invocation in B been written ((A)this).PrintFields(), it would recursively invoke the PrintFields method declared in B, not the one declared in A, since PrintFields is virtual and the run-time type of ((A)this) is B.

Yalnızca bir değiştirici ekleyerek bir override Yöntem başka bir yöntemi geçersiz kılar.Only by including an override modifier can a method override another method. Diğer tüm durumlarda, devralınan bir yöntemle aynı imzaya sahip bir yöntem devralınan yöntemi gizler.In all other cases, a method with the same signature as an inherited method simply hides the inherited method. ÖrnekteIn the example

class A
{
    public virtual void F() {}
}

class B: A
{
    public virtual void F() {}        // Warning, hiding inherited F()
}

Fiçindeki yöntemi B bir override değiştirici içermez ve bu nedenle F içindeki yöntemi geçersiz kılmaz A .the F method in B does not include an override modifier and therefore does not override the F method in A. Bunun yerine, F içindeki yöntemi B içindeki yöntemi gizler A ve bildirim bir değiştirici içermediğinden bir uyarı bildirilir new .Rather, the F method in B hides the method in A, and a warning is reported because the declaration does not include a new modifier.

ÖrnekteIn the example

class A
{
    public virtual void F() {}
}

class B: A
{
    new private void F() {}        // Hides A.F within body of B
}

class C: B
{
    public override void F() {}    // Ok, overrides A.F
}

Fiçindeki yöntemi B F öğesinden devralınan sanal yöntemi gizler A .the F method in B hides the virtual F method inherited from A. İçindeki yeni öğesinin F B özel erişimi olduğundan, kapsamı yalnızca ' ın sınıf gövdesini içerir B ve genişletilmez C .Since the new F in B has private access, its scope only includes the class body of B and does not extend to C. Bu nedenle, içindeki bildiriminin F C devralınan öğesinden geçersiz kılınmasına izin verilir F A .Therefore, the declaration of F in C is permitted to override the F inherited from A.

Sealed yöntemleriSealed methods

Bir örnek yöntemi bildirimi bir değiştirici içerdiğinde sealed , bu yöntem Sealed bir yöntem olarak kabul edilir.When an instance method declaration includes a sealed modifier, that method is said to be a sealed method. Bir örnek yöntemi bildirimi sealed değiştiricisini içeriyorsa, override değiştiriciyi de içermelidir.If an instance method declaration includes the sealed modifier, it must also include the override modifier. sealedDeğiştirici kullanımı, türetilmiş bir sınıfın yöntemi daha fazla geçersiz kılmasını önler.Use of the sealed modifier prevents a derived class from further overriding the method.

ÖrnekteIn the example

using System;

class A
{
    public virtual void F() {
        Console.WriteLine("A.F");
    }

    public virtual void G() {
        Console.WriteLine("A.G");
    }
}

class B: A
{
    sealed override public void F() {
        Console.WriteLine("B.F");
    } 

    override public void G() {
        Console.WriteLine("B.G");
    } 
}

class C: B
{
    override public void G() {
        Console.WriteLine("C.G");
    } 
}

sınıfı B iki geçersiz kılma yöntemi sağlar: F sealed değiştiriciye sahip olan ve olmayan bir yöntem G .the class B provides two override methods: an F method that has the sealed modifier and a G method that does not. BSealed kullanımı, modifier C daha fazla geçersiz kılmayı önler F .B's use of the sealed modifier prevents C from further overriding F.

Soyut yöntemlerAbstract methods

Bir örnek yöntemi bildirimi bir değiştirici içerdiğinde abstract , bu yöntem soyut bir yöntem olarak kabul edilir.When an instance method declaration includes an abstract modifier, that method is said to be an abstract method. Soyut bir yöntem örtülü olarak bir sanal yöntem olsa da, değiştiriciye sahip olamaz virtual .Although an abstract method is implicitly also a virtual method, it cannot have the modifier virtual.

Soyut yöntem bildirimi yeni bir sanal yöntem tanıtır, ancak bu yöntemin bir uygulamasını sağlamaz.An abstract method declaration introduces a new virtual method but does not provide an implementation of that method. Bunun yerine, soyut olmayan türetilmiş sınıfların bu yöntemi geçersiz kılarak kendi uygulamasını sağlaması gerekir.Instead, non-abstract derived classes are required to provide their own implementation by overriding that method. Soyut bir yöntem gerçek uygulama sunmadığından, soyut bir yöntemin method_body noktalı virgülden oluşur.Because an abstract method provides no actual implementation, the method_body of an abstract method simply consists of a semicolon.

Soyut yöntem bildirimlerine yalnızca soyut sınıflarda izin verilir (soyut sınıflar).Abstract method declarations are only permitted in abstract classes (Abstract classes).

ÖrnekteIn the example

public abstract class Shape
{
    public abstract void Paint(Graphics g, Rectangle r);
}

public class Ellipse: Shape
{
    public override void Paint(Graphics g, Rectangle r) {
        g.DrawEllipse(r);
    }
}

public class Box: Shape
{
    public override void Paint(Graphics g, Rectangle r) {
        g.DrawRect(r);
    }
}

Shapesınıfı, kendisini boyayacak bir geometrik şekil nesnesinin soyut kavramını tanımlar.the Shape class defines the abstract notion of a geometrical shape object that can paint itself. PaintAnlamlı bir varsayılan uygulama olmadığından Yöntem soyuttur.The Paint method is abstract because there is no meaningful default implementation. EllipseVe Box sınıfları somut Shape uygulamalardır.The Ellipse and Box classes are concrete Shape implementations. Bu sınıflar soyut olmadığından, yöntemi geçersiz kılmaları Paint ve gerçek bir uygulama sağlaması gerekir.Because these classes are non-abstract, they are required to override the Paint method and provide an actual implementation.

Bir soyut metoda başvurmak için bir base_access (taban erişimi) için derleme zamanı hatası.It is a compile-time error for a base_access (Base access) to reference an abstract method. ÖrnekteIn the example

abstract class A
{
    public abstract void F();
}

class B: A
{
    public override void F() {
        base.F();                        // Error, base.F is abstract
    }
}

bir soyut metoda başvurduğundan, çağrı için derleme zamanı hatası bildirilir base.F() .a compile-time error is reported for the base.F() invocation because it references an abstract method.

Bir soyut Yöntem bildiriminin sanal bir yöntemi geçersiz kılmasına izin verilir.An abstract method declaration is permitted to override a virtual method. Bu, bir soyut sınıfın türetilmiş sınıflarda yöntemin yeniden uygulanmasını zormasına olanak tanır ve yöntemin orijinal uygulamasını kullanılamaz hale getirir.This allows an abstract class to force re-implementation of the method in derived classes, and makes the original implementation of the method unavailable. ÖrnekteIn the example

using System;

class A
{
    public virtual void F() {
        Console.WriteLine("A.F");
    }
}

abstract class B: A
{
    public abstract override void F();
}

class C: B
{
    public override void F() {
        Console.WriteLine("C.F");
    }
}

sınıf A bir sanal yöntem bildirir, sınıf B Bu yöntemi soyut bir yöntemle geçersiz kılar ve sınıf C kendi uygulamasını sağlamak için soyut yöntemi geçersiz kılar.class A declares a virtual method, class B overrides this method with an abstract method, and class C overrides the abstract method to provide its own implementation.

Dış YöntemlerExternal methods

Bir yöntem bildirimi bir değiştirici içerdiğinde extern , bu yöntem bir *dış yöntem _ olarak kabul edilir.When a method declaration includes an extern modifier, that method is said to be an *external method _. Dış Yöntemler, genellikle C# dışında bir dil kullanılarak harici olarak uygulanır.External methods are implemented externally, typically using a language other than C#. Bir dış yöntem bildirimi gerçek uygulama sunmadığından, bir dış yöntemin _method_body * noktalı virgül oluşur.Because an external method declaration provides no actual implementation, the _method_body* of an external method simply consists of a semicolon. Dış yöntem genel olmayabilir.An external method may not be generic.

externDeğiştirici genellikle bir DllImport ÖZNITELIK (com ve Win32 bileşenleriyle birlikte çalışabilirlik) ile birlikte kullanıldığında, dış yöntemlerin dll 'ler tarafından uygulanmasına Izin verir (dinamik bağlantı kitaplıkları).The extern modifier is typically used in conjunction with a DllImport attribute (Interoperation with COM and Win32 components), allowing external methods to be implemented by DLLs (Dynamic Link Libraries). Yürütme ortamı, dış yöntemlerin uygulamalarının sağlanabildiği diğer mekanizmaları destekleyebilir.The execution environment may support other mechanisms whereby implementations of external methods can be provided.

Bir dış yöntem bir öznitelik içerdiğinde DllImport , yöntem bildirimi de bir static değiştirici içermelidir.When an external method includes a DllImport attribute, the method declaration must also include a static modifier. Bu örnek, extern değiştiricinin ve özniteliğin kullanımını gösterir DllImport :This example demonstrates the use of the extern modifier and the DllImport attribute:

using System.Text;
using System.Security.Permissions;
using System.Runtime.InteropServices;

class Path
{
    [DllImport("kernel32", SetLastError=true)]
    static extern bool CreateDirectory(string name, SecurityAttribute sa);

    [DllImport("kernel32", SetLastError=true)]
    static extern bool RemoveDirectory(string name);

    [DllImport("kernel32", SetLastError=true)]
    static extern int GetCurrentDirectory(int bufSize, StringBuilder buf);

    [DllImport("kernel32", SetLastError=true)]
    static extern bool SetCurrentDirectory(string name);
}

Kısmi Yöntemler (Recap)Partial methods (recap)

Bir yöntem bildirimi bir değiştirici içerdiğinde partial , bu yöntem kısmi bir yöntem olarak kabul edilir.When a method declaration includes a partial modifier, that method is said to be a partial method. Kısmi yöntemler yalnızca kısmi türlerin (kısmi türlerin) üyeleri olarak bildirilebilecek ve bir dizi kısıtlamayla tabidir.Partial methods can only be declared as members of partial types (Partial types), and are subject to a number of restrictions. Kısmi Yöntemler, kısmi yöntemlerdedaha ayrıntılı olarak açıklanmıştır.Partial methods are further described in Partial methods.

Genişletme yöntemleriExtension methods

Bir yöntemin ilk parametresi this değiştirici içerdiğinde, bu yöntem bir genişletme yöntemi olarak kabul edilir.When the first parameter of a method includes the this modifier, that method is said to be an extension method. Uzantı yöntemleri yalnızca genel olmayan, iç içe olmayan statik sınıflarda bildirilemez.Extension methods can only be declared in non-generic, non-nested static classes. Bir genişletme yönteminin ilk parametresi dışında bir değiştirici içeremez this ve parametre türü bir işaretçi türü olamaz.The first parameter of an extension method can have no modifiers other than this, and the parameter type cannot be a pointer type.

Aşağıda iki uzantı yöntemi bildiren bir statik sınıfa bir örnek verilmiştir:The following is an example of a static class that declares two extension methods:

public static class Extensions
{
    public static int ToInt32(this string s) {
        return Int32.Parse(s);
    }

    public static T[] Slice<T>(this T[] source, int index, int count) {
        if (index < 0 || count < 0 || source.Length - index < count)
            throw new ArgumentException();
        T[] result = new T[count];
        Array.Copy(source, index, result, 0, count);
        return result;
    }
}

Uzantı yöntemi, normal bir statik yöntemdir.An extension method is a regular static method. Ayrıca, kapsayan statik sınıfının kapsam içinde olduğu yerlerde, ilk bağımsız değişken olarak alıcı ifadesi kullanılarak örnek yöntemi çağırma sözdizimi (genişletme yöntemi etkinleştirmeleri) kullanılarak bir genişletme yöntemi çağrılabilir.In addition, where its enclosing static class is in scope, an extension method can be invoked using instance method invocation syntax (Extension method invocations), using the receiver expression as the first argument.

Aşağıdaki program, yukarıda belirtilen uzantı yöntemlerini kullanır:The following program uses the extension methods declared above:

static class Program
{
    static void Main() {
        string[] strings = { "1", "22", "333", "4444" };
        foreach (string s in strings.Slice(1, 2)) {
            Console.WriteLine(s.ToInt32());
        }
    }
}

SliceYöntemi ' de kullanılabilir string[] ve ToInt32 yöntemi string Uzantı yöntemleri olarak bildirildiği için üzerinde kullanılabilir.The Slice method is available on the string[], and the ToInt32 method is available on string, because they have been declared as extension methods. Programın anlamı, sıradan statik yöntem çağrıları kullanılarak aşağıdakiler ile aynıdır:The meaning of the program is the same as the following, using ordinary static method calls:

static class Program
{
    static void Main() {
        string[] strings = { "1", "22", "333", "4444" };
        foreach (string s in Extensions.Slice(strings, 1, 2)) {
            Console.WriteLine(Extensions.ToInt32(s));
        }
    }
}

Yöntem gövdesiMethod body

Yöntem bildiriminin method_body bir blok gövdesinden, bir ifade gövdesinden veya noktalı virgülden oluşur.The method_body of a method declaration consists of either a block body, an expression body or a semicolon.

Bir yöntemin sonuç türü , void dönüş türü ise void veya yöntemin zaman uyumsuz olması ve dönüş türünün olması durumunda olur System.Threading.Tasks.Task .The result type of a method is void if the return type is void, or if the method is async and the return type is System.Threading.Tasks.Task. Aksi takdirde, zaman uyumsuz bir yöntemin sonuç türü dönüş türüdür ve dönüş türü ile zaman uyumsuz bir metodun sonuç türü System.Threading.Tasks.Task<T> olur T .Otherwise, the result type of a non-async method is its return type, and the result type of an async method with return type System.Threading.Tasks.Task<T> is T.

Bir yöntemin void sonuç türü ve bir blok gövdesi olduğunda, return bloktaki deyimlerin (return deyimi) bir ifade belirtmelerine izin verilmez.When a method has a void result type and a block body, return statements (The return statement) in the block are not permitted to specify an expression. Void yönteminin bloğunun yürütülmesi normal şekilde tamamlanırsa (diğer bir deyişle, bu yöntem, Yöntem gövdesinin sonundaki şekilde akar), bu yöntem yalnızca geçerli çağıranına döner.If execution of the block of a void method completes normally (that is, control flows off the end of the method body), that method simply returns to its current caller.

Bir yöntemin void sonucu ve bir ifade gövdesi olduğunda, ifade E bir statement_expression olmalıdır ve gövde, formun bir blok gövdesine tam olarak eşdeğerdir { E; } .When a method has a void result and an expression body, the expression E must be a statement_expression, and the body is exactly equivalent to a block body of the form { E; }.

Bir yöntemde void olmayan bir sonuç türü ve bir blok gövdesi olduğunda, return bloktaki her deyim, sonuç türüne örtük olarak dönüştürülebilir bir ifade belirtmelidir.When a method has a non-void result type and a block body, each return statement in the block must specify an expression that is implicitly convertible to the result type. Değer döndüren metodun blok gövdesinin uç noktasına ulaşılamıyor olmalıdır.The endpoint of a block body of a value-returning method must not be reachable. Diğer bir deyişle, blok gövdesi olan bir değer döndüren yöntemde, denetimin Yöntem gövdesinin sonunu akışa girmesine izin verilmez.In other words, in a value-returning method with a block body, control is not permitted to flow off the end of the method body.

Bir yöntemde void olmayan bir sonuç türü ve bir ifade gövdesi olduğunda, ifadenin sonuç türüne örtülü olarak dönüştürülebilir olması gerekir ve gövde, formun bir blok gövdesine tam olarak eşdeğerdir { return E; } .When a method has a non-void result type and an expression body, the expression must be implicitly convertible to the result type, and the body is exactly equivalent to a block body of the form { return E; }.

ÖrnekteIn the example

class A
{
    public int F() {}            // Error, return value required

    public int G() {
        return 1;
    }

    public int H(bool b) {
        if (b) {
            return 1;
        }
        else {
            return 0;
        }
    }

    public int I(bool b) => b ? 1 : 0;
}

değer döndüren yöntem, F Denetim Yöntem gövdesinin sonuna akabileceğinden, derleme zamanı hatası ile sonuçlanır.the value-returning F method results in a compile-time error because control can flow off the end of the method body. GVe H yöntemleri, olası tüm yürütme yolları bir dönüş değeri belirten bir return ifadesinde sona uğradığından doğrudur.The G and H methods are correct because all possible execution paths end in a return statement that specifies a return value. IYöntemi doğrudur, çünkü gövdesi yalnızca tek bir dönüş ifadesiyle bir ifade bloğuna denk gelir.The I method is correct, because its body is equivalent to a statement block with just a single return statement in it.

Yöntem aşırı yüklemesiMethod overloading

Yöntem aşırı yükleme çözümleme kuralları tür çıkarımıbölümünde açıklanmaktadır.The method overload resolution rules are described in Type inference.

ÖzelliklerProperties

*Özelliği _, bir nesnenin veya sınıfın özelliklerine erişim sağlayan bir üyesidir.A *property _ is a member that provides access to a characteristic of an object or a class. Özellik örnekleri, bir dizenin uzunluğunu, bir yazı tipinin boyutunu, bir pencerenin başlığını, bir müşterinin adını vb. içerir.Examples of properties include the length of a string, the size of a font, the caption of a window, the name of a customer, and so on. Özellikler, alanlar için doğal bir uzantıdır. her ikisi de ilişkili türleri olan üyeler adlandırılmış ve alanlara ve özelliklere erişim için sözdizimi aynıdır.Properties are a natural extension of fields—both are named members with associated types, and the syntax for accessing fields and properties is the same. Ancak, alanların aksine, Özellikler depolama konumlarını göstermiyor.However, unlike fields, properties do not denote storage locations. Bunun yerine, özelliklerde, değerleri okunmadığında veya yazıldığında yürütülecek deyimleri belirten _ erişimcileri* vardır.Instead, properties have _ accessors* that specify the statements to be executed when their values are read or written. Bu sayede, eylemleri bir nesne özniteliklerinin okuma ve yazma ile ilişkilendirmek için bir mekanizma sağlar; Ayrıca, bu tür özniteliklere de hesaplanmasına izin verir.Properties thus provide a mechanism for associating actions with the reading and writing of an object's attributes; furthermore, they permit such attributes to be computed.

Özellikler property_declaration s kullanılarak bildirilmiştir:Properties are declared using property_declaration s:

property_declaration
    : attributes? property_modifier* type member_name property_body
    ;

property_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'static'
    | 'virtual'
    | 'sealed'
    | 'override'
    | 'abstract'
    | 'extern'
    | property_modifier_unsafe
    ;

property_body
    : '{' accessor_declarations '}' property_initializer?
    | '=>' expression ';'
    ;

property_initializer
    : '=' variable_initializer ';'
    ;

Bir property_declaration bir öznitelikler kümesi (öznitelikler) ve dört erişim değiştiricisinin (erişim değiştiricileri), ( new Yeni değiştirici), static (statik ve örnek yöntemleri), ( virtual sanal yöntemler), ( override geçersiz kılma yöntemleri), (korumalı Yöntemler), (soyut yöntemler sealed ) abstract ve extern (dış Yöntemler) değiştiricilerin geçerli bir bileşimini içerebilir.A property_declaration may include a set of attributes (Attributes) and a valid combination of the four access modifiers (Access modifiers), the new (The new modifier), static (Static and instance methods), virtual (Virtual methods), override (Override methods), sealed (Sealed methods), abstract (Abstract methods), and extern (External methods) modifiers.

Özellik bildirimleri, geçerli değiştiriciler birleşimleriyle ilgili olarak yöntem bildirimleri (Yöntemler) ile aynı kurallara tabidir.Property declarations are subject to the same rules as method declarations (Methods) with regard to valid combinations of modifiers.

Bir özellik bildiriminin türü , bildirim tarafından tanıtılan özelliğin türünü belirtir ve MEMBER_NAME özelliğin adını belirtir.The type of a property declaration specifies the type of the property introduced by the declaration, and the member_name specifies the name of the property. Özellik açık bir arabirim üyesi uygulama değilse, MEMBER_NAME yalnızca bir tanıtıcıdır.Unless the property is an explicit interface member implementation, the member_name is simply an identifier. Açık arabirim üye uygulaması (Açık arabirim üye uygulamaları) için member_name , bir interface_type ve ardından bir . tanımlayıcı ile oluşur.For an explicit interface member implementation (Explicit interface member implementations), the member_name consists of an interface_type followed by a "." and an identifier.

Özelliğin türü en az özelliğin kendisi (Erişilebilirlik kısıtlamaları) olarak erişilebilir olmalıdır.The type of a property must be at least as accessible as the property itself (Accessibility constraints).

Bir property_body bir erişimci gövdesinden veya bir _ifade gövdesinden*_ oluşabilir.A property_body may either consist of an accessor body _ or an _expression body*_. Bir erişimci gövdesinde, " { " ve "" belirteçlerinin içine alınması gereken _accessor_declarations *, } özelliğin erişimcileri (erişimcileri) bildirmek.In an accessor body, _accessor_declarations*, which must be enclosed in "{" and "}" tokens, declare the accessors (Accessors) of the property. Erişimciler, özelliği okuma ve yazma ile ilişkili yürütülebilir deyimleri belirler.The accessors specify the executable statements associated with reading and writing the property.

=>Arkasından bir ifade ve bir noktalı virgül gelen bir ifade gövdesi, E deyim gövdesine tam olarak eşdeğerdir { get { return E; } } ve bu nedenle yalnızca alıcı sonucunun tek bir ifade tarafından verildiği yerde yalnızca alıcı özelliklerini belirtmek için kullanılabilir.An expression body consisting of => followed by an expression E and a semicolon is exactly equivalent to the statement body { get { return E; } }, and can therefore only be used to specify getter-only properties where the result of the getter is given by a single expression.

Bir property_initializer yalnızca otomatik olarak uygulanan bir Özellik (otomatik olarak uygulanan özellikler) için verilebilir ve bu tür özelliklerin temel alan, ifade tarafından verilen değerle başlatılmasına neden olur.A property_initializer may only be given for an automatically implemented property (Automatically implemented properties), and causes the initialization of the underlying field of such properties with the value given by the expression.

Bir özelliğe erişim sözdizimi, bir alanla ilgili olarak aynı olsa da, bir özellik değişken olarak sınıflandırılmıyor.Even though the syntax for accessing a property is the same as that for a field, a property is not classified as a variable. Bu nedenle, bir özelliği ref veya bağımsız değişken olarak geçirmek mümkün değildir out .Thus, it is not possible to pass a property as a ref or out argument.

Bir özellik bildirimi bir değiştirici içerdiğinde extern , özelliği bir *External özelliği olarak kabul edilir.When a property declaration includes an extern modifier, the property is said to be an *external property _. Dış özellik bildirimi gerçek uygulama sağladığından, her bir _accessor_declarations * noktalı virgül oluşur.Because an external property declaration provides no actual implementation, each of its _accessor_declarations* consists of a semicolon.

Statik ve örnek özellikleriStatic and instance properties

Bir özellik bildirimi bir değiştirici içerdiğinde static , özelliği *static özelliği olan _ olarak kabul edilir.When a property declaration includes a static modifier, the property is said to be a *static property _. Değiştirici yoksa static , özelliği _ örnek özelliği * olarak kabul edilir.When no static modifier is present, the property is said to be an _*instance property**.

Statik bir özellik belirli bir örnekle ilişkili değildir ve this statik bir özelliğin erişimcilerine başvuracak derleme zamanı hatasıdır.A static property is not associated with a specific instance, and it is a compile-time error to refer to this in the accessors of a static property.

Örnek özelliği, bir sınıfın belirli bir örneğiyle ilişkilendirilir ve bu örneğe bu this özelliğin erişimcilerinde (Bu erişim) erişilebilir.An instance property is associated with a given instance of a class, and that instance can be accessed as this (This access) in the accessors of that property.

Bir özellik, formun bir member_access (üye erişimi) içinde başvuruluyorsa, bir E.M M statik özelliktir, E içeren bir türü belirtmelidir M ve eğer M bir örnek özelliği ise, içeren bir türün örneğini belirtmelidir M .When a property is referenced in a member_access (Member access) of the form E.M, if M is a static property, E must denote a type containing M, and if M is an instance property, E must denote an instance of a type containing M.

Statik ve örnek üyeleri arasındaki farklılıklar, statik ve örnek üyelerindedaha ayrıntılı bir şekilde ele alınmıştır.The differences between static and instance members are discussed further in Static and instance members.

CAccessors

Bir özelliğin accessor_declarations , bu özelliği okuma ve yazma ile ilişkili çalıştırılabilir deyimleri belirtir.The accessor_declarations of a property specify the executable statements associated with reading and writing that property.

accessor_declarations
    : get_accessor_declaration set_accessor_declaration?
    | set_accessor_declaration get_accessor_declaration?
    ;

get_accessor_declaration
    : attributes? accessor_modifier? 'get' accessor_body
    ;

set_accessor_declaration
    : attributes? accessor_modifier? 'set' accessor_body
    ;

accessor_modifier
    : 'protected'
    | 'internal'
    | 'private'
    | 'protected' 'internal'
    | 'internal' 'protected'
    ;

accessor_body
    : block
    | ';'
    ;

Erişimci bildirimleri get_accessor_declaration, set_accessor_declaration veya her ikisinden oluşur.The accessor declarations consist of a get_accessor_declaration, a set_accessor_declaration, or both. Her erişimci bildirimi belirtecinden oluşur veya sonra get set isteğe bağlı bir accessor_modifier ve accessor_body gelir.Each accessor declaration consists of the token get or set followed by an optional accessor_modifier and an accessor_body.

Accessor_modifier s kullanımı aşağıdaki kısıtlamalara tabidir:The use of accessor_modifier s is governed by the following restrictions:

  • Bir accessor_modifier , bir arabirimde veya açık arabirim üyesi uygulamasında kullanılamaz.An accessor_modifier may not be used in an interface or in an explicit interface member implementation.
  • Değiştirici içermeyen bir özellik veya Dizin Oluşturucu için override , yalnızca özellik veya dizin oluşturucunun hem hem de get erişimcisi varsa set ve bu erişimcilerle yalnızca biri için izin verildiğinde bir accessor_modifier izin verilir.For a property or indexer that has no override modifier, an accessor_modifier is permitted only if the property or indexer has both a get and set accessor, and then is permitted only on one of those accessors.
  • Değiştirici içeren bir özellik veya Dizin Oluşturucu için, erişimci override geçersiz kılınmakta olan erişimcinin accessor_modifier eşleşmesi gerekir.For a property or indexer that includes an override modifier, an accessor must match the accessor_modifier, if any, of the accessor being overridden.
  • Accessor_modifier , özelliğin veya dizin oluşturucunun kendisi tarafından belirtilen erişilebilirliğine göre kesinlikle daha kısıtlayıcı bir erişilebilirlik bildirmelidir.The accessor_modifier must declare an accessibility that is strictly more restrictive than the declared accessibility of the property or indexer itself. Kesin olması için:To be precise:
    • Özelliğin veya dizin oluşturucunun tanımlanmış bir erişilebilirliği varsa public accessor_modifier protected internal ,, veya olabilir internal protected private .If the property or indexer has a declared accessibility of public, the accessor_modifier may be either protected internal, internal, protected, or private.
    • Özelliğin veya dizin oluşturucunun tanımlanmış bir erişilebilirliği varsa protected internal accessor_modifier internal , ya da olabilir protected private .If the property or indexer has a declared accessibility of protected internal, the accessor_modifier may be either internal, protected, or private.
    • Özellik veya dizin oluşturucunun veya ' nin tanımlanmış bir erişilebilirliği internal varsa protected accessor_modifier olmalıdır private .If the property or indexer has a declared accessibility of internal or protected, the accessor_modifier must be private.
    • Özelliğin veya dizin oluşturucunun tanımlanmış bir erişilebilirliği varsa private , hiçbir accessor_modifier kullanılabilir.If the property or indexer has a declared accessibility of private, no accessor_modifier may be used.

abstractVe extern özellikleri için, belirtilen her erişimci için accessor_body yalnızca noktalı virgül olur.For abstract and extern properties, the accessor_body for each accessor specified is simply a semicolon. Soyut olmayan, extern olmayan bir özelliğin her bir accessor_body noktalı virgül olması olabilir. Bu durumda, *otomatik olarak uygulanan bir özellik _ (otomatik olarak uygulanan özellikler) olur.A non-abstract, non-extern property may have each accessor_body be a semicolon, in which case it is an *automatically implemented property _ (Automatically implemented properties). Otomatik olarak uygulanan özelliğin en az bir get erişimcisi olmalıdır.An automatically implemented property must have at least a get accessor. Diğer soyut olmayan, extern olmayan özelliğin erişimcileri için _accessor_body *, karşılık gelen erişimci çağrıldığında yürütülecek deyimleri belirten bir bloğudur .For the accessors of any other non-abstract, non-extern property, the _accessor_body* is a block which specifies the statements to be executed when the corresponding accessor is invoked.

getErişimci, özellik türünün dönüş değeri olan parametresiz bir yönteme karşılık gelir.A get accessor corresponds to a parameterless method with a return value of the property type. Atama hedefi dışında, bir ifadede bir özelliğe başvurulduğunda, özelliğin get erişimcisi özelliğin değerini hesaplamak için çağrılır (ifadelerin değerleri).Except as the target of an assignment, when a property is referenced in an expression, the get accessor of the property is invoked to compute the value of the property (Values of expressions). Bir get erişimcinin gövdesi, Yöntem gövdesindeaçıklanan değer döndüren yöntemlere yönelik kurallara uymalıdır.The body of a get accessor must conform to the rules for value-returning methods described in Method body. Özellikle, return bir erişimcinin gövdesindeki tüm deyimler, get özellik türüne örtük olarak dönüştürülebilir bir ifade belirtmelidir.In particular, all return statements in the body of a get accessor must specify an expression that is implicitly convertible to the property type. Ayrıca, erişimcinin uç noktasına get ulaşılamamalıdır.Furthermore, the endpoint of a get accessor must not be reachable.

setErişimci, özellik türü ve dönüş türü tek bir değer parametresine sahip bir yönteme karşılık gelir void .A set accessor corresponds to a method with a single value parameter of the property type and a void return type. setErişimcinin örtük parametresi her zaman adlandırılır value .The implicit parameter of a set accessor is always named value. Bir özelliğe bir atamanın hedefi (atama işleçleri) veya ++ ya da -- (sonek artırma ve azaltma işleçleri, önek artırma ve azaltma işleçleri) olarak başvurulduğunda, set erişimci bir bağımsız değişkenle çağrılır (değeri, atamanın sağ tarafındaki veya ++ veya işlecinin işleneni olan -- ) yeni değeri (basit atama) sağlar.When a property is referenced as the target of an assignment (Assignment operators), or as the operand of ++ or -- (Postfix increment and decrement operators, Prefix increment and decrement operators), the set accessor is invoked with an argument (whose value is that of the right-hand side of the assignment or the operand of the ++ or -- operator) that provides the new value (Simple assignment). Bir set erişimcinin gövdesi, void Yöntem gövdesindeaçıklanan yöntemler için kurallara uymalıdır.The body of a set accessor must conform to the rules for void methods described in Method body. Özellikle, return set erişimci gövdesindeki deyimlerin bir ifade belirtmelerine izin verilmez.In particular, return statements in the set accessor body are not permitted to specify an expression. setErişimci örtük olarak adlı bir parametreye sahip olduğundan value , bu adı bir yerel değişken veya bir set erişimcinin sabit bildiriminin bu ada sahip olması için derleme zamanı hatası olur.Since a set accessor implicitly has a parameter named value, it is a compile-time error for a local variable or constant declaration in a set accessor to have that name.

Ve erişimcilerinin varlığına veya yokluğuna get göre set , bir özellik şu şekilde sınıflandırılır:Based on the presence or absence of the get and set accessors, a property is classified as follows:

  • Hem erişimci hem de erişimci içeren bir özellik get set , okuma-yazma özelliği olarak kabul edilir.A property that includes both a get accessor and a set accessor is said to be a read-write property.
  • Yalnızca bir erişimcisi olan bir özellik get salt okunurdur özelliği olarak kabul edilir.A property that has only a get accessor is said to be a read-only property. Bir salt okuma özelliğinin bir atamanın hedefi olması için derleme zamanı hatası.It is a compile-time error for a read-only property to be the target of an assignment.
  • Yalnızca bir erişimcisi olan bir özellik set salt yazılır bir özellik olarak kabul edilir.A property that has only a set accessor is said to be a write-only property. Atama hedefi dışında, bir ifadede salt yazılır bir özelliğe başvurmak için derleme zamanı hatası olur.Except as the target of an assignment, it is a compile-time error to reference a write-only property in an expression.

ÖrnekteIn the example

public class Button: Control
{
    private string caption;

    public string Caption {
        get {
            return caption;
        }
        set {
            if (caption != value) {
                caption = value;
                Repaint();
            }
        }
    }

    public override void Paint(Graphics g, Rectangle r) {
        // Painting code goes here
    }
}

ButtonDenetim ortak bir özellik bildirir Caption .the Button control declares a public Caption property. get Caption Özelliğin erişimcisi özel alanda depolanan dizeyi döndürür caption .The get accessor of the Caption property returns the string stored in the private caption field. setErişimci, yeni değerin geçerli değerden farklı olup olmadığını denetler ve bu durumda yeni değeri depolar ve denetimi yeniden boyar.The set accessor checks if the new value is different from the current value, and if so, it stores the new value and repaints the control. Özellikler genellikle yukarıda gösterilen kalıbı izler: get erişimci yalnızca özel bir alanda depolanan bir değer döndürür ve set erişimci bu özel alanı değiştirir ve ardından nesnenin durumunu tamamen güncelleştirmek için gereken ek eylemleri gerçekleştirir.Properties often follow the pattern shown above: The get accessor simply returns a value stored in a private field, and the set accessor modifies that private field and then performs any additional actions required to fully update the state of the object.

ButtonYukarıdaki sınıf verildiğinde, özelliğin kullanım örneği aşağıda verilmiştir Caption :Given the Button class above, the following is an example of use of the Caption property:

Button okButton = new Button();
okButton.Caption = "OK";            // Invokes set accessor
string s = okButton.Caption;        // Invokes get accessor

Burada, set erişimci özelliğe bir değer atanarak çağrılır ve get erişimci bir ifadede özelliğe başvuruda bulunarak çağrılır.Here, the set accessor is invoked by assigning a value to the property, and the get accessor is invoked by referencing the property in an expression.

get set Bir özelliğin ve erişimcileri farklı Üyeler değildir ve bir özelliğin erişimcilerinin ayrı ayrı bildirilmesini mümkün değildir.The get and set accessors of a property are not distinct members, and it is not possible to declare the accessors of a property separately. Bu nedenle, bir okuma-yazma özelliğinin iki erişimcinin farklı erişilebilirliği olması mümkün değildir.As such, it is not possible for the two accessors of a read-write property to have different accessibility. ÖrnekteThe example

class A
{
    private string name;

    public string Name {                // Error, duplicate member name
        get { return name; }
    }

    public string Name {                // Error, duplicate member name
        set { name = value; }
    }
}

tek bir okuma-yazma özelliği bildirmiyor.does not declare a single read-write property. Bunun yerine, aynı ada sahip iki özellik bildirir, bir salt okunurdur ve bir salt yazılır.Rather, it declares two properties with the same name, one read-only and one write-only. Aynı sınıfta belirtilen iki üye aynı ada sahip olmadığından, örnek bir derleme zamanı hatası oluşmasına neden olur.Since two members declared in the same class cannot have the same name, the example causes a compile-time error to occur.

Türetilmiş bir sınıf devralınan bir özellik ile aynı ada sahip bir özelliği bildiriyorsa, türetilen Özellik devralınan özelliği hem okuma hem de yazma açısından gizler.When a derived class declares a property by the same name as an inherited property, the derived property hides the inherited property with respect to both reading and writing. ÖrnekteIn the example

class A
{
    public int P {
        set {...}
    }
}

class B: A
{
    new public int P {
        get {...}
    }
}

Piçindeki özelliği B , P içindeki özelliğini A hem okuma hem de yazma açısından gizler.the P property in B hides the P property in A with respect to both reading and writing. Bu nedenle, deyimlerdeThus, in the statements

B b = new B();
b.P = 1;          // Error, B.P is read-only
((A)b).P = 1;     // Ok, reference to A.P

b.P P ' deki salt B yazılır özelliği ' deki salt yazılır özelliğini gizlemediğinden, ' a atama, derleme zamanı hatasına neden olur P A .the assignment to b.P causes a compile-time error to be reported, since the read-only P property in B hides the write-only P property in A. Ancak, bir dönüştürmenin gizli özelliğe erişmek için kullanılabileceğini unutmayın P .Note, however, that a cast can be used to access the hidden P property.

Ortak alanlardan farklı olarak, özellikler bir nesnenin iç durumu ile ortak arabirimi arasında bir ayrım sağlar.Unlike public fields, properties provide a separation between an object's internal state and its public interface. Örneği göz önünde bulundurun:Consider the example:

class Label
{
    private int x, y;
    private string caption;

    public Label(int x, int y, string caption) {
        this.x = x;
        this.y = y;
        this.caption = caption;
    }

    public int X {
        get { return x; }
    }

    public int Y {
        get { return y; }
    }

    public Point Location {
        get { return new Point(x, y); }
    }

    public string Caption {
        get { return caption; }
    }
}

Burada, Label sınıfı iki int alanı x ve y , konumunu depolamak için kullanır.Here, the Label class uses two int fields, x and y, to store its location. Konum, hem hem de bir özellik olarak X Y ve Location türünün özelliği olarak genel kullanıma sunulur Point .The location is publicly exposed both as an X and a Y property and as a Location property of type Point. Uygulamasının gelecek bir sürümünde, Label konumu dahili olarak depolamak daha uygun hale gelirse Point , bu değişiklik sınıfın genel arabirimini etkilemeden yapılabilir:If, in a future version of Label, it becomes more convenient to store the location as a Point internally, the change can be made without affecting the public interface of the class:

class Label
{
    private Point location;
    private string caption;

    public Label(int x, int y, string caption) {
        this.location = new Point(x, y);
        this.caption = caption;
    }

    public int X {
        get { return location.x; }
    }

    public int Y {
        get { return location.y; }
    }

    public Point Location {
        get { return location; }
    }

    public string Caption {
        get { return caption; }
    }
}

xAlan ve y bunun yerine public readonly , bu tür bir değişikliği sınıfında yapmak imkansız olurdu Label .Had x and y instead been public readonly fields, it would have been impossible to make such a change to the Label class.

Durumu özellikler aracılığıyla göstermek, alanları doğrudan açığa çıkarmadan daha az verimlidir.Exposing state through properties is not necessarily any less efficient than exposing fields directly. Özellikle, bir özellik sanal olmayan ve yalnızca küçük miktarda kod içerdiğinde, yürütme ortamı erişimcileri çağrılarını erişimcilerinin gerçek koduyla değiştirebilir.In particular, when a property is non-virtual and contains only a small amount of code, the execution environment may replace calls to accessors with the actual code of the accessors. Bu işlem, satır içi olarak bilinir ve özellik erişimini alan erişimi olarak verimli hale getirir, ancak özelliklerin daha fazla esnekliğini korur.This process is known as inlining, and it makes property access as efficient as field access, yet preserves the increased flexibility of properties.

Bir get erişimcinin çağrılması bir alanın değerini okumak için kavramsal olarak denk olduğundan, get erişimcilerin observable yan etkileri olması için kötü programlama stili olarak değerlendirilir.Since invoking a get accessor is conceptually equivalent to reading the value of a field, it is considered bad programming style for get accessors to have observable side-effects. ÖrnekteIn the example

class Counter
{
    private int next;

    public int Next {
        get { return next++; }
    }
}

özelliğin değeri, Next özelliğin daha önce erişilme sayısına bağlıdır.the value of the Next property depends on the number of times the property has previously been accessed. Bu nedenle, özelliğe erişmek bir observable yan etkisi oluşturur ve özellik bunun yerine bir yöntem olarak uygulanmalıdır.Thus, accessing the property produces an observable side-effect, and the property should be implemented as a method instead.

Erişimcileri için "yan etkileri yok" kuralı, get get erişimcilerin yalnızca alanlarda depolanan değerleri döndürmek için her zaman yazılması anlamına gelmez.The "no side-effects" convention for get accessors doesn't mean that get accessors should always be written to simply return values stored in fields. Aslında, get erişimciler genellikle birden çok alana erişerek veya yöntemleri çağırarak bir özelliğin değerini hesaplar.Indeed, get accessors often compute the value of a property by accessing multiple fields or invoking methods. Ancak, düzgün tasarlanmış bir get erişimci nesnenin durumunda observable değişikliklerine neden olan hiçbir eylem gerçekleştirmiyor.However, a properly designed get accessor performs no actions that cause observable changes in the state of the object.

Özellikler, ilk kez başvuruluncaya kadar bir kaynağın başlatılmasını geciktirmek için kullanılabilir.Properties can be used to delay initialization of a resource until the moment it is first referenced. Örnek:For example:

using System.IO;

public class Console
{
    private static TextReader reader;
    private static TextWriter writer;
    private static TextWriter error;

    public static TextReader In {
        get {
            if (reader == null) {
                reader = new StreamReader(Console.OpenStandardInput());
            }
            return reader;
        }
    }

    public static TextWriter Out {
        get {
            if (writer == null) {
                writer = new StreamWriter(Console.OpenStandardOutput());
            }
            return writer;
        }
    }

    public static TextWriter Error {
        get {
            if (error == null) {
                error = new StreamWriter(Console.OpenStandardError());
            }
            return error;
        }
    }
}

ConsoleSınıfı, In Out Error sırasıyla standart giriş, çıkış ve hata cihazlarını temsil eden üç özellik içerir,, ve.The Console class contains three properties, In, Out, and Error, that represent the standard input, output, and error devices, respectively. Bu üyelerin özellikler olarak kullanıma Console sunulmasıyla, sınıf gerçekten kullanılana kadar başlatma durumlarını erteleyebilir.By exposing these members as properties, the Console class can delay their initialization until they are actually used. Örneğin, ilk Out olarak özelliğe başvurulduğundaFor example, upon first referencing the Out property, as in

Console.Out.WriteLine("hello, world");

TextWriterçıkış aygıtı için temel alınan oluşturulur.the underlying TextWriter for the output device is created. Ancak uygulama In ve özelliklerine başvuru yapıyorsa Error , bu cihazlar için hiçbir nesne oluşturulmaz.But if the application makes no reference to the In and Error properties, then no objects are created for those devices.

Otomatik uygulanan özelliklerAutomatically implemented properties

Otomatik olarak uygulanan bir Özellik (ya da Short için Otomatik Özellik ), salt noktalı erişimci gövdeleriyle soyut olmayan extern olmayan bir özelliktir.An automatically implemented property (or auto-property for short), is a non-abstract non-extern property with semicolon-only accessor bodies. Otomatik Özellikler bir get erişimcisine sahip olmalı ve isteğe bağlı olarak bir set erişimcisine sahip olabilir.Auto-properties must have a get accessor and can optionally have a set accessor.

Bir özellik otomatik olarak uygulanan bir özellik olarak belirtildiğinde, özelliği için otomatik olarak bir yedekleme alanı kullanılabilir ve erişimciler, bu yedekleme alanına okuma ve yazma için uygulanır.When a property is specified as an automatically implemented property, a hidden backing field is automatically available for the property, and the accessors are implemented to read from and write to that backing field. Auto özelliğinin ayarlanmış bir erişimcisi yoksa, yedekleme alanı kabul edilir readonly (salt okunur alanlar).If the auto-property has no set accessor, the backing field is considered readonly (Readonly fields). readonlyYalnızca bir alan gibi, bir alıcı otomatik özelliği de kapsayan sınıfın oluşturucusunun gövdesinde de atanabilir.Just like a readonly field, a getter-only auto-property can also be assigned to in the body of a constructor of the enclosing class. Böyle bir atama, doğrudan özelliğinin salt okunur yedekleme alanına atar.Such an assignment assigns directly to the readonly backing field of the property.

Otomatik Özellik isteğe bağlı olarak, doğrudan bir variable_initializer (değişken başlatıcıları) olarak yedekleme alanına uygulanan bir property_initializer olabilir.An auto-property may optionally have a property_initializer, which is applied directly to the backing field as a variable_initializer (Variable initializers).

Aşağıdaki örnek:The following example:

public class Point {
    public int X { get; set; } = 0;
    public int Y { get; set; } = 0;
}

aşağıdaki bildirime eşdeğerdir:is equivalent to the following declaration:

public class Point {
    private int __x = 0;
    private int __y = 0;
    public int X { get { return __x; } set { __x = value; } }
    public int Y { get { return __y; } set { __y = value; } }
}

Aşağıdaki örnek:The following example:

public class ReadOnlyPoint
{
    public int X { get; }
    public int Y { get; }
    public ReadOnlyPoint(int x, int y) { X = x; Y = y; }
}

aşağıdaki bildirime eşdeğerdir:is equivalent to the following declaration:

public class ReadOnlyPoint
{
    private readonly int __x;
    private readonly int __y;
    public int X { get { return __x; } }
    public int Y { get { return __y; } }
    public ReadOnlyPoint(int x, int y) { __x = x; __y = y; }
}

ReadOnly alanının atamalarının, Oluşturucu içinde gerçekleştikleri için geçerli olduğuna dikkat edin.Notice that the assignments to the readonly field are legal, because they occur within the constructor.

ErişilebilirlikAccessibility

Bir erişimcinin accessor_modifier varsa, erişimcinin erişilebilirlik etki alanı (erişilebilirlik etki alanları) accessor_modifier belirtilen erişilebilirliği kullanılarak belirlenir.If an accessor has an accessor_modifier, the accessibility domain (Accessibility domains) of the accessor is determined using the declared accessibility of the accessor_modifier. Bir erişimcinin accessor_modifier yoksa, erişimcinin erişilebilirlik etki alanı, özelliğin veya dizin oluşturucunun tanımlanmış erişilebilirliğine göre belirlenir.If an accessor does not have an accessor_modifier, the accessibility domain of the accessor is determined from the declared accessibility of the property or indexer.

Accessor_modifier varlığı, üye aramasını (işleçler) veya aşırı yükleme çözümünü (aşırı yükleme çözümlemesi) hiçbir şekilde etkilemez.The presence of an accessor_modifier never affects member lookup (Operators) or overload resolution (Overload resolution). Özellik veya dizin oluşturucudaki değiştiriciler her zaman erişim bağlamından bağımsız olarak hangi özelliğin veya dizin oluşturucunun bağlı olduğunu belirlenir.The modifiers on the property or indexer always determine which property or indexer is bound to, regardless of the context of the access.

Belirli bir özellik veya Dizin Oluşturucu seçildikten sonra, bu kullanımın geçerli olup olmadığını anlamak için ilgili erişimcilerinin erişilebilirlik etki alanları kullanılır:Once a particular property or indexer has been selected, the accessibility domains of the specific accessors involved are used to determine if that usage is valid:

  • Kullanım bir değer (Ifadelerin değerleri) ise, get erişimci bulunmalı ve erişilebilir olmalıdır.If the usage is as a value (Values of expressions), the get accessor must exist and be accessible.
  • Kullanım basit bir atamanın hedefi (basit atama) ise, set erişimci bulunmalı ve erişilebilir olmalıdır.If the usage is as the target of a simple assignment (Simple assignment), the set accessor must exist and be accessible.
  • Kullanım, bileşik atamanın hedefi (bileşik atama) veya ++ ya da -- Işleçlerinin hedefi (işlev üyeleri.9, çağırma ifadeleri) olarak ise, hem erişimciler hem de get set erişimci bulunmalı ve erişilebilir olmalıdır.If the usage is as the target of compound assignment (Compound assignment), or as the target of the ++ or -- operators (Function members.9, Invocation expressions), both the get accessors and the set accessor must exist and be accessible.

Aşağıdaki örnekte, özelliği, A.Text B.Text yalnızca erişimcinin çağrıldığı bağlamlarda bile özelliği tarafından gizlenir set .In the following example, the property A.Text is hidden by the property B.Text, even in contexts where only the set accessor is called. Buna karşılık, özelliği B.Count sınıfına erişemez M , bu nedenle A.Count bunun yerine erişilebilir özellik kullanılır.In contrast, the property B.Count is not accessible to class M, so the accessible property A.Count is used instead.

class A
{
    public string Text {
        get { return "hello"; }
        set { }
    }

    public int Count {
        get { return 5; }
        set { }
    }
}

class B: A
{
    private string text = "goodbye"; 
    private int count = 0;

    new public string Text {
        get { return text; }
        protected set { text = value; }
    }

    new protected int Count { 
        get { return count; }
        set { count = value; }
    }
}

class M
{
    static void Main() {
        B b = new B();
        b.Count = 12;             // Calls A.Count set accessor
        int i = b.Count;          // Calls A.Count get accessor
        b.Text = "howdy";         // Error, B.Text set accessor not accessible
        string s = b.Text;        // Calls B.Text get accessor
    }
}

Arabirim uygulamak için kullanılan bir erişimcinin accessor_modifier olmayabilir.An accessor that is used to implement an interface may not have an accessor_modifier. Bir arabirim uygulamak için yalnızca bir erişimci kullanılırsa, diğer erişimci bir accessor_modifier ile bildirilemeyebilir:If only one accessor is used to implement an interface, the other accessor may be declared with an accessor_modifier:

public interface I
{
    string Prop { get; }
}

public class C: I
{
    public string Prop {
        get { return "April"; }       // Must not have a modifier here
        internal set {...}            // Ok, because I.Prop has no set accessor
    }
}

Sanal, Sealed, override ve abstract Özellik erişimcileriVirtual, sealed, override, and abstract property accessors

virtualÖzellik bildirimi, özelliği erişimcilerinin sanal olduğunu belirtir.A virtual property declaration specifies that the accessors of the property are virtual. virtualDeğiştirici, okuma-yazma özelliğinin her iki erişimcisi için de geçerlidir; bir okuma-yazma özelliğinin yalnızca bir erişimcisinin sanal olması mümkün değildir.The virtual modifier applies to both accessors of a read-write property—it is not possible for only one accessor of a read-write property to be virtual.

abstractÖzellik bildirimi, özelliğin erişimcilerinin sanal olduğunu, ancak erişimcilerinin gerçek bir uygulamasını sağlamamayı belirtir.An abstract property declaration specifies that the accessors of the property are virtual, but does not provide an actual implementation of the accessors. Bunun yerine, soyut olmayan türetilmiş sınıfların, özelliği geçersiz kılarak erişimcileri için kendi uygulamasını sağlaması gerekir.Instead, non-abstract derived classes are required to provide their own implementation for the accessors by overriding the property. Soyut Özellik bildirimine yönelik bir erişimci gerçek uygulama sunmadığından, accessor_body yalnızca noktalı virgülden oluşur.Because an accessor for an abstract property declaration provides no actual implementation, its accessor_body simply consists of a semicolon.

Hem hem de değiştiricilerini içeren bir özellik bildirimi, abstract override özelliğin soyut olduğunu ve bir temel özelliği geçersiz kıldığını belirtir.A property declaration that includes both the abstract and override modifiers specifies that the property is abstract and overrides a base property. Böyle bir özelliğin erişimcileri de soyuttur.The accessors of such a property are also abstract.

Soyut Özellik bildirimlerine yalnızca soyut sınıflarda izin verilir (soyut sınıflar). Devralınan bir sanal özelliğin erişimcileri, bir yönergeyi belirten özellik bildirimini ekleyerek türetilmiş bir sınıfta geçersiz kılınabilir override .Abstract property declarations are only permitted in abstract classes (Abstract classes).The accessors of an inherited virtual property can be overridden in a derived class by including a property declaration that specifies an override directive. Bu, geçersiz kılma özelliği bildirimi olarak bilinir.This is known as an overriding property declaration. Geçersiz kılan özellik bildirimi yeni bir özellik bildirmiyor.An overriding property declaration does not declare a new property. Bunun yerine, var olan bir sanal özelliğin erişimcilerinin uygulamalarını özelleştirir.Instead, it simply specializes the implementations of the accessors of an existing virtual property.

Geçersiz kılma özelliği bildirimi devralınan özellik olarak aynı erişilebilirlik değiştiricilerini, türü ve adı belirtmelidir.An overriding property declaration must specify the exact same accessibility modifiers, type, and name as the inherited property. Devralınan özelliğin yalnızca tek bir erişimcisi varsa (yani devralınan özellik salt okunurdur veya salt yazılır ise), geçersiz kılma özelliği yalnızca o erişimciyi içermelidir.If the inherited property has only a single accessor (i.e., if the inherited property is read-only or write-only), the overriding property must include only that accessor. Devralınan özellik her iki erişimcileri de içeriyorsa (yani, devralınan Özellik okuma-yazma ise), geçersiz kılma özelliği tek bir erişimci veya her iki erişimci içerebilir.If the inherited property includes both accessors (i.e., if the inherited property is read-write), the overriding property can include either a single accessor or both accessors.

Geçersiz kılma özelliği bildirimi, değiştiricisini içerebilir sealed .An overriding property declaration may include the sealed modifier. Bu değiştiricinin kullanılması, türetilmiş bir sınıfın özelliği daha fazla geçersiz kılmasını önler.Use of this modifier prevents a derived class from further overriding the property. Sealed özelliğinin erişimcileri de korumalıdır.The accessors of a sealed property are also sealed.

Bildirim ve çağırma sözdiziminde farklar haricinde, sanal, korumalı, geçersiz kılma ve soyut erişimciler, sanal, mühürlenmiş, geçersiz kılma ve soyut yöntemler gibi davranır.Except for differences in declaration and invocation syntax, virtual, sealed, override, and abstract accessors behave exactly like virtual, sealed, override and abstract methods. Özellikle, sanal yöntemlerdeaçıklanan kurallar, geçersiz kılma yöntemleri, korumalı Yöntemlerve soyut yöntemler , erişimciler karşılık gelen bir formun yöntemlerimiz gibi geçerlidir:Specifically, the rules described in Virtual methods, Override methods, Sealed methods, and Abstract methods apply as if accessors were methods of a corresponding form:

  • getErişimci, özellik türünün dönüş değeri ve kapsayan özelliği ile aynı değiştiriciler içeren parametresiz bir yönteme karşılık gelir.A get accessor corresponds to a parameterless method with a return value of the property type and the same modifiers as the containing property.
  • setErişimci, özellik türünün tek değerli parametresine, void dönüş türüne ve kapsayan özelliği ile aynı değiştiricilere karşılık gelen bir yönteme karşılık gelir.A set accessor corresponds to a method with a single value parameter of the property type, a void return type, and the same modifiers as the containing property.

ÖrnekteIn the example

abstract class A
{
    int y;

    public virtual int X {
        get { return 0; }
    }

    public virtual int Y {
        get { return y; }
        set { y = value; }
    }

    public abstract int Z { get; set; }
}

X , sanal bir salt okunurdur özelliğidir, Y sanal bir okuma-yazma özelliğidir ve Z soyut bir okuma-yazma özelliğidir.X is a virtual read-only property, Y is a virtual read-write property, and Z is an abstract read-write property. ZSoyut olduğundan, kapsayan sınıf A de soyut olarak bildirilmelidir.Because Z is abstract, the containing class A must also be declared abstract.

Öğesinden türetilen bir sınıf A aşağıda gösterilmektedir:A class that derives from A is show below:

class B: A
{
    int z;

    public override int X {
        get { return base.X + 1; }
    }

    public override int Y {
        set { base.Y = value < 0? 0: value; }
    }

    public override int Z {
        get { return z; }
        set { z = value; }
    }
}

Burada,, ve bildirimleri X Y Z özellik bildirimlerini geçersiz kılar.Here, the declarations of X, Y, and Z are overriding property declarations. Her özellik bildirimi, karşılık gelen devralınmış özelliğin erişilebilirlik değiştiricilerini, türünü ve adını tam olarak eşleştirir.Each property declaration exactly matches the accessibility modifiers, type, and name of the corresponding inherited property. Ve erişimcisinin get erişimcisi, X set Y base devralınan erişimcilere erişmek için anahtar sözcüğünü kullanır.The get accessor of X and the set accessor of Y use the base keyword to access the inherited accessors. Öğesinin bildirimi, Z her iki soyut erişimciyi geçersiz kılar. bu nedenle içinde bekleyen soyut işlev üyeleri yoktur B ve B soyut olmayan bir sınıf olarak izin verilir.The declaration of Z overrides both abstract accessors—thus, there are no outstanding abstract function members in B, and B is permitted to be a non-abstract class.

Bir özellik bir olarak bildirildiğinde, geçersiz override kılınan hiçbir erişimciyi geçersiz kılma kodu tarafından erişilebilir olmalıdır.When a property is declared as an override, any overridden accessors must be accessible to the overriding code. Ayrıca, hem özelliğin hem de dizin oluşturucunun kendisi ve erişimcilerinin tanımlanmış erişilebilirliği, geçersiz kılınan üye ve erişimcilerinin ile eşleşmelidir.In addition, the declared accessibility of both the property or indexer itself, and of the accessors, must match that of the overridden member and accessors. Örnek:For example:

public class B
{
    public virtual int P {
        protected set {...}
        get {...}
    }
}

public class D: B
{
    public override int P {
        protected set {...}            // Must specify protected here
        get {...}                      // Must not have a modifier here
    }
}

EkinliklerEvents

*Event _ bir nesne veya sınıfın bildirimleri sağlamasını sağlayan bir üyedir.An *event _ is a member that enables an object or class to provide notifications. İstemciler, _ olay işleyicileri * sağlayarak olaylar için yürütülebilir kod ekleyebilir.Clients can attach executable code for events by supplying _*event handlers**.

Olaylar event_declaration s kullanılarak bildirilmiştir:Events are declared using event_declaration s:

event_declaration
    : attributes? event_modifier* 'event' type variable_declarators ';'
    | attributes? event_modifier* 'event' type member_name '{' event_accessor_declarations '}'
    ;

event_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'static'
    | 'virtual'
    | 'sealed'
    | 'override'
    | 'abstract'
    | 'extern'
    | event_modifier_unsafe
    ;

event_accessor_declarations
    : add_accessor_declaration remove_accessor_declaration
    | remove_accessor_declaration add_accessor_declaration
    ;

add_accessor_declaration
    : attributes? 'add' block
    ;

remove_accessor_declaration
    : attributes? 'remove' block
    ;

Bir event_declaration bir öznitelikler kümesi (öznitelikler) ve dört erişim değiştiricisinin (erişim değiştiricileri), ( new Yeni değiştirici), static (statik ve örnek yöntemleri), ( virtual sanal yöntemler), ( override geçersiz kılma yöntemleri), (korumalı Yöntemler), (soyut yöntemler sealed ) abstract ve extern (dış Yöntemler) değiştiricilerin geçerli bir birleşimini içerebilir.An event_declaration may include a set of attributes (Attributes) and a valid combination of the four access modifiers (Access modifiers), the new (The new modifier), static (Static and instance methods), virtual (Virtual methods), override (Override methods), sealed (Sealed methods), abstract (Abstract methods), and extern (External methods) modifiers.

Olay bildirimleri, geçerli değiştiriciler birleşimleriyle ilgili olarak yöntem bildirimleri (yöntemleriyle) ile aynı kurallara tabidir.Event declarations are subject to the same rules as method declarations (Methods) with regard to valid combinations of modifiers.

Olay bildiriminin türü bir delegate_type (başvuru türleri) olmalıdır ve bu delegate_type en azından olayın kendisi (Erişilebilirlik kısıtlamaları) olarak erişilebilir olmalıdır.The type of an event declaration must be a delegate_type (Reference types), and that delegate_type must be at least as accessible as the event itself (Accessibility constraints).

Bir olay bildirimi event_accessor_declarations içerebilir.An event declaration may include event_accessor_declarations. Ancak, dış olmayan, soyut olmayan olaylar için derleyici onları otomatik olarak (alan benzeri olaylar) sağlar; extern olaylar için, erişimciler dışarıdan sağlanır.However, if it does not, for non-extern, non-abstract events, the compiler supplies them automatically (Field-like events); for extern events, the accessors are provided externally.

Event_accessor_declarations atan bir olay bildirimi, bir veya daha fazla olayı tanımlar — her biri variable_declarator s.An event declaration that omits event_accessor_declarations defines one or more events—one for each of the variable_declarator s. Öznitelikler ve değiştiriciler, bu tür bir event_declaration tarafından belirtilen tüm üyelere uygulanır.The attributes and modifiers apply to all of the members declared by such an event_declaration.

Event_declaration , hem abstract değiştirici hem de küme ayracı ile ayrılmış event_accessor_declarations içermesi için derleme zamanı hatasıdır.It is a compile-time error for an event_declaration to include both the abstract modifier and brace-delimited event_accessor_declarations.

Bir olay bildirimi bir değiştirici içerdiğinde extern , olay *dış olay _ olarak kabul edilir.When an event declaration includes an extern modifier, the event is said to be an *external event _. Dış bir olay bildirimi gerçek uygulama içermediği için, hem değiştirici hem de extern _event_accessor_declarations * içermesi hatadır.Because an external event declaration provides no actual implementation, it is an error for it to include both the extern modifier and _event_accessor_declarations*.

Bir abstract external variable_initializer dahil etme veya değiştiriciyle bir olay bildiriminin variable_declarator için derleme zamanı hatasıdır.It is a compile-time error for a variable_declarator of an event declaration with an abstract or external modifier to include a variable_initializer.

Bir olay, ve işleçlerinin sol işleneni olarak kullanılabilir += -= (olay atama).An event can be used as the left-hand operand of the += and -= operators (Event assignment). Bu işleçler sırasıyla olay işleyicilerini bir olaydan kaldırmak ya da kaldırmak için kullanılır ve olayın erişim değiştiricileri, bu tür işlemlere izin verilen bağlamlara eklenir.These operators are used, respectively, to attach event handlers to or to remove event handlers from an event, and the access modifiers of the event control the contexts in which such operations are permitted.

+= -= Olayı bildiren tür dışındaki bir olayda izin verilen tek işlemler olduğundan, dış kod bir olay için işleyiciler ekleyebilir ve kaldırabilir, ancak başka hiçbir şekilde olay işleyicilerinin temel alınan listesini alabilir veya değiştirebilir.Since += and -= are the only operations that are permitted on an event outside the type that declares the event, external code can add and remove handlers for an event, but cannot in any other way obtain or modify the underlying list of event handlers.

Formun bir işleminde x += y veya x -= y , x bir olaysa ve başvuru, bildirimini içeren türün dışında gerçekleşirken x , işlemin sonucu bir tür olur void (türü, x x atamasından sonra değeriyle birlikte).In an operation of the form x += y or x -= y, when x is an event and the reference takes place outside the type that contains the declaration of x, the result of the operation has type void (as opposed to having the type of x, with the value of x after the assignment). Bu kural, dış kodun bir olayın temel temsilcisini dolaylı olarak incelemeden yasaklar.This rule prohibits external code from indirectly examining the underlying delegate of an event.

Aşağıdaki örnekte, olay işleyicilerinin sınıfının örneklerine nasıl eklendiği gösterilmektedir Button :The following example shows how event handlers are attached to instances of the Button class:

public delegate void EventHandler(object sender, EventArgs e);

public class Button: Control
{
    public event EventHandler Click;
}

public class LoginDialog: Form
{
    Button OkButton;
    Button CancelButton;

    public LoginDialog() {
        OkButton = new Button(...);
        OkButton.Click += new EventHandler(OkButtonClick);
        CancelButton = new Button(...);
        CancelButton.Click += new EventHandler(CancelButtonClick);
    }

    void OkButtonClick(object sender, EventArgs e) {
        // Handle OkButton.Click event
    }

    void CancelButtonClick(object sender, EventArgs e) {
        // Handle CancelButton.Click event
    }
}

Burada, LoginDialog örnek Oluşturucu iki örnek oluşturur Button ve olay işleyicilerini Click olaylara ekler.Here, the LoginDialog instance constructor creates two Button instances and attaches event handlers to the Click events.

Alan benzeri olaylarField-like events

Bir olayın bildirimini içeren sınıfın veya yapının program metni içinde, bazı olaylar alan gibi kullanılabilir.Within the program text of the class or struct that contains the declaration of an event, certain events can be used like fields. Bu şekilde kullanılmak üzere, bir olay ya da olmamalıdır abstract extern ve açıkça event_accessor_declarations içermemelidir.To be used in this way, an event must not be abstract or extern, and must not explicitly include event_accessor_declarations. Bu tür bir olay, bir alana izin veren herhangi bir bağlamda kullanılabilir.Such an event can be used in any context that permits a field. Alan, olaya eklenmiş olan olay işleyicileri listesine başvuran bir temsilci (Temsilciler) içerir.The field contains a delegate (Delegates) which refers to the list of event handlers that have been added to the event. Hiçbir olay işleyicisi eklenmemişse, alan içerir null .If no event handlers have been added, the field contains null.

ÖrnekteIn the example

public delegate void EventHandler(object sender, EventArgs e);

public class Button: Control
{
    public event EventHandler Click;

    protected void OnClick(EventArgs e) {
        if (Click != null) Click(this, e);
    }

    public void Reset() {
        Click = null;
    }
}

Click sınıf içinde bir alan olarak kullanılır Button .Click is used as a field within the Button class. Örneğin gösterdiği gibi, alan, temsilci çağırma ifadelerinde incelenebilir, değiştirilebilir ve kullanılabilir.As the example demonstrates, the field can be examined, modified, and used in delegate invocation expressions. OnClickSınıfındaki yöntemi, Button olayı "oluşturur" Click .The OnClick method in the Button class "raises" the Click event. Bir olayı oluşturma kavramı, olayın gösterdiği temsilciyi çağırmak için tam olarak eşdeğerdir. bu nedenle, olayları yükseltmek için özel dil yapıları yoktur.The notion of raising an event is precisely equivalent to invoking the delegate represented by the event—thus, there are no special language constructs for raising events. Temsilci çağrısının önünde, temsilcinin null olmamasını sağlayan bir denetim olduğunu unutmayın.Note that the delegate invocation is preceded by a check that ensures the delegate is non-null.

Sınıf bildiriminin dışında Button , Click üye yalnızca ve işleçlerinin sol tarafında, += -= içinde olduğu gibi kullanılabilir.Outside the declaration of the Button class, the Click member can only be used on the left-hand side of the += and -= operators, as in

b.Click += new EventHandler(...);

Bu, olayın çağırma listesine bir temsilci ekler Click vewhich appends a delegate to the invocation list of the Click event, and

b.Click -= new EventHandler(...);

Bu, olayın çağırma listesinden bir temsilciyi kaldırır Click .which removes a delegate from the invocation list of the Click event.

Alan benzeri bir olay derlenirken, derleyici temsilciyi tutmak için otomatik olarak depolama oluşturur ve temsilci alanına olay işleyicileri ekleyen veya çıkarmayan olay için erişimciler oluşturur.When compiling a field-like event, the compiler automatically creates storage to hold the delegate, and creates accessors for the event that add or remove event handlers to the delegate field. Ekleme ve kaldırma işlemleri iş parçacığı açısından güvenlidir ve bir örnek olayı için kapsayan nesne üzerinde kilit (kilit deyimi) veya statik bir olay için tür nesnesi (anonim nesne oluşturma ifadeleri) tutulurken (ancak için gerekli değildir) yapılması gerekir.The addition and removal operations are thread safe, and may (but are not required to) be done while holding the lock (The lock statement) on the containing object for an instance event, or the type object (Anonymous object creation expressions) for a static event.

Bu nedenle, formun bir örnek olay bildirimi:Thus, an instance event declaration of the form:

class X
{
    public event D Ev;
}

Şuna eşdeğer bir değere derlenecek:will be compiled to something equivalent to:

class X
{
    private D __Ev;  // field to hold the delegate

    public event D Ev {
        add {
            /* add the delegate in a thread safe way */
        }

        remove {
            /* remove the delegate in a thread safe way */
        }
    }
}

Sınıfı içinde, X Ev ve işleçlerinin sol tarafındaki başvurular += -= ekleme ve kaldırma erişimcilerinin çağrılmasına neden olur.Within the class X, references to Ev on the left-hand side of the += and -= operators cause the add and remove accessors to be invoked. Diğer tüm başvuruları Ev , bunun yerine gizli alana başvuracak şekilde derlenir __Ev (üye erişim).All other references to Ev are compiled to reference the hidden field __Ev instead (Member access). "" Adı __Ev rastgele; gizli alan herhangi bir ada veya hiç ada sahip olabilir.The name "__Ev" is arbitrary; the hidden field could have any name or no name at all.

Olay erişimcileriEvent accessors

Olay bildirimleri, yukarıdaki örnekte olduğu gibi genellikle event_accessor_declarations atlamaz Button .Event declarations typically omit event_accessor_declarations, as in the Button example above. Bunun için bir durum, her olay için bir alanın depolama maliyetinin kabul edilebilir olması durumunda oluşur.One situation for doing so involves the case in which the storage cost of one field per event is not acceptable. Böyle durumlarda, bir sınıf event_accessor_declarations içerebilir ve olay işleyicilerinin listesini depolamak için özel bir mekanizma kullanabilir.In such cases, a class can include event_accessor_declarations and use a private mechanism for storing the list of event handlers.

Bir olayın event_accessor_declarations , olay işleyicilerini ekleme ve kaldırma ile ilişkili yürütülebilir deyimleri belirtir.The event_accessor_declarations of an event specify the executable statements associated with adding and removing event handlers.

Erişimci bildirimleri bir add_accessor_declaration ve bir remove_accessor_declaration oluşur.The accessor declarations consist of an add_accessor_declaration and a remove_accessor_declaration. Her erişimci bildirimi belirtecinden oluşur add veya remove arkasından bir blok gelir.Each accessor declaration consists of the token add or remove followed by a block. Bir add_accessor_declaration ilişkili blok , bir olay işleyicisi eklendiğinde yürütülecek deyimleri belirtir ve bir remove_accessor_declaration ilişkili blok , bir olay işleyicisi kaldırıldığında yürütülecek deyimleri belirler.The block associated with an add_accessor_declaration specifies the statements to execute when an event handler is added, and the block associated with a remove_accessor_declaration specifies the statements to execute when an event handler is removed.

Her add_accessor_declaration ve remove_accessor_declaration , olay türü ve dönüş türü tek bir değer parametresine sahip bir yönteme karşılık gelir void .Each add_accessor_declaration and remove_accessor_declaration corresponds to a method with a single value parameter of the event type and a void return type. Bir olay erişimcisinin örtük parametresi olarak adlandırılmıştır value .The implicit parameter of an event accessor is named value. Olay atamasında bir olay kullanıldığında, uygun olay erişimcisi kullanılır.When an event is used in an event assignment, the appropriate event accessor is used. Özellikle, atama işleci ise += Add erişimcisi kullanılır ve atama işleci varsa -= kaldırma erişimcisi kullanılır.Specifically, if the assignment operator is += then the add accessor is used, and if the assignment operator is -= then the remove accessor is used. Her iki durumda da, atama işlecinin sağ işleneni olay erişimcisinin bağımsız değişkeni olarak kullanılır.In either case, the right-hand operand of the assignment operator is used as the argument to the event accessor. Bir add_accessor_declaration veya Remove_accessor_declaration bloğunun, void Yöntem gövdesindeaçıklanan yöntemlere yönelik kurallara uyması gerekir.The block of an add_accessor_declaration or a remove_accessor_declaration must conform to the rules for void methods described in Method body. Özellikle, return Bu tür bir bloktaki deyimlerin bir ifade belirtmelerine izin verilmez.In particular, return statements in such a block are not permitted to specify an expression.

Bir olay erişimcisinde örtük olarak adlı bir parametre olduğundan value , bu ada sahip olması için bir yerel değişken veya bir olay erişimcisinde belirtilen sabit için derleme zamanı hatası olur.Since an event accessor implicitly has a parameter named value, it is a compile-time error for a local variable or constant declared in an event accessor to have that name.

ÖrnekteIn the example

class Control: Component
{
    // Unique keys for events
    static readonly object mouseDownEventKey = new object();
    static readonly object mouseUpEventKey = new object();

    // Return event handler associated with key
    protected Delegate GetEventHandler(object key) {...}

    // Add event handler associated with key
    protected void AddEventHandler(object key, Delegate handler) {...}

    // Remove event handler associated with key
    protected void RemoveEventHandler(object key, Delegate handler) {...}

    // MouseDown event
    public event MouseEventHandler MouseDown {
        add { AddEventHandler(mouseDownEventKey, value); }
        remove { RemoveEventHandler(mouseDownEventKey, value); }
    }

    // MouseUp event
    public event MouseEventHandler MouseUp {
        add { AddEventHandler(mouseUpEventKey, value); }
        remove { RemoveEventHandler(mouseUpEventKey, value); }
    }

    // Invoke the MouseUp event
    protected void OnMouseUp(MouseEventArgs args) {
        MouseEventHandler handler; 
        handler = (MouseEventHandler)GetEventHandler(mouseUpEventKey);
        if (handler != null)
            handler(this, args);
    }
}

Controlsınıfı, olaylar için bir iç depolama mekanizması uygular.the Control class implements an internal storage mechanism for events. AddEventHandlerYöntemi bir temsilci değerini bir anahtarla ilişkilendirir, GetEventHandler yöntemi şu anda bir anahtarla ilişkili temsilciyi döndürür ve RemoveEventHandler yöntemi belirtilen olay için bir temsilciyi olay işleyicisi olarak kaldırır.The AddEventHandler method associates a delegate value with a key, the GetEventHandler method returns the delegate currently associated with a key, and the RemoveEventHandler method removes a delegate as an event handler for the specified event. Temel alınan depolama mekanizması, bir null temsilci değerini bir anahtarla ilişkilendirme maliyeti olmaması ve bu nedenle işlenmemiş olayların hiçbir depolama alanını tüketmesi gibi tasarlanmıştır.Presumably, the underlying storage mechanism is designed such that there is no cost for associating a null delegate value with a key, and thus unhandled events consume no storage.

Statik ve örnek olaylarıStatic and instance events

Bir olay bildirimi bir değiştirici içerdiğinde static , olay *statik olay _ olarak kabul edilir.When an event declaration includes a static modifier, the event is said to be a *static event _. Değiştirici yoksa static , olay _ örnek olayı * olarak kabul edilir.When no static modifier is present, the event is said to be an _*instance event**.

Statik bir olay, belirli bir örnekle ilişkili değildir ve this statik bir olayın erişimcilerine başvurmak için derleme zamanı hatasıdır.A static event is not associated with a specific instance, and it is a compile-time error to refer to this in the accessors of a static event.

Örnek olay, bir sınıfın belirli bir örneğiyle ilişkilendirilir ve bu örneğe bu this olayın erişimcilerinde (Bu erişim) erişilebilir.An instance event is associated with a given instance of a class, and this instance can be accessed as this (This access) in the accessors of that event.

Bir olaya, formun bir member_access (üye erişimi) başvurduğu zaman, statik bir E.M M olaydır, E içeren bir türü belirtmek M ve M bir örnek olayıdır, içeren bir türün örneğini belirtmelidir M .When an event is referenced in a member_access (Member access) of the form E.M, if M is a static event, E must denote a type containing M, and if M is an instance event, E must denote an instance of a type containing M.

Statik ve örnek üyeleri arasındaki farklılıklar, statik ve örnek üyelerindedaha ayrıntılı bir şekilde ele alınmıştır.The differences between static and instance members are discussed further in Static and instance members.

Sanal, korumalı, geçersiz kılma ve soyut olay erişimcileriVirtual, sealed, override, and abstract event accessors

virtualOlay bildirimi, bu olayın erişimcilerinin sanal olduğunu belirtir.A virtual event declaration specifies that the accessors of that event are virtual. virtualDeğiştirici her iki bir olayın erişimcisi için geçerlidir.The virtual modifier applies to both accessors of an event.

Bir abstract olay bildirimi, olayın erişimcilerinin sanal olduğunu, ancak erişimcilerinin gerçek bir uygulamasını sağlamamayı belirtir.An abstract event declaration specifies that the accessors of the event are virtual, but does not provide an actual implementation of the accessors. Bunun yerine, Özet olmayan türetilmiş sınıfların, olayı geçersiz kılarak erişimcileri için kendi uygulamasını sağlaması gerekir.Instead, non-abstract derived classes are required to provide their own implementation for the accessors by overriding the event. Soyut bir olay bildirimi gerçek uygulama sağlamadığı için, küme ayracı ile ayrılmış event_accessor_declarations sağlayamaz.Because an abstract event declaration provides no actual implementation, it cannot provide brace-delimited event_accessor_declarations.

Hem hem de değiştiricilerini içeren bir olay bildirimi abstract override , olayın soyut olduğunu ve bir temel olayı geçersiz kıldığını belirtir.An event declaration that includes both the abstract and override modifiers specifies that the event is abstract and overrides a base event. Böyle bir olayın erişimcileri de soyuttur.The accessors of such an event are also abstract.

Soyut olay bildirimlerine yalnızca soyut sınıflarda izin verilir (soyut sınıflar).Abstract event declarations are only permitted in abstract classes (Abstract classes).

Bir değiştirici belirten bir olay bildirimi eklenerek, devralınan bir sanal olayın erişimcileri türetilmiş bir sınıfta geçersiz kılınabilir override .The accessors of an inherited virtual event can be overridden in a derived class by including an event declaration that specifies an override modifier. Bu, geçersiz kılan bir olay bildirimi olarak bilinir.This is known as an overriding event declaration. Geçersiz kılan bir olay bildirimi yeni bir olay bildirmiyor.An overriding event declaration does not declare a new event. Bunun yerine, var olan bir sanal olay erişimcilerinin uygulamalarını özelleştirir.Instead, it simply specializes the implementations of the accessors of an existing virtual event.

Geçersiz kılan bir olay bildirimi, geçersiz kılınan olayla aynı erişilebilirlik değiştiricilerini, türü ve adı belirtmelidir.An overriding event declaration must specify the exact same accessibility modifiers, type, and name as the overridden event.

Geçersiz kılan bir olay bildirimi sealed değiştiriciyi içerebilir.An overriding event declaration may include the sealed modifier. Bu değiştiricinin kullanılması, türetilmiş bir sınıfın olayı daha fazla geçersiz kılmasını önler.Use of this modifier prevents a derived class from further overriding the event. Korumalı bir olayın erişimcileri de korumalıdır.The accessors of a sealed event are also sealed.

Geçersiz kılan bir olay bildiriminin bir değiştirici içermesi için derleme zamanı hatasıdır new .It is a compile-time error for an overriding event declaration to include a new modifier.

Bildirim ve çağırma sözdiziminde farklar haricinde, sanal, korumalı, geçersiz kılma ve soyut erişimciler, sanal, mühürlenmiş, geçersiz kılma ve soyut yöntemler gibi davranır.Except for differences in declaration and invocation syntax, virtual, sealed, override, and abstract accessors behave exactly like virtual, sealed, override and abstract methods. Özellikle, sanal yöntemlerdeaçıklanan kurallar, geçersiz kılma yöntemleri, korumalı Yöntemlerve soyut yöntemler , erişimciler karşılık gelen bir formun yöntemlerimiz gibi geçerlidir.Specifically, the rules described in Virtual methods, Override methods, Sealed methods, and Abstract methods apply as if accessors were methods of a corresponding form. Her erişimci, olay türünün tek değerli parametresine, void dönüş türüne ve kapsayan olay ile aynı değiştiricilere karşılık gelen bir yönteme karşılık gelir.Each accessor corresponds to a method with a single value parameter of the event type, a void return type, and the same modifiers as the containing event.

Dizin OluşturucularIndexers

*Indexer _ bir nesnenin bir dizi ile aynı şekilde dizinlenmesini sağlayan bir üyedir.An *indexer _ is a member that enables an object to be indexed in the same way as an array. Dizin oluşturucular _indexer_declaration * s kullanılarak bildirilmiştir:Indexers are declared using _indexer_declaration*s:

indexer_declaration
    : attributes? indexer_modifier* indexer_declarator indexer_body
    ;

indexer_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'virtual'
    | 'sealed'
    | 'override'
    | 'abstract'
    | 'extern'
    | indexer_modifier_unsafe
    ;

indexer_declarator
    : type 'this' '[' formal_parameter_list ']'
    | type interface_type '.' 'this' '[' formal_parameter_list ']'
    ;

indexer_body
    : '{' accessor_declarations '}' 
    | '=>' expression ';'
    ;

Bir indexer_declaration bir öznitelikler kümesi (öznitelikler) ve dört erişim değiştiricisinin (erişim değiştiricileri), ( new Yeni değiştirici), virtual (sanal yöntemler), override (geçersiz kılma yöntemleri), (korumalı Yöntemler), (soyut yöntemler sealed ) abstract ve extern (dış Yöntemler) değiştiricilerin geçerli bir birleşimini içerebilir.An indexer_declaration may include a set of attributes (Attributes) and a valid combination of the four access modifiers (Access modifiers), the new (The new modifier), virtual (Virtual methods), override (Override methods), sealed (Sealed methods), abstract (Abstract methods), and extern (External methods) modifiers.

Dizin Oluşturucu bildirimleri, bir özel durum, Dizin Oluşturucu bildiriminde statik değiştiriciye izin verilmemesine neden olacak şekilde, geçerli değiştiriciler birleşimleriyle ilgili olarak yöntem bildirimleri (yöntemleri) ile aynı kurallara tabidir.Indexer declarations are subject to the same rules as method declarations (Methods) with regard to valid combinations of modifiers, with the one exception being that the static modifier is not permitted on an indexer declaration.

, virtual Ve değiştiricileri override abstract tek bir durum dışında birbirini dışlıyor.The modifiers virtual, override, and abstract are mutually exclusive except in one case. abstractVe override değiştiricileri bir soyut dizin oluşturucunun sanal bir dizin için geçersiz kılabilmesi için birlikte kullanılabilir.The abstract and override modifiers may be used together so that an abstract indexer can override a virtual one.

Bir Dizin Oluşturucu bildiriminin türü , bildirim tarafından tanıtılan dizin oluşturucunun öğe türünü belirtir.The type of an indexer declaration specifies the element type of the indexer introduced by the declaration. Dizin Oluşturucu açık bir arabirim üyesi uygulama değilse, türün ardından anahtar sözcüğü gelir this .Unless the indexer is an explicit interface member implementation, the type is followed by the keyword this. Açık arabirim üyesi uygulama için, türün arkasından bir interface_type, bir " . " ve anahtar sözcüğü gelir this .For an explicit interface member implementation, the type is followed by an interface_type, a ".", and the keyword this. Diğer üyelerin aksine, Dizin oluşturucular Kullanıcı tanımlı adlara sahip değildir.Unlike other members, indexers do not have user-defined names.

Formal_parameter_list , dizin oluşturucunun parametrelerini belirtir.The formal_parameter_list specifies the parameters of the indexer. Bir dizin oluşturucunun biçimsel parametre listesibir yönteme karşılıkgelir, ancak en az bir parametre belirtilmesi ve ref ve out parametre değiştiricilerine izin verilmemelidir.The formal parameter list of an indexer corresponds to that of a method (Method parameters), except that at least one parameter must be specified, and that the ref and out parameter modifiers are not permitted.

Bir dizin oluşturucunun türü ve formal_parameter_list başvurulan her bir tür, en azından dizin oluşturucunun kendisi (Erişilebilirlik kısıtlamaları) olarak erişilebilir olmalıdır.The type of an indexer and each of the types referenced in the formal_parameter_list must be at least as accessible as the indexer itself (Accessibility constraints).

Bir indexer_body bir erişimci gövdesinden veya bir _ifade gövdesinden*_ oluşabilir.An indexer_body may either consist of an accessor body _ or an _expression body*_. Bir erişimci gövdesinde, " { " ve "" belirteçlerinin içine alınması gereken _accessor_declarations *, } özelliğin erişimcileri (erişimcileri) bildirmek.In an accessor body, _accessor_declarations*, which must be enclosed in "{" and "}" tokens, declare the accessors (Accessors) of the property. Erişimciler, özelliği okuma ve yazma ile ilişkili yürütülebilir deyimleri belirler.The accessors specify the executable statements associated with reading and writing the property.

" => " İfadesinden sonra gelen ve noktalı virgülden oluşan bir ifade gövdesi E deyim gövdesine tam olarak eşdeğerdir { get { return E; } } ve bu nedenle yalnızca alıcı sonucunun tek bir ifade tarafından verildiği alıcı dizin oluşturucularının belirtilmesi için kullanılabilir.An expression body consisting of "=>" followed by an expression E and a semicolon is exactly equivalent to the statement body { get { return E; } }, and can therefore only be used to specify getter-only indexers where the result of the getter is given by a single expression.

Bir Dizin Oluşturucu öğesine erişmek için sözdizimi, bir dizi öğesiyle aynı olsa da, bir Dizin Oluşturucu öğesi değişken olarak sınıflandırılmaz.Even though the syntax for accessing an indexer element is the same as that for an array element, an indexer element is not classified as a variable. Bu nedenle, bir Dizin Oluşturucu öğesini bir ref veya bağımsız değişken olarak geçirmek mümkün değildir out .Thus, it is not possible to pass an indexer element as a ref or out argument.

Bir dizin oluşturucunun biçimsel parametre listesi, dizin oluşturucunun imzasını (imzalar ve aşırı yükleme) tanımlar.The formal parameter list of an indexer defines the signature (Signatures and overloading) of the indexer. Özellikle, bir dizin oluşturucunun imzası, resmi parametrelerinin sayısından ve türlerinden oluşur.Specifically, the signature of an indexer consists of the number and types of its formal parameters. Öğe türü ve biçimsel parametrelerinin adları, dizin oluşturucunun imzasının bir parçası değildir.The element type and names of the formal parameters are not part of an indexer's signature.

Bir dizin oluşturucunun imzası aynı sınıfta belirtilen diğer tüm dizin oluşturucularının imzalarından farklı olmalıdır.The signature of an indexer must differ from the signatures of all other indexers declared in the same class.

Dizin oluşturucular ve Özellikler kavram bakımından çok benzerdir, ancak aşağıdaki yollarla farklılık gösterir:Indexers and properties are very similar in concept, but differ in the following ways:

  • Bir özellik adıyla tanımlanır, ancak bir Dizin Oluşturucu imza tarafından tanımlanır.A property is identified by its name, whereas an indexer is identified by its signature.
  • Bir özelliğe simple_name (basit adlar) veya bir member_access (üye erişimi) üzerinden erişilir, ancak bir Dizin Oluşturucu öğesine bir element_access (Dizin Oluşturucu erişimi) üzerinden erişilir.A property is accessed through a simple_name (Simple names) or a member_access (Member access), whereas an indexer element is accessed through an element_access (Indexer access).
  • Bir özellik static üye olabilir, ancak bir Dizin Oluşturucu her zaman bir örnek üyesidir.A property can be a static member, whereas an indexer is always an instance member.
  • getBir özelliğin erişimcisi parametresi olmayan bir yönteme karşılık gelir, ancak bir get dizin oluşturucunun erişimcisi, Dizin oluşturucudaki aynı biçimsel parametre listesine sahip bir yönteme karşılık gelir.A get accessor of a property corresponds to a method with no parameters, whereas a get accessor of an indexer corresponds to a method with the same formal parameter list as the indexer.
  • setBir özelliğin erişimcisi adlı tek parametreli bir yönteme karşılık gelir value , ancak bir set dizin oluşturucunun erişimcisi, Dizin Oluşturucu ile aynı biçimsel parametre listesine sahip bir yönteme karşılık gelir ve adlı ek bir parametredir value .A set accessor of a property corresponds to a method with a single parameter named value, whereas a set accessor of an indexer corresponds to a method with the same formal parameter list as the indexer, plus an additional parameter named value.
  • Bir Dizin Oluşturucu erişimcisinin bir Dizin Oluşturucu parametresiyle aynı ada sahip yerel bir değişken bildirmesi için derleme zamanı hatası.It is a compile-time error for an indexer accessor to declare a local variable with the same name as an indexer parameter.
  • Geçersiz kılan özellik bildiriminde, devralınan özelliğe sözdizimi kullanılarak erişilir base.P , burada P özellik adıdır.In an overriding property declaration, the inherited property is accessed using the syntax base.P, where P is the property name. Geçersiz kılan bir Dizin Oluşturucu bildiriminde, devralınan dizin oluşturucuya sözdizimi kullanılarak erişilir; base[E] burada, E ifadelerin virgülle ayrılmış bir listesi bulunur.In an overriding indexer declaration, the inherited indexer is accessed using the syntax base[E], where E is a comma separated list of expressions.
  • "Otomatik olarak uygulanan Dizin Oluşturucu" kavramı yoktur.There is no concept of an "automatically implemented indexer". Noktalı olmayan, dış olmayan ve olmayan bir dizinleyiciye sahip bir hata.It is an error to have a non-abstract, non-external indexer with semicolon accessors.

Bu farklılıklardan farklı olarak, erişimciler ve Otomatik uygulanan özellikleri tanımlanan tüm kurallar, Dizin Oluşturucu erişimcileri ve özellik erişimcileri için de geçerlidir.Aside from these differences, all rules defined in Accessors and Automatically implemented properties apply to indexer accessors as well as to property accessors.

Bir Dizin Oluşturucu bildirimi bir extern değiştirici içerdiğinde, Dizin Oluşturucu bir *dış Dizin Oluşturucu _ olarak kabul edilir.When an indexer declaration includes an extern modifier, the indexer is said to be an *external indexer _. Bir dış Dizin Oluşturucu bildirimi gerçek uygulama sağladığından, her bir _accessor_declarations * noktalı virgül oluşur.Because an external indexer declaration provides no actual implementation, each of its _accessor_declarations* consists of a semicolon.

Aşağıdaki örnek, BitArray bit dizisindeki tek tek bitlerin erişimine yönelik bir Dizin Oluşturucu uygulayan bir sınıf bildirir.The example below declares a BitArray class that implements an indexer for accessing the individual bits in the bit array.

using System;

class BitArray
{
    int[] bits;
    int length;

    public BitArray(int length) {
        if (length < 0) throw new ArgumentException();
        bits = new int[((length - 1) >> 5) + 1];
        this.length = length;
    }

    public int Length {
        get { return length; }
    }

    public bool this[int index] {
        get {
            if (index < 0 || index >= length) {
                throw new IndexOutOfRangeException();
            }
            return (bits[index >> 5] & 1 << index) != 0;
        }
        set {
            if (index < 0 || index >= length) {
                throw new IndexOutOfRangeException();
            }
            if (value) {
                bits[index >> 5] |= 1 << index;
            }
            else {
                bits[index >> 5] &= ~(1 << index);
            }
        }
    }
}

Sınıfının bir örneği BitArray , buna karşılık gelen bool[] (ilk değeri ikinci bir baytlık bir bit yerine yalnızca bir bit kapladığından) büyük ölçüde daha az bellek tüketir, ancak aynı işlemlere bir ile aynı şekilde izin verir bool[] .An instance of the BitArray class consumes substantially less memory than a corresponding bool[] (since each value of the former occupies only one bit instead of the latter's one byte), but it permits the same operations as a bool[].

Aşağıdaki CountPrimes sınıf, BitArray 1 ile verilen bir maksimum arasındaki primün sayısını hesaplamak için bir ve klasik "sıya" algoritmasını kullanır:The following CountPrimes class uses a BitArray and the classical "sieve" algorithm to compute the number of primes between 1 and a given maximum:

class CountPrimes
{
    static int Count(int max) {
        BitArray flags = new BitArray(max + 1);
        int count = 1;
        for (int i = 2; i <= max; i++) {
            if (!flags[i]) {
                for (int j = i * 2; j <= max; j += i) flags[j] = true;
                count++;
            }
        }
        return count;
    }

    static void Main(string[] args) {
        int max = int.Parse(args[0]);
        int count = Count(max);
        Console.WriteLine("Found {0} primes between 1 and {1}", count, max);
    }
}

Öğesinin öğelerine erişim sözdiziminin BitArray tam olarak bir ile aynı olduğunu unutmayın bool[] .Note that the syntax for accessing elements of the BitArray is precisely the same as for a bool[].

Aşağıdaki örnek, iki parametreli bir dizin oluşturucuya sahip bir 26 * 10 Grid sınıfı gösterir.The following example shows a 26 * 10 grid class that has an indexer with two parameters. İlk parametrenin A-Z aralığında bir büyük veya küçük harf olması gerekir ve ikincisinin 0-9 aralığında bir tamsayı olması gerekir.The first parameter is required to be an upper- or lowercase letter in the range A-Z, and the second is required to be an integer in the range 0-9.

using System;

class Grid
{
    const int NumRows = 26;
    const int NumCols = 10;

    int[,] cells = new int[NumRows, NumCols];

    public int this[char c, int col] {
        get {
            c = Char.ToUpper(c);
            if (c < 'A' || c > 'Z') {
                throw new ArgumentException();
            }
            if (col < 0 || col >= NumCols) {
                throw new IndexOutOfRangeException();
            }
            return cells[c - 'A', col];
        }

        set {
            c = Char.ToUpper(c);
            if (c < 'A' || c > 'Z') {
                throw new ArgumentException();
            }
            if (col < 0 || col >= NumCols) {
                throw new IndexOutOfRangeException();
            }
            cells[c - 'A', col] = value;
        }
    }
}

Dizin Oluşturucu aşırı yüklemesiIndexer overloading

Dizin Oluşturucu aşırı yükleme çözümleme kuralları tür çıkarımı' nda açıklanmıştır.The indexer overload resolution rules are described in Type inference.

İşleçlerOperators

*İşleci _, sınıfının örneklerine uygulanabilen bir ifade işlecinin anlamını tanımlayan bir üyedir.An *operator _ is a member that defines the meaning of an expression operator that can be applied to instances of the class. İşleçler _operator_declaration * s kullanılarak bildirilmiştir:Operators are declared using _operator_declaration*s:

operator_declaration
    : attributes? operator_modifier+ operator_declarator operator_body
    ;

operator_modifier
    : 'public'
    | 'static'
    | 'extern'
    | operator_modifier_unsafe
    ;

operator_declarator
    : unary_operator_declarator
    | binary_operator_declarator
    | conversion_operator_declarator
    ;

unary_operator_declarator
    : type 'operator' overloadable_unary_operator '(' type identifier ')'
    ;

overloadable_unary_operator
    : '+' | '-' | '!' | '~' | '++' | '--' | 'true' | 'false'
    ;

binary_operator_declarator
    : type 'operator' overloadable_binary_operator '(' type identifier ',' type identifier ')'
    ;

overloadable_binary_operator
    : '+'   | '-'   | '*'   | '/'   | '%'   | '&'   | '|'   | '^'   | '<<'
    | right_shift | '=='  | '!='  | '>'   | '<'   | '>='  | '<='
    ;

conversion_operator_declarator
    : 'implicit' 'operator' type '(' type identifier ')'
    | 'explicit' 'operator' type '(' type identifier ')'
    ;

operator_body
    : block
    | '=>' expression ';'
    | ';'
    ;

Fazla yüklenebilir operatörlerin üç kategorisi vardır: Birli İşleçler (Birli İşleçler), ikili Işleçler (ikili işleçler) ve dönüştürme işleçleri (dönüştürme işleçleri).There are three categories of overloadable operators: Unary operators (Unary operators), binary operators (Binary operators), and conversion operators (Conversion operators).

Operator_body noktalı virgül, deyim gövdesi _ veya bir _ifade gövdesi*.The operator_body is either a semicolon, a statement body _ or an _expression body*. Deyim gövdesi, işleç çağrıldığında yürütülecek deyimleri belirten bir _block * oluşur.A statement body consists of a _block*, which specifies the statements to execute when the operator is invoked. Blok , Yöntem gövdesindeaçıklanan değer döndüren yöntemlere yönelik kurallara uymalıdır.The block must conform to the rules for value-returning methods described in Method body. Bir ifade gövdesi => , sonrasında bir ifade ve noktalı virgül ile oluşur ve işleç çağrıldığında gerçekleştirilecek tek bir ifadeyi gösterir.An expression body consists of => followed by an expression and a semicolon, and denotes a single expression to perform when the operator is invoked.

externİşleçler için operator_body yalnızca noktalı virgülden oluşur.For extern operators, the operator_body consists simply of a semicolon. Diğer tüm işleçler için operator_body bir blok gövdesi ya da bir ifade gövdesidir.For all other operators, the operator_body is either a block body or an expression body.

Tüm işleç bildirimleri için aşağıdaki kurallar geçerlidir:The following rules apply to all operator declarations:

  • İşleç bildirimi hem a hem de public static değiştirici içermelidir.An operator declaration must include both a public and a static modifier.
  • Bir işlecin parametre (ler) i değer parametreleri olmalıdır (değer parametreleri).The parameter(s) of an operator must be value parameters (Value parameters). Bu, bir işleç bildirimi için veya parametreleri belirtmek üzere derleme zamanı hatasıdır ref out .It is a compile-time error for an operator declaration to specify ref or out parameters.
  • Bir işlecin imzası (Birli İşleçler, ikili işleçler, dönüştürme işleçleri) aynı sınıfta belirtilen diğer tüm işleçlerin imzalarından farklı olmalıdır.The signature of an operator (Unary operators, Binary operators, Conversion operators) must differ from the signatures of all other operators declared in the same class.
  • Bir işleç bildiriminde başvurulan tüm türlerin en az işlecin kendisi (Erişilebilirlik kısıtlamaları) olarak erişilebilir olması gerekir.All types referenced in an operator declaration must be at least as accessible as the operator itself (Accessibility constraints).
  • Aynı değiştiricinin bir operatör bildiriminde birden çok kez görünmesi bir hatadır.It is an error for the same modifier to appear multiple times in an operator declaration.

Her operatör kategorisi, aşağıdaki bölümlerde açıklandığı gibi ek kısıtlamalar uygular.Each operator category imposes additional restrictions, as described in the following sections.

Diğer Üyeler gibi, bir temel sınıfta belirtilen operatörler türetilmiş sınıflar tarafından devralınır.Like other members, operators declared in a base class are inherited by derived classes. İşleç bildirimleri, işlecin, işlecin imzasına katılması için bildirildiği sınıf veya yapının her zaman gerektirdiğinden, bir temel sınıfta belirtilen bir işleci gizlemek için türetilmiş sınıfta belirtilen bir operatör mümkün değildir.Because operator declarations always require the class or struct in which the operator is declared to participate in the signature of the operator, it is not possible for an operator declared in a derived class to hide an operator declared in a base class. Bu nedenle, new değiştirici hiçbir şekilde gerekli değildir ve bu nedenle bir işleç bildiriminde hiçbir izin verilmez.Thus, the new modifier is never required, and therefore never permitted, in an operator declaration.

Birli ve ikili işleçlerle ilgili ek bilgiler, işleçlerindebulunabilir.Additional information on unary and binary operators can be found in Operators.

Dönüştürme işleçleri hakkında ek bilgi, Kullanıcı tanımlı dönüştürmelerdebulunabilir.Additional information on conversion operators can be found in User-defined conversions.

Birli işleçlerUnary operators

Aşağıdaki kurallar, T işleç bildirimini içeren sınıfın veya yapının örnek türünü belirten birli operatör bildirimleri için geçerlidir:The following rules apply to unary operator declarations, where T denotes the instance type of the class or struct that contains the operator declaration:

  • Birli + , - , ! , veya ~ işleç türünde tek bir parametre almalıdır, ya da T herhangi bir T? tür döndürebilir.A unary +, -, !, or ~ operator must take a single parameter of type T or T? and can return any type.
  • Birli ++ or -- işleci, türünde tek bir parametre almalıdır T T? ve aynı türü veya ondan türetilmiş bir türü döndürmelidir.A unary ++ or -- operator must take a single parameter of type T or T? and must return that same type or a type derived from it.
  • Birli true veya false işleç türünde tek bir parametre almalıdır T T? ve türü döndürmelidir bool .A unary true or false operator must take a single parameter of type T or T? and must return type bool.

Birli işlecin imzası, işleç belirtecinden (,,,,, + , - ! ~ ++ -- true veya false ) ve tek biçimsel parametrenin türünden oluşur.The signature of a unary operator consists of the operator token (+, -, !, ~, ++, --, true, or false) and the type of the single formal parameter. Dönüş türü birli işlecin imzasının bir parçası değildir, ya da biçimsel parametrenin adıdır.The return type is not part of a unary operator's signature, nor is the name of the formal parameter.

trueVe false Birli İşleçler çift yönlü bildirim gerektirir.The true and false unary operators require pair-wise declaration. Bir sınıf bu işleçlerden birini diğeri de bildirmeksizin bildirirse bir derleme zamanı hatası oluşur.A compile-time error occurs if a class declares one of these operators without also declaring the other. trueVe false Işleçleri, Kullanıcı tanımlı Koşullu mantıksal işleçler ve Boole ifadelerindedaha ayrıntılı olarak açıklanmıştır.The true and false operators are described further in User-defined conditional logical operators and Boolean expressions.

Aşağıdaki örnek, bir operator ++ tamsayı vektör sınıfı için bir uygulama ve sonraki kullanımını gösterir:The following example shows an implementation and subsequent usage of operator ++ for an integer vector class:

public class IntVector
{
    public IntVector(int length) {...}

    public int Length {...}                 // read-only property

    public int this[int index] {...}        // read-write indexer

    public static IntVector operator ++(IntVector iv) {
        IntVector temp = new IntVector(iv.Length);
        for (int i = 0; i < iv.Length; i++)
            temp[i] = iv[i] + 1;
        return temp;
    }
}

class Test
{
    static void Main() {
        IntVector iv1 = new IntVector(4);    // vector of 4 x 0
        IntVector iv2;

        iv2 = iv1++;    // iv2 contains 4 x 0, iv1 contains 4 x 1
        iv2 = ++iv1;    // iv2 contains 4 x 2, iv1 contains 4 x 2
    }
}

İşleç yönteminin, sonek artırma ve azaltma işleçleri (sonekartışı ve azaltma işleçleri) ve ön ek artırma ve azaltma Işleçleri (önek artırma ve azaltma işleçleri) gibi, işlenene 1 eklenerek üretilen değeri nasıl döndürdüğünü aklınızda.Note how the operator method returns the value produced by adding 1 to the operand, just like the postfix increment and decrement operators (Postfix increment and decrement operators), and the prefix increment and decrement operators (Prefix increment and decrement operators). C++ ' dan farklı olarak, bu yöntemin işleneninin değerini doğrudan değiştirmesi gerekmez.Unlike in C++, this method need not modify the value of its operand directly. Aslında, işlenen değerini değiştirmek, sonek artışı işlecinin standart semantiğini ihlal ediyor.In fact, modifying the operand value would violate the standard semantics of the postfix increment operator.

İkili işleçlerBinary operators

Aşağıdaki kurallar, T işleç bildirimini içeren sınıfın veya yapının örnek türünü belirten ikili işleç bildirimleri için geçerlidir:The following rules apply to binary operator declarations, where T denotes the instance type of the class or struct that contains the operator declaration:

  • Binary olmayan bir operatör iki parametre almalıdır, en az bir, türü T veya olmalıdır T? ve herhangi bir tür döndürebilir.A binary non-shift operator must take two parameters, at least one of which must have type T or T?, and can return any type.
  • Bir ikili << veya >> işleç iki parametre almalıdır, ilki türü T veya T? , ikincisinin türü int veya olmalıdır int? ve herhangi bir tür döndürebilir.A binary << or >> operator must take two parameters, the first of which must have type T or T? and the second of which must have type int or int?, and can return any type.

Bir ikili işlecinin imzası, işleç belirtecinden (,,,,,,,,,,,,, + - * / % & | ^ << >> == != > < , >= veya <= ) ve iki biçimsel parametrenin türlerinden oluşur.The signature of a binary operator consists of the operator token (+, -, *, /, %, &, |, ^, <<, >>, ==, !=, >, <, >=, or <=) and the types of the two formal parameters. Dönüş türü ve biçimsel parametrelerin adları bir ikili işlecin imzasının parçası değil.The return type and the names of the formal parameters are not part of a binary operator's signature.

Belirli ikili işleçler çift yönlü bildirim gerektirir.Certain binary operators require pair-wise declaration. Bir çiftin her iki işlecinin her bildirimi için, çiftin diğer işlecinin eşleşen bir bildirimi olması gerekir.For every declaration of either operator of a pair, there must be a matching declaration of the other operator of the pair. İki işleç bildirimi aynı dönüş türüne ve her parametre için aynı türe sahip olduklarında eşleşir.Two operator declarations match when they have the same return type and the same type for each parameter. Aşağıdaki işleçler çift yönlü bildirim gerektirir:The following operators require pair-wise declaration:

  • operator == ve operator !=operator == and operator !=
  • operator > ve operator <operator > and operator <
  • operator >= ve operator <=operator >= and operator <=

Dönüştürme işleçleriConversion operators

Bir dönüştürme işleci bildirimi, önceden tanımlanmış örtük ve açık dönüştürmeleri genişleten Kullanıcı tanımlı bir dönüştürme (Kullanıcı tanımlı dönüştürmeler) sunar.A conversion operator declaration introduces a user-defined conversion (User-defined conversions) which augments the pre-defined implicit and explicit conversions.

Anahtar sözcüğünü içeren bir dönüştürme işleci bildirimi, implicit Kullanıcı tanımlı bir örtük dönüştürmeyi tanıtır.A conversion operator declaration that includes the implicit keyword introduces a user-defined implicit conversion. Örtük dönüştürmeler işlev üyesi etkinleştirmeleri, atama ifadeleri ve atamalar dahil çeşitli durumlarda gerçekleşebilir.Implicit conversions can occur in a variety of situations, including function member invocations, cast expressions, and assignments. Bu, örtük dönüştürmelerdedaha ayrıntılı olarak açıklanmıştır.This is described further in Implicit conversions.

Anahtar sözcüğünü içeren bir dönüştürme işleci bildirimi, explicit Kullanıcı tanımlı bir açık dönüştürme sunar.A conversion operator declaration that includes the explicit keyword introduces a user-defined explicit conversion. Dönüştürme ifadelerinde açık dönüştürmeler gerçekleşebilir ve Açık dönüştürmelerdedaha ayrıntılı olarak açıklanmıştır.Explicit conversions can occur in cast expressions, and are described further in Explicit conversions.

Bir dönüştürme işleci, dönüştürme işlecinin parametre türü ile belirtilen bir kaynak türünden, dönüştürme işlecinin dönüş türü tarafından belirtilen bir hedef türüne dönüştürülür.A conversion operator converts from a source type, indicated by the parameter type of the conversion operator, to a target type, indicated by the return type of the conversion operator.

Belirli bir kaynak türü S ve hedef türü için T , S T null yapılabilir türler varsa, S0 kendi temel türlerine izin verin ve bunlara T0 başvurur, aksi takdirde ve S0 T0 S sırasıyla eşittir T .For a given source type S and target type T, if S or T are nullable types, let S0 and T0 refer to their underlying types, otherwise S0 and T0 are equal to S and T respectively. Bir sınıf veya yapının, S T yalnızca aşağıdakilerin tümü doğru olduğunda bir kaynak türünden hedef türüne dönüştürme bildirmesine izin verilir:A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true:

  • S0 ve T0 farklı türlerdir.S0 and T0 are different types.
  • S0Ya da T0 işleç bildiriminin gerçekleştiği sınıf veya yapı türüdür.Either S0 or T0 is the class or struct type in which the operator declaration takes place.
  • Ne S0 ne de T0 bir interface_type.Neither S0 nor T0 is an interface_type.
  • Kullanıcı tanımlı dönüştürmeler hariç olmak üzere dönüştürme, ' den ' e veya ' den ' a arasında bulunmaz S T T S .Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

Bu kuralların amaçları doğrultusunda, veya ile ilişkili herhangi bir tür parametresi S , T diğer türlerle devralma ilişkisine sahip olmayan benzersiz türler olarak kabul edilir ve bu tür parametrelerinin herhangi bir kısıtlaması yok sayılır.For the purposes of these rules, any type parameters associated with S or T are considered to be unique types that have no inheritance relationship with other types, and any constraints on those type parameters are ignored.

ÖrnekteIn the example

class C<T> {...}

class D<T>: C<T>
{
    public static implicit operator C<int>(D<T> value) {...}      // Ok
    public static implicit operator C<string>(D<T> value) {...}   // Ok
    public static implicit operator C<T>(D<T> value) {...}        // Error
}

ilk iki işleç bildirimi izin verilir çünkü, .3, ve sırasıyla Dizin oluşturucular, T int string hiçbir ilişki olmadan benzersiz türler olarak kabul edilir.the first two operator declarations are permitted because, for the purposes of Indexers.3, T and int and string respectively are considered unique types with no relationship. Ancak, üçüncü işleç bir hatadır çünkü C<T> öğesinin temel sınıfı D<T> .However, the third operator is an error because C<T> is the base class of D<T>.

İkinci kuraldan, bir dönüştürme işlecinin, işlecin bildirildiği sınıf veya yapı türünden ya da türüne dönüştürülmesi gerekir.From the second rule it follows that a conversion operator must convert either to or from the class or struct type in which the operator is declared. Örneğin, bir sınıf veya yapı türü, ' den ' a C ve kaynağından öğesine dönüştürme tanımlamak için mümkündür C int int C int bool .For example, it is possible for a class or struct type C to define a conversion from C to int and from int to C, but not from int to bool.

Önceden tanımlanmış bir dönüştürmeyi doğrudan yeniden tanımlamak mümkün değildir.It is not possible to directly redefine a pre-defined conversion. Bu nedenle, object örtük ve açık dönüştürmeler diğer tüm türler arasında zaten mevcut olduğundan, dönüştürme işleçleri veya ' den ' a dönüştürme yapılamaz object .Thus, conversion operators are not allowed to convert from or to object because implicit and explicit conversions already exist between object and all other types. Benzer şekilde, bir dönüştürme daha sonra zaten mevcut olduğundan, bir dönüştürmenin kaynağı veya hedef türleri diğerinin temel türü olamaz.Likewise, neither the source nor the target types of a conversion can be a base type of the other, since a conversion would then already exist.

Ancak, belirli tür bağımsız değişkenleri için önceden tanımlanmış dönüştürmeler olarak zaten var olan dönüştürmeleri belirtmek üzere genel türlerde işleçler bildirmek mümkündür.However, it is possible to declare operators on generic types that, for particular type arguments, specify conversions that already exist as pre-defined conversions. ÖrnekteIn the example

struct Convertible<T>
{
    public static implicit operator Convertible<T>(T value) {...}
    public static explicit operator T(Convertible<T> value) {...}
}

türü object için tür bağımsız değişkeni olarak belirtildiğinde T , İkinci işleç zaten var olan bir dönüştürme (örtük olarak) ve bu nedenle bir açık, her türden türden bir dönüşüm bulunur object ) bildirir.when type object is specified as a type argument for T, the second operator declares a conversion that already exists (an implicit, and therefore also an explicit, conversion exists from any type to type object).

İki tür arasında önceden tanımlanmış bir dönüştürmenin mevcut olduğu durumlarda, bu türler arasındaki Kullanıcı tanımlı dönüştürmeler yok sayılır.In cases where a pre-defined conversion exists between two types, any user-defined conversions between those types are ignored. Özellikle:Specifically:

  • Tür türünden bir önceden tanımlanmış örtük dönüştürme (örtük dönüştürmeler) varsa S T , ' den ' e kadar Kullanıcı tanımlı dönüştürmeler (örtük veya açık) yok S T sayılır.If a pre-defined implicit conversion (Implicit conversions) exists from type S to type T, all user-defined conversions (implicit or explicit) from S to T are ignored.
  • Türünden türüne önceden tanımlanmış bir açık dönüştürme (Açık dönüştürmeler) varsa S T , öğesinden öğesine Kullanıcı tanımlı açık dönüştürmeler yok S T sayılır.If a pre-defined explicit conversion (Explicit conversions) exists from type S to type T, any user-defined explicit conversions from S to T are ignored. BunaFurthermore:

TBir arabirim türü ise, ' den ' e Kullanıcı tanımlı örtük S dönüştürmeler T yok sayılır.If T is an interface type, user-defined implicit conversions from S to T are ignored.

Aksi takdirde, ' den ' e Kullanıcı tanımlı örtük dönüştürmeler S T hala göz önünde bulundurulacaktır.Otherwise, user-defined implicit conversions from S to T are still considered.

Tüm türler için object , yukarıdaki tür tarafından belirtilen işleçler Convertible<T> önceden tanımlanmış dönüşümlerle çakışmaz.For all types but object, the operators declared by the Convertible<T> type above do not conflict with pre-defined conversions. Örnek:For example:

void F(int i, Convertible<int> n) {
    i = n;                          // Error
    i = (int)n;                     // User-defined explicit conversion
    n = i;                          // User-defined implicit conversion
    n = (Convertible<int>)i;        // User-defined implicit conversion
}

Ancak, tür object , önceden tanımlı dönüştürmeler için Kullanıcı tanımlı dönüştürmeleri her durumda gizleyin, ancak bir:However, for type object, pre-defined conversions hide the user-defined conversions in all cases but one:

void F(object o, Convertible<object> n) {
    o = n;                         // Pre-defined boxing conversion
    o = (object)n;                 // Pre-defined boxing conversion
    n = o;                         // User-defined implicit conversion
    n = (Convertible<object>)o;    // Pre-defined unboxing conversion
}

Kullanıcı tanımlı dönüştürmelerde veya interface_type s 'ye dönüştürme yapılamaz.User-defined conversions are not allowed to convert from or to interface_type s. Özellikle, bu kısıtlama, bir interface_type dönüştürülürken Kullanıcı tanımlı dönüştürmeler olmamasını ve bir interface_type dönüştürmenin yalnızca, belirtilen interface_type gerçekten uyguladığı durumlarda başarılı olmasını sağlar.In particular, this restriction ensures that no user-defined transformations occur when converting to an interface_type, and that a conversion to an interface_type succeeds only if the object being converted actually implements the specified interface_type.

Bir dönüştürme işlecinin imzası, kaynak türü ve hedef türünden oluşur.The signature of a conversion operator consists of the source type and the target type. (Bunun, dönüş türünün imzaya katıldığı tek üye formu olduğunu unutmayın.) implicit explicit Bir dönüştürme işlecinin veya sınıflandırması, işlecin imzasının bir parçası değil.(Note that this is the only form of member for which the return type participates in the signature.) The implicit or explicit classification of a conversion operator is not part of the operator's signature. Bu nedenle, bir sınıf veya yapı implicit explicit aynı kaynak ve hedef türlerine sahip hem hem de bir dönüştürme işleci bildiremez.Thus, a class or struct cannot declare both an implicit and an explicit conversion operator with the same source and target types.

Genel olarak, Kullanıcı tanımlı örtük dönüştürmeler hiçbir şekilde özel durum oluşturmaz ve hiçbir bilgi kaybedilmez.In general, user-defined implicit conversions should be designed to never throw exceptions and never lose information. Kullanıcı tanımlı bir dönüştürme özel durumlara (örneğin, kaynak bağımsız değişkeni aralık dışında) veya bilgi kaybına (yüksek sıralı bitleri atma gibi) izin verebileceğinden, bu dönüştürme açık bir dönüştürme olarak tanımlanmalıdır.If a user-defined conversion can give rise to exceptions (for example, because the source argument is out of range) or loss of information (such as discarding high-order bits), then that conversion should be defined as an explicit conversion.

ÖrnekteIn the example

using System;

public struct Digit
{
    byte value;

    public Digit(byte value) {
        if (value < 0 || value > 9) throw new ArgumentException();
        this.value = value;
    }

    public static implicit operator byte(Digit d) {
        return d.value;
    }

    public static explicit operator Digit(byte b) {
        return new Digit(b);
    }
}

' dan ' Digit e dönüştürme byte örtük bir şekilde özel durum oluşturmaz veya bilgi kaybettiğinden, ancak ' den byte ' Digit Digit ın yalnızca olası değerlerinin bir alt kümesini temsil ettiğinden, öğesinden dönüşümü açıktır byte .the conversion from Digit to byte is implicit because it never throws exceptions or loses information, but the conversion from byte to Digit is explicit since Digit can only represent a subset of the possible values of a byte.

Örnek oluşturucularInstance constructors

*Örnek Oluşturucusu _, bir sınıfın örneğini başlatmak için gereken eylemleri uygulayan bir üyesidir.An *instance constructor _ is a member that implements the actions required to initialize an instance of a class. Örnek oluşturucular _constructor_declaration * s kullanılarak bildirilmiştir:Instance constructors are declared using _constructor_declaration*s:

constructor_declaration
    : attributes? constructor_modifier* constructor_declarator constructor_body
    ;

constructor_modifier
    : 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | 'extern'
    | constructor_modifier_unsafe
    ;

constructor_declarator
    : identifier '(' formal_parameter_list? ')' constructor_initializer?
    ;

constructor_initializer
    : ':' 'base' '(' argument_list? ')'
    | ':' 'this' '(' argument_list? ')'
    ;

constructor_body
    : block
    | ';'
    ;

Constructor_declaration bir dizi öznitelik (öznitelik), dört erişim değiştiricisinin geçerli bir birleşimi (erişim değiştiricileri) ve bir extern (dış Yöntemler) değiştiricisi içerebilir.A constructor_declaration may include a set of attributes (Attributes), a valid combination of the four access modifiers (Access modifiers), and an extern (External methods) modifier. Oluşturucu bildiriminin aynı değiştiriciyi birden çok kez içerme izni yoktur.A constructor declaration is not permitted to include the same modifier multiple times.

Bir constructor_declarator tanımlayıcısı , örnek oluşturucusunun bildirildiği sınıfa ad vermelidir.The identifier of a constructor_declarator must name the class in which the instance constructor is declared. Başka bir ad belirtilmişse, derleme zamanı hatası oluşur.If any other name is specified, a compile-time error occurs.

Örnek oluşturucusunun isteğe bağlı formal_parameter_list , yöntemin formal_parameter_list aynı kurallara tabidir (Yöntemler).The optional formal_parameter_list of an instance constructor is subject to the same rules as the formal_parameter_list of a method (Methods). Biçimsel parametre listesi bir örnek oluşturucusunun imzasını (imzalar ve aşırı yükleme) tanımlar ve aşırı yükleme çözümünün (tür çıkarımı) bir çağrıdaki belirli bir örnek oluşturucusunu seçtiği işlemi yönetir.The formal parameter list defines the signature (Signatures and overloading) of an instance constructor and governs the process whereby overload resolution (Type inference) selects a particular instance constructor in an invocation.

Bir örnek oluşturucusunun formal_parameter_list başvuruda bulunulan türlerin her biri, oluşturucunun kendisi (Erişilebilirlik kısıtlamaları) olarak en az erişilebilir olmalıdır.Each of the types referenced in the formal_parameter_list of an instance constructor must be at least as accessible as the constructor itself (Accessibility constraints).

İsteğe bağlı constructor_initializer , bu örnek oluşturucusunun constructor_body verilen deyimleri yürütmeden önce çağrılacak başka bir örnek Oluşturucu belirtir.The optional constructor_initializer specifies another instance constructor to invoke before executing the statements given in the constructor_body of this instance constructor. Bu, Oluşturucu başlatıcılardadaha ayrıntılı olarak açıklanmıştır.This is described further in Constructor initializers.

Bir Oluşturucu bildirimi bir değiştirici içerdiğinde extern , Oluşturucu bir *dış Oluşturucu _ olarak kabul edilir.When a constructor declaration includes an extern modifier, the constructor is said to be an *external constructor _. Bir dış Oluşturucu bildirimi gerçek uygulama olmadığından, _constructor_body * noktalı virgülden oluşur.Because an external constructor declaration provides no actual implementation, its _constructor_body* consists of a semicolon. Diğer tüm oluşturucular için constructor_body , sınıfın yeni bir örneğini başlatmak için deyimleri belirten bir bloğundan oluşur.For all other constructors, the constructor_body consists of a block which specifies the statements to initialize a new instance of the class. Bu, void dönüş türü (Yöntem gövdesi) olan bir örnek yönteminin bloğuna tam olarak karşılık gelir.This corresponds exactly to the block of an instance method with a void return type (Method body).

Örnek oluşturucular devralınmaz.Instance constructors are not inherited. Bu nedenle, bir sınıf sınıf içinde gerçekten bildirilenler dışında bir örnek Oluşturucu içermez.Thus, a class has no instance constructors other than those actually declared in the class. Bir sınıf örnek Oluşturucu bildirimleri içermiyorsa, varsayılan bir örnek Oluşturucu otomatik olarak sağlanır (Varsayılan oluşturucular).If a class contains no instance constructor declarations, a default instance constructor is automatically provided (Default constructors).

Örnek oluşturucular object_creation_expression s (nesne oluşturma ifadeleri) ve constructor_initializer s aracılığıyla çağrılır.Instance constructors are invoked by object_creation_expression s (Object creation expressions) and through constructor_initializer s.

Oluşturucu başlatıcılarıConstructor initializers

Tüm örnek oluşturucular (sınıf dışındakiler hariç object ), constructor_body hemen öncesine başka bir örnek oluşturucusunun bir çağrılmasını dolaylı olarak içerir.All instance constructors (except those for class object) implicitly include an invocation of another instance constructor immediately before the constructor_body. Örtük olarak çağrılacak Oluşturucu constructor_initializer belirlenir:The constructor to implicitly invoke is determined by the constructor_initializer:

  • Formun bir örnek Oluşturucu Başlatıcısı base(argument_list) veya base() doğrudan taban sınıftan çağrılabilir bir örnek oluşturucusunun oluşmasına neden olur.An instance constructor initializer of the form base(argument_list) or base() causes an instance constructor from the direct base class to be invoked. Bu Oluşturucu, varsa argument_list ve aşırı yüklemeçözümlemesi çözüm kuralları kullanılarak seçilir.That constructor is selected using argument_list if present and the overload resolution rules of Overload resolution. Aday örnek oluşturucular kümesi, doğrudan Taban sınıfında yer alan tüm erişilebilir örnek oluşturuculardan veya doğrudan temel sınıfta hiçbir örnek Oluşturucu bildirilmemiş ise varsayılan oluşturucuda (Varsayılan oluşturucular) oluşur.The set of candidate instance constructors consists of all accessible instance constructors contained in the direct base class, or the default constructor (Default constructors), if no instance constructors are declared in the direct base class. Bu küme boşsa veya tek bir en iyi örnek Oluşturucu tanımlanamıyorsa, bir derleme zamanı hatası oluşur.If this set is empty, or if a single best instance constructor cannot be identified, a compile-time error occurs.
  • Formun bir örnek Oluşturucu Başlatıcısı this(argument-list) veya this() sınıfın kendisinden bir örnek oluşturucusunun çağrılmasını sağlar.An instance constructor initializer of the form this(argument-list) or this() causes an instance constructor from the class itself to be invoked. Oluşturucu, varsa argument_list ve aşırı yüklemeçözümlemesi çözüm kuralları kullanılarak seçilir.The constructor is selected using argument_list if present and the overload resolution rules of Overload resolution. Aday örnek oluşturucular kümesi, sınıfta belirtilen tüm erişilebilir örnek oluşturuculardan oluşur.The set of candidate instance constructors consists of all accessible instance constructors declared in the class itself. Bu küme boşsa veya tek bir en iyi örnek Oluşturucu tanımlanamıyorsa, bir derleme zamanı hatası oluşur.If this set is empty, or if a single best instance constructor cannot be identified, a compile-time error occurs. Bir örnek Oluşturucu bildirimi, oluşturucuyu çağıran bir Oluşturucu başlatıcısı içeriyorsa, bir derleme zamanı hatası oluşur.If an instance constructor declaration includes a constructor initializer that invokes the constructor itself, a compile-time error occurs.

Bir örnek oluşturucusunun Oluşturucu başlatıcısı yoksa, formun bir Oluşturucu Başlatıcısı base() örtülü olarak sağlanır.If an instance constructor has no constructor initializer, a constructor initializer of the form base() is implicitly provided. Bu nedenle, formun örnek Oluşturucu bildirimiThus, an instance constructor declaration of the form

C(...) {...}

tam olarak eşdeğerdiris exactly equivalent to

C(...): base() {...}

Örnek Oluşturucu bildiriminin formal_parameter_list tarafından verilen parametrelerin kapsamı, bu bildirimin Oluşturucu başlatıcısını içerir.The scope of the parameters given by the formal_parameter_list of an instance constructor declaration includes the constructor initializer of that declaration. Bu nedenle, bir Oluşturucu başlatıcısının, oluşturucunun parametrelerine erişmesine izin verilir.Thus, a constructor initializer is permitted to access the parameters of the constructor. Örnek:For example:

class A
{
    public A(int x, int y) {}
}

class B: A
{
    public B(int x, int y): base(x + y, x - y) {}
}

Örnek Oluşturucu Başlatıcısı oluşturulan örneğe erişemez.An instance constructor initializer cannot access the instance being created. Bu nedenle this , Oluşturucu başlatıcısının bağımsız değişken ifadesinde başvurulmasına yönelik derleme zamanı hatası, bir bağımsız değişken ifadesi için bir simple_name aracılığıyla bir örnek üyesine başvuru için derleme zamanı hatası olur.Therefore it is a compile-time error to reference this in an argument expression of the constructor initializer, as is it a compile-time error for an argument expression to reference any instance member through a simple_name.

Örnek değişken başlatıcılarıInstance variable initializers

Bir örnek oluşturucusunun bir Oluşturucu başlatıcısı olmadığında veya formun Oluşturucu başlatıcısı varsa base(...) , bu Oluşturucu kendi sınıfında bildirildiği örnek alanlarının variable_initializer s tarafından belirtilen başlatmaları dolaylı olarak gerçekleştirir.When an instance constructor has no constructor initializer, or it has a constructor initializer of the form base(...), that constructor implicitly performs the initializations specified by the variable_initializer s of the instance fields declared in its class. Bu, oluşturucuya girişte ve doğrudan temel sınıf oluşturucusunun örtük çağrılmasıyla önce yürütülen bir atama dizisine karşılık gelir.This corresponds to a sequence of assignments that are executed immediately upon entry to the constructor and before the implicit invocation of the direct base class constructor. Değişken başlatıcıları, sınıf bildiriminde göründükleri metin sırasına göre yürütülür.The variable initializers are executed in the textual order in which they appear in the class declaration.

Oluşturucu yürütmeConstructor execution

Değişken başlatıcıları atama ifadelerine dönüştürülür ve bu atama deyimleri, temel sınıf örneği oluşturucusunun çağrısından önce yürütülür.Variable initializers are transformed into assignment statements, and these assignment statements are executed before the invocation of the base class instance constructor. Bu sıralama, bu örneğe erişimi olan herhangi bir deyim yürütülmeden önce tüm örnek alanlarının değişken başlatıcılara göre başlatılmasını sağlar.This ordering ensures that all instance fields are initialized by their variable initializers before any statements that have access to that instance are executed.

Örnek verildiğindeGiven the example

using System;

class A
{
    public A() {
        PrintFields();
    }

    public virtual void PrintFields() {}
}

class B: A
{
    int x = 1;
    int y;

    public B() {
        y = -1;
    }

    public override void PrintFields() {
        Console.WriteLine("x = {0}, y = {1}", x, y);
    }
}

new B()öğesinin bir örneğini oluşturmak için kullanıldığında B , aşağıdaki çıktı üretilir:when new B() is used to create an instance of B, the following output is produced:

x = 1, y = 0

Değeri, x taban sınıf örneği Oluşturucusu çağrılmadan önce, değişken başlatıcısı yürütüldüğü için 1 ' dir.The value of x is 1 because the variable initializer is executed before the base class instance constructor is invoked. Ancak, y int öğesine atama, y taban sınıf oluşturucusu döndürülünceye kadar yürütülmediği için, değeri 0 ' dır (varsayılan değeri).However, the value of y is 0 (the default value of an int) because the assignment to y is not executed until after the base class constructor returns.

Örnek değişken başlatıcıları ve Oluşturucu başlatıcıları, constructor_body önce otomatik olarak eklenen deyimler olarak düşünmek yararlıdır.It is useful to think of instance variable initializers and constructor initializers as statements that are automatically inserted before the constructor_body. ÖrnekteThe example

using System;
using System.Collections;

class A
{
    int x = 1, y = -1, count;

    public A() {
        count = 0;
    }

    public A(int n) {
        count = n;
    }
}

class B: A
{
    double sqrt2 = Math.Sqrt(2.0);
    ArrayList items = new ArrayList(100);
    int max;

    public B(): this(100) {
        items.Add("default");
    }

    public B(int n): base(n - 1) {
        max = n;
    }
}

çeşitli değişken başlatıcıları içerir; Ayrıca, her iki formun de Oluşturucu başlatıcıları ( base ve this ) içerir.contains several variable initializers; it also contains constructor initializers of both forms (base and this). Örnek, aşağıda gösterilen koda karşılık gelir; burada her yorum otomatik olarak yerleştirilen bir ifadeyi gösterir (otomatik olarak yerleştirilen Oluşturucu etkinleştirmeleri için kullanılan söz dizimi geçerli değildir, ancak yalnızca mekanizmayı göstermeye çalışır).The example corresponds to the code shown below, where each comment indicates an automatically inserted statement (the syntax used for the automatically inserted constructor invocations isn't valid, but merely serves to illustrate the mechanism).

using System.Collections;

class A
{
    int x, y, count;

    public A() {
        x = 1;                       // Variable initializer
        y = -1;                      // Variable initializer
        object();                    // Invoke object() constructor
        count = 0;
    }

    public A(int n) {
        x = 1;                       // Variable initializer
        y = -1;                      // Variable initializer
        object();                    // Invoke object() constructor
        count = n;
    }
}

class B: A
{
    double sqrt2;
    ArrayList items;
    int max;

    public B(): this(100) {
        B(100);                      // Invoke B(int) constructor
        items.Add("default");
    }

    public B(int n): base(n - 1) {
        sqrt2 = Math.Sqrt(2.0);      // Variable initializer
        items = new ArrayList(100);  // Variable initializer
        A(n - 1);                    // Invoke A(int) constructor
        max = n;
    }
}

Varsayılan oluşturucularDefault constructors

Bir sınıf örnek Oluşturucu bildirimleri içermiyorsa, varsayılan bir örnek Oluşturucu otomatik olarak sağlanır.If a class contains no instance constructor declarations, a default instance constructor is automatically provided. Bu varsayılan Oluşturucu yalnızca doğrudan temel sınıfın parametresiz oluşturucusunu çağırır.That default constructor simply invokes the parameterless constructor of the direct base class. Sınıf soyut ise, varsayılan Oluşturucu için belirtilen erişilebilirlik korunur.If the class is abstract then the declared accessibility for the default constructor is protected. Aksi takdirde, varsayılan Oluşturucu için belirtilen erişilebilirlik geneldir.Otherwise, the declared accessibility for the default constructor is public. Bu nedenle, varsayılan Oluşturucu her zaman formundadırThus, the default constructor is always of the form

protected C(): base() {}

veyaor

public C(): base() {}

Burada C sınıfın adıdır.where C is the name of the class. Aşırı yükleme çözümlemesi temel sınıf Oluşturucu başlatıcısı için benzersiz bir en iyi aday tespit leyemiyorsa, derleme zamanı hatası oluşur.If overload resolution is unable to determine a unique best candidate for the base class constructor initializer then a compile-time error occurs.

ÖrnekteIn the example

class Message
{
    object sender;
    string text;
}

sınıf örnek Oluşturucu bildirimleri içerdiğinden, varsayılan bir Oluşturucu sağlanır.a default constructor is provided because the class contains no instance constructor declarations. Bu nedenle, örnek tam olarak şu şekilde eşdeğerdirThus, the example is precisely equivalent to

class Message
{
    object sender;
    string text;

    public Message(): base() {}
}

Özel oluşturucularPrivate constructors

Bir sınıf T yalnızca özel örnek oluşturucular bildirdiğinde, ' ın program metni dışındaki sınıflar, ' T ın ' dan türetilmiş T veya doğrudan örnekleri oluşturmak için mümkün değildir T .When a class T declares only private instance constructors, it is not possible for classes outside the program text of T to derive from T or to directly create instances of T. Bu nedenle, bir sınıf yalnızca statik üyeler içeriyorsa ve örneği oluşturulması amaçlanmazsa, boş bir özel örnek Oluşturucu eklemek, örnek oluşturmayı engeller.Thus, if a class contains only static members and isn't intended to be instantiated, adding an empty private instance constructor will prevent instantiation. Örnek:For example:

public class Trig
{
    private Trig() {}        // Prevent instantiation

    public const double PI = 3.14159265358979323846;

    public static double Sin(double x) {...}
    public static double Cos(double x) {...}
    public static double Tan(double x) {...}
}

TrigSınıfı ilgili yöntemleri ve sabitleri gruplandırır, ancak örneği oluşturulacak şekilde tasarlanmamıştır.The Trig class groups related methods and constants, but is not intended to be instantiated. Bu nedenle, tek bir boş özel örnek Oluşturucu bildirir.Therefore it declares a single empty private instance constructor. Varsayılan oluşturucunun otomatik olarak oluşturulmasını engellemek için en az bir örnek Oluşturucu bildirilmelidir.At least one instance constructor must be declared to suppress the automatic generation of a default constructor.

İsteğe bağlı örnek Oluşturucu parametreleriOptional instance constructor parameters

this(...)Oluşturucu başlatıcısı formu, isteğe bağlı örnek oluşturucu parametrelerini uygulamak için yaygın olarak aşırı yükleme ile birlikte kullanılır.The this(...) form of constructor initializer is commonly used in conjunction with overloading to implement optional instance constructor parameters. ÖrnekteIn the example

class Text
{
    public Text(): this(0, 0, null) {}

    public Text(int x, int y): this(x, y, null) {}

    public Text(int x, int y, string s) {
        // Actual constructor implementation
    }
}

ilk iki örnek Oluşturucu yalnızca eksik bağımsız değişkenler için varsayılan değerleri sağlar.the first two instance constructors merely provide the default values for the missing arguments. Her ikisi de this(...) , yeni örneği başlatma işini gerçekten yapan üçüncü örnek oluşturucuyu çağırmak için bir Oluşturucu başlatıcısı kullanın.Both use a this(...) constructor initializer to invoke the third instance constructor, which actually does the work of initializing the new instance. Bu, isteğe bağlı Oluşturucu parametrelerinin etkidir:The effect is that of optional constructor parameters:

Text t1 = new Text();                    // Same as Text(0, 0, null)
Text t2 = new Text(5, 10);               // Same as Text(5, 10, null)
Text t3 = new Text(5, 20, "Hello");

Statik oluşturucularStatic constructors

*Statik Oluşturucusu _, kapalı bir sınıf türünü başlatmak için gereken eylemleri uygulayan bir üyesidir.A *static constructor _ is a member that implements the actions required to initialize a closed class type. Statik oluşturucular _static_constructor_declaration * s kullanılarak bildirilmiştir:Static constructors are declared using _static_constructor_declaration*s:

static_constructor_declaration
    : attributes? static_constructor_modifiers identifier '(' ')' static_constructor_body
    ;

static_constructor_modifiers
    : 'extern'? 'static'
    | 'static' 'extern'?
    | static_constructor_modifiers_unsafe
    ;

static_constructor_body
    : block
    | ';'
    ;

Bir static_constructor_declaration öznitelik (öznitelikler) ve extern değiştirici (dış Yöntemler) kümesini içerebilir.A static_constructor_declaration may include a set of attributes (Attributes) and an extern modifier (External methods).

Bir static_constructor_declaration tanımlayıcısı , statik oluşturucunun bildirildiği sınıfı içermelidir.The identifier of a static_constructor_declaration must name the class in which the static constructor is declared. Başka bir ad belirtilmişse, derleme zamanı hatası oluşur.If any other name is specified, a compile-time error occurs.

Statik Oluşturucu bildirimi bir extern değiştirici içerdiğinde, statik oluşturucu bir *dış statik Oluşturucu _ olarak kabul edilir.When a static constructor declaration includes an extern modifier, the static constructor is said to be an *external static constructor _. Dış bir statik Oluşturucu bildirimi gerçek uygulama olmadığından, _static_constructor_body * noktalı virgülden oluşur.Because an external static constructor declaration provides no actual implementation, its _static_constructor_body* consists of a semicolon. Diğer tüm statik Oluşturucu bildirimleri için static_constructor_body , sınıfı başlatmak için yürütülecek deyimleri belirten bir bloğundan oluşur.For all other static constructor declarations, the static_constructor_body consists of a block which specifies the statements to execute in order to initialize the class. Bu, void dönüş türü (Yöntem gövdesi) ile bir statik metodun method_body tam olarak karşılık gelir.This corresponds exactly to the method_body of a static method with a void return type (Method body).

Statik oluşturucular devralınmaz ve doğrudan çağrılamaz.Static constructors are not inherited, and cannot be called directly.

Kapalı bir sınıf türü için statik oluşturucu, belirli bir uygulama etki alanında en çok bir kez yürütülür.The static constructor for a closed class type executes at most once in a given application domain. Bir statik oluşturucunun yürütülmesi, bir uygulama etki alanı içinde gerçekleşecek aşağıdaki olayların ilki tarafından tetiklenir:The execution of a static constructor is triggered by the first of the following events to occur within an application domain:

  • Sınıf türünün bir örneği oluşturulur.An instance of the class type is created.
  • Sınıf türünün statik üyelerinden herhangi birine başvurulur.Any of the static members of the class type are referenced.

Bir sınıf Main yürütmenin başladığı yöntemi (uygulama başlatma) içeriyorsa, bu sınıfın statik Oluşturucusu Main Yöntem çağrılmadan önce yürütülür.If a class contains the Main method (Application Startup) in which execution begins, the static constructor for that class executes before the Main method is called.

Yeni bir kapalı sınıf türünü başlatmak için, önce bu kapalı tür için yeni bir statik alanlar kümesi (statik ve örnek alanları) oluşturulur.To initialize a new closed class type, first a new set of static fields (Static and instance fields) for that particular closed type is created. Statik alanların her biri varsayılan değerine (varsayılan değerler) başlatılır.Each of the static fields is initialized to its default value (Default values). Daha sonra, statik alan başlatıcıları (statik alan başlatma) Bu statik alanlar için yürütülür.Next, the static field initializers (Static field initialization) are executed for those static fields. Son olarak, statik Oluşturucu yürütülür.Finally, the static constructor is executed.

ÖrnekteThe example

using System;

class Test
{
    static void Main() {
        A.F();
        B.F();
    }
}

class A
{
    static A() {
        Console.WriteLine("Init A");
    }
    public static void F() {
        Console.WriteLine("A.F");
    }
}

class B
{
    static B() {
        Console.WriteLine("Init B");
    }
    public static void F() {
        Console.WriteLine("B.F");
    }
}

Çıktının üretilmesi gerekir:must produce the output:

Init A
A.F
Init B
B.F

Astatik oluşturucunun yürütülmesi çağrısı tarafından tetiklendiğinden A.F ve B statik oluşturucunun yürütülmesi öğesine yapılan çağrısıyla tetiklendiğinden B.F .because the execution of A's static constructor is triggered by the call to A.F, and the execution of B's static constructor is triggered by the call to B.F.

Değişken başlatıcıların varsayılan değer durumunda gözlenecek statik alanlara izin veren dairesel bağımlılıklar oluşturmak mümkündür.It is possible to construct circular dependencies that allow static fields with variable initializers to be observed in their default value state.

ÖrnekteThe example

using System;

class A
{
    public static int X;

    static A() {
        X = B.Y + 1;
    }
}

class B
{
    public static int Y = A.X + 1;

    static B() {}

    static void Main() {
        Console.WriteLine("X = {0}, Y = {1}", A.X, B.Y);
    }
}

çıktıyı üretirproduces the output

X = 1, Y = 2

Yöntemi yürütmek için Main , sistemin B.Y , sınıfının statik Oluşturucusu öncesinde, için başlatıcıyı çalıştırması gerekir B .To execute the Main method, the system first runs the initializer for B.Y, prior to class B's static constructor. Yöğesinin başlatıcısı, A değerine başvurulduğundan statik oluşturucunun çalışmasına neden olur A.X .Y's initializer causes A's static constructor to be run because the value of A.X is referenced. ' In ' in statik Oluşturucusu  A değerini hesaplamak için  X ' i ve ' nin varsayılan değerini getirir  Y , sıfır değeridir.The static constructor of A in turn proceeds to compute the value of X, and in doing so fetches the default value of Y, which is zero. A.X Bu nedenle 1 olarak başlatılır.A.X is thus initialized to 1. AStatik alan başlatıcıları ve statik Oluşturucu çalıştırma işlemi daha sonra, öğesinin başlangıç değerinin hesaplamasına dönerek tamamlanır ve  Y bunun sonucu 2 olur.The process of running A's static field initializers and static constructor then completes, returning to the calculation of the initial value of Y, the result of which becomes 2.

Statik Oluşturucu her bir kapalı oluşturulmuş sınıf türü için tam olarak bir kez yürütüldüğü için, tür parametresinde, kısıtlamalar aracılığıyla (tür parametresi kısıtlamaları) denetlenemeyen çalışma zamanı denetimlerini zorlamak için kullanışlı bir yerdir.Because the static constructor is executed exactly once for each closed constructed class type, it is a convenient place to enforce run-time checks on the type parameter that cannot be checked at compile-time via constraints (Type parameter constraints). Örneğin, aşağıdaki tür, tür bağımsız değişkeninin bir sabit listesi olmasını zorlamak için bir statik Oluşturucu kullanır:For example, the following type uses a static constructor to enforce that the type argument is an enum:

class Gen<T> where T: struct
{
    static Gen() {
        if (!typeof(T).IsEnum) {
            throw new ArgumentException("T must be an enum");
        }
    }
}

YıkıcılarDestructors

*Yıkıcısı _, bir sınıf örneğinin yapısını kaldırma için gereken eylemleri uygulayan bir üyesidir.A *destructor _ is a member that implements the actions required to destruct an instance of a class. Yok edici bir _destructor_declaration * kullanılarak bildirilmiştir:A destructor is declared using a _destructor_declaration*:

destructor_declaration
    : attributes? 'extern'? '~' identifier '(' ')' destructor_body
    | destructor_declaration_unsafe
    ;

destructor_body
    : block
    | ';'
    ;

Bir destructor_declaration bir öznitelikler kümesi içerebilir (öznitelikler).A destructor_declaration may include a set of attributes (Attributes).

Bir destructor_declaration tanımlayıcısı , yok edicinin bildirildiği sınıfı isimlendiremelidir.The identifier of a destructor_declaration must name the class in which the destructor is declared. Başka bir ad belirtilmişse, derleme zamanı hatası oluşur.If any other name is specified, a compile-time error occurs.

Yıkıcı bildirimi bir extern değiştirici içerdiğinde, yıkıcı bir *dış yıkıcı _ olarak kabul edilir.When a destructor declaration includes an extern modifier, the destructor is said to be an *external destructor _. Bir dış yıkıcı bildirimi gerçek uygulama sunmadığından, _destructor_body * noktalı virgülden oluşur.Because an external destructor declaration provides no actual implementation, its _destructor_body* consists of a semicolon. Diğer tüm yok ediciler için destructor_body , sınıfın bir örneğinin çıkarılması için yürütülecek deyimleri belirten bir bloğundan oluşur.For all other destructors, the destructor_body consists of a block which specifies the statements to execute in order to destruct an instance of the class. Bir destructor_body , void dönüş türü (Yöntem gövdesi) olan bir örnek yönteminin method_body tam olarak karşılık gelir.A destructor_body corresponds exactly to the method_body of an instance method with a void return type (Method body).

Yok ediciler devralınmaz.Destructors are not inherited. Bu nedenle, bir sınıfta bu sınıfta bildirilebilecek olandan başka yok edicisi yoktur.Thus, a class has no destructors other than the one which may be declared in that class.

Yok edicinin parametresi olmaması gerektiğinden aşırı yüklenemez, bu nedenle bir sınıf, en fazla bir yıkıcıya sahip olabilir.Since a destructor is required to have no parameters, it cannot be overloaded, so a class can have, at most, one destructor.

Yok ediciler otomatik olarak çağrılır ve açıkça çağrılamaz.Destructors are invoked automatically, and cannot be invoked explicitly. Bir örnek, hiçbir kodun bu örneği kullanabilmesi için artık mümkün olmadığında yok etme için uygun hale gelir.An instance becomes eligible for destruction when it is no longer possible for any code to use that instance. Örnek için yıkıcının yürütülmesi, örnek yok etme için uygun hale geldikten sonra herhangi bir zamanda gerçekleşebilir.Execution of the destructor for the instance may occur at any time after the instance becomes eligible for destruction. Bir örnek çıkarlandığınızda, bu örneğin devralma zincirindeki yok ediciler, en çok türetilen ve en az türetilmiş olarak çağrılır.When an instance is destructed, the destructors in that instance's inheritance chain are called, in order, from most derived to least derived. Herhangi bir iş parçacığında yıkıcı çalıştırılabilir.A destructor may be executed on any thread. Yok edicinin ne zaman ve nasıl yürütüleceğini belirleyen kurallara ilişkin daha fazla tartışma için bkz. Otomatik bellek yönetimi.For further discussion of the rules that govern when and how a destructor is executed, see Automatic memory management.

Örneğin çıktısıThe output of the example

using System;

class A
{
    ~A() {
        Console.WriteLine("A's destructor");
    }
}

class B: A
{
    ~B() {
        Console.WriteLine("B's destructor");
    }
}

class Test
{
   static void Main() {
        B b = new B();
        b = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
   }
}

isis

B's destructor
A's destructor

devralma zincirindeki yok ediciler sırasıyla, en çok türetilen ve en az türeten olarak çağrıldıklarından.since destructors in an inheritance chain are called in order, from most derived to least derived.

Yok ediciler, üzerinde sanal yöntemi geçersiz kılınarak uygulanır Finalize System.Object .Destructors are implemented by overriding the virtual method Finalize on System.Object. C# programlarının bu yöntemi geçersiz kılmasına veya doğrudan bunu (ya da geçersiz kıldığından) çağırmasına izin verilmez.C# programs are not permitted to override this method or call it (or overrides of it) directly. Örneğin, programFor instance, the program

class A 
{
    override protected void Finalize() {}    // error

    public void F() {
        this.Finalize();                     // error
    }
}

iki hata içerir.contains two errors.

Derleyici, bu yöntem ve geçersiz kılmalar gibi davranır.The compiler behaves as if this method, and overrides of it, do not exist at all. Bu nedenle, bu program:Thus, this program:

class A 
{
    void Finalize() {}                            // permitted
}

geçerlidir ve gösterilen yöntem System.Object Finalize yöntemi gizler.is valid, and the method shown hides System.Object's Finalize method.

Yıkıcıdan bir özel durum oluştuğunda davranış tartışması için bkz. özel durumların nasıl işlendiği.For a discussion of the behavior when an exception is thrown from a destructor, see How exceptions are handled.

YineleyicilerIterators

Yineleyici bloğu (bloklar) kullanılarak uygulanan bir işlev üyesine (işlev üyeleri) Yineleyici denir.A function member (Function members) implemented using an iterator block (Blocks) is called an iterator.

Bir yineleyici bloğu, karşılık gelen işlev üyesinin dönüş türü Numaralandırıcı arabirimlerinden (Numaralandırıcı arabirimleri) biri veya sıralanabilir arabirimlerin (sıralanabilir arabirimler) biri olduğu sürece bir işlev üyesinin gövdesi olarak kullanılabilir.An iterator block may be used as the body of a function member as long as the return type of the corresponding function member is one of the enumerator interfaces (Enumerator interfaces) or one of the enumerable interfaces (Enumerable interfaces). Method_body, operator_body veya accessor_body olarak gerçekleşebilir, ancak olaylar, örnek oluşturucular, statik oluşturucular ve Yıkıcılar yineleyiciler olarak uygulanamaz.It can occur as a method_body, operator_body or accessor_body, whereas events, instance constructors, static constructors and destructors cannot be implemented as iterators.

Bir işlev üyesi Yineleyici bloğu kullanılarak uygulandığında, işlev üyesinin biçimsel parametre listesi için herhangi bir veya parametresi belirtmek üzere derleme zamanı hatası olur ref out .When a function member is implemented using an iterator block, it is a compile-time error for the formal parameter list of the function member to specify any ref or out parameters.

Numaralandırıcı arabirimleriEnumerator interfaces

Numaralandırıcı arabirimleri genel olmayan arabirimdir System.Collections.IEnumerator ve genel arabirimin tüm örneklemelerinden oluşur System.Collections.Generic.IEnumerator<T> .The enumerator interfaces are the non-generic interface System.Collections.IEnumerator and all instantiations of the generic interface System.Collections.Generic.IEnumerator<T>. Breçekimi 'nin sake 'ı için bu bölümde IEnumerator sırasıyla ve olarak başvurulur IEnumerator<T> .For the sake of brevity, in this chapter these interfaces are referenced as IEnumerator and IEnumerator<T>, respectively.

Sıralanabilir arabirimlerEnumerable interfaces

Sıralanabilir arabirimler genel olmayan arabirimdir System.Collections.IEnumerable ve genel arabirimin tüm örneklemelerinden oluşur System.Collections.Generic.IEnumerable<T> .The enumerable interfaces are the non-generic interface System.Collections.IEnumerable and all instantiations of the generic interface System.Collections.Generic.IEnumerable<T>. Breçekimi 'nin sake 'ı için bu bölümde IEnumerable sırasıyla ve olarak başvurulur IEnumerable<T> .For the sake of brevity, in this chapter these interfaces are referenced as IEnumerable and IEnumerable<T>, respectively.

Yield türüYield type

Bir yineleyici, hepsi aynı türden bir değer dizisi üretir.An iterator produces a sequence of values, all of the same type. Bu tür, yineleyicinin yield türü olarak adlandırılır.This type is called the yield type of the iterator.

  • Veya döndüren bir yineleyicinin yield türü IEnumerator IEnumerable object .The yield type of an iterator that returns IEnumerator or IEnumerable is object.
  • Veya döndüren bir yineleyicinin yield türü IEnumerator<T> IEnumerable<T> T .The yield type of an iterator that returns IEnumerator<T> or IEnumerable<T> is T.

Numaralandırıcı nesneleriEnumerator objects

Bir Numaralandırıcı arabirim türü döndüren bir işlev üyesi Yineleyici bloğu kullanılarak uygulandığında, işlev üyesini çağırmak kodu Yineleyici bloğunda hemen yürütmez.When a function member returning an enumerator interface type is implemented using an iterator block, invoking the function member does not immediately execute the code in the iterator block. Bunun yerine, bir Numaralandırıcı nesnesi oluşturulup döndürülür.Instead, an enumerator object is created and returned. Bu nesne Yineleyici bloğunda belirtilen kodu kapsüller ve Numaralandırıcı nesnesinin yöntemi çağrıldığında Yineleyici bloğunda kodun yürütülmesi oluşur MoveNext .This object encapsulates the code specified in the iterator block, and execution of the code in the iterator block occurs when the enumerator object's MoveNext method is invoked. Bir Numaralandırıcı nesnesi aşağıdaki özelliklere sahiptir:An enumerator object has the following characteristics:

  • IEnumerator IEnumerator<T> , Ve ' nin uyguladığı, T yineleyicinin yield türüdür.It implements IEnumerator and IEnumerator<T>, where T is the yield type of the iterator.
  • Uygular System.IDisposable .It implements System.IDisposable.
  • Bağımsız değişken değerlerinin bir kopyasıyla başlatılır (varsa) ve örnek değeri işlev üyesine geçirilir.It is initialized with a copy of the argument values (if any) and instance value passed to the function member.
  • Dört olası durum, önce _, _çalışıyor_, _askıya alındı_ ve _sonra_, ilk olarak _ *önce* durumunda olur.It has four potential states, before _, _running_, _suspended_, and _after_, and is initially in the _ before state.

Numaralandırıcı nesnesi genellikle Yineleyici bloğundaki kodu kapsülleyen ve Numaralandırıcı arabirimlerini uygulayan derleyici tarafından oluşturulan Numaralandırıcı sınıfının bir örneğidir, ancak diğer uygulama yöntemleri mümkündür.An enumerator object is typically an instance of a compiler-generated enumerator class that encapsulates the code in the iterator block and implements the enumerator interfaces, but other methods of implementation are possible. Bir Numaralandırıcı sınıfı derleyici tarafından oluşturulduysa, bu sınıf doğrudan veya dolaylı olarak işlev üyesini içeren sınıfta iç içe gelir, özel erişilebilirliği olur ve derleyici kullanımı (tanımlayıcılar) için ayrılmış bir ada sahip olur.If an enumerator class is generated by the compiler, that class will be nested, directly or indirectly, in the class containing the function member, it will have private accessibility, and it will have a name reserved for compiler use (Identifiers).

Bir Numaralandırıcı nesnesi, yukarıda belirtilenden daha fazla arabirim uygulayabilir.An enumerator object may implement more interfaces than those specified above.

Aşağıdaki bölümlerde,, ve MoveNext Current Dispose IEnumerable IEnumerable<T> bir Numaralandırıcı nesnesi tarafından sunulan ve arabirim uygulamalarının üyelerinin tam davranışı açıklanır.The following sections describe the exact behavior of the MoveNext, Current, and Dispose members of the IEnumerable and IEnumerable<T> interface implementations provided by an enumerator object.

Numaralandırıcı nesnelerinin yöntemi desteklemediğini unutmayın IEnumerator.Reset .Note that enumerator objects do not support the IEnumerator.Reset method. Bu yöntemi çağırmak, bir oluşturulmasına neden olur System.NotSupportedException .Invoking this method causes a System.NotSupportedException to be thrown.

MoveNext yöntemiThe MoveNext method

MoveNextBir Numaralandırıcı nesnesinin yöntemi bir yineleyici bloğunun kodunu kapsüller.The MoveNext method of an enumerator object encapsulates the code of an iterator block. Yöntemi çağırmak MoveNext Yineleyici bloğunda kodu yürütür ve Current Numaralandırıcı nesnesinin özelliğini uygun şekilde ayarlar.Invoking the MoveNext method executes code in the iterator block and sets the Current property of the enumerator object as appropriate. Tarafından gerçekleştirilen kesin eylem, MoveNext çağrıldığında Numaralandırıcı nesnesinin durumuna bağlıdır MoveNext :The precise action performed by MoveNext depends on the state of the enumerator object when MoveNext is invoked:

  • Numaralandırıcı nesnesinin durumu daha önce ise, şunu çağırır MoveNext :If the state of the enumerator object is before, invoking MoveNext:
    • Durumu çalışıyor olarak değiştirir.Changes the state to running.
    • thisYineleyici bloğunun, Numaralandırıcı nesnesi başlatıldığında kaydedilen bağımsız değişken değerlerine ve örnek değerine sahip parametrelerini (dahil) başlatır.Initializes the parameters (including this) of the iterator block to the argument values and instance value saved when the enumerator object was initialized.
    • , Yürütme kesintiye gelinceye kadar Yineleyici bloğunu baştan yürütür (aşağıda açıklandığı gibi).Executes the iterator block from the beginning until execution is interrupted (as described below).
  • Numaralandırıcı nesnesinin durumu çalışıyorsa, çağırma sonucu MoveNext belirtilmemiş olur.If the state of the enumerator object is running, the result of invoking MoveNext is unspecified.
  • Numaralandırıcı nesnesinin durumu askıya alınırsa, çağırma MoveNext :If the state of the enumerator object is suspended, invoking MoveNext:
    • Durumu çalışıyor olarak değiştirir.Changes the state to running.
    • Tüm yerel değişkenlerin ve parametrelerin (Bu dahil) değerlerini, yineleyici bloğunun yürütülmesi son askıya alındığında kaydedilen değerlere geri yükler.Restores the values of all local variables and parameters (including this) to the values saved when execution of the iterator block was last suspended. Bu değişkenlerin başvurduğu nesnelerin içeriklerinin, önceki MoveNext çağrısından bu yana değişmiş olabileceğini unutmayın.Note that the contents of any objects referenced by these variables may have changed since the previous call to MoveNext.
    • Yürütmenin askıya alınmasına neden olan deyimin hemen sonrasında Yineleyici bloğunun yürütülmesini sürdürür yield return ve yürütme kesintiye uğratılıncaya kadar devam eder (aşağıda açıklandığı gibi).Resumes execution of the iterator block immediately following the yield return statement that caused the suspension of execution and continues until execution is interrupted (as described below).
  • Numaralandırıcı nesnesinin durumu After ise, MoveNext dönüşler çağırma false .If the state of the enumerator object is after, invoking MoveNext returns false.

MoveNextYineleyici bloğunu yürüttüğünde, yürütme dört şekilde kesilebilir: bir yield return deyime göre, yield break Yineleyici bloğunun sonuyla karşılaşarak ve bir özel durum oluşan ve yineleyici bloğunun dışına yayıldığında.When MoveNext executes the iterator block, execution can be interrupted in four ways: By a yield return statement, by a yield break statement, by encountering the end of the iterator block, and by an exception being thrown and propagated out of the iterator block.

  • Bir yield return ifadeye rastlandı (yield bildirisi):When a yield return statement is encountered (The yield statement):
    • Deyimde verilen ifade değerlendirilir, örtülü olarak yield türüne dönüştürülür ve Current Numaralandırıcı nesnesinin özelliğine atanır.The expression given in the statement is evaluated, implicitly converted to the yield type, and assigned to the Current property of the enumerator object.
    • Yineleyici gövdesinin yürütülmesi askıya alındı.Execution of the iterator body is suspended. Tüm yerel değişkenlerin ve parametrelerin (dahil) değerleri, this Bu deyimin konumu olduğu gibi kaydedilir yield return .The values of all local variables and parameters (including this) are saved, as is the location of this yield return statement. yield returnİfade bir veya daha fazla try blok içindeyse, ilişkili finally bloklar Şu anda yürütülmez.If the yield return statement is within one or more try blocks, the associated finally blocks are not executed at this time.
    • Numaralandırıcı nesnesinin durumu askıya alındı olarak değiştirildi.The state of the enumerator object is changed to suspended.
    • MoveNextYöntemi, true yinelemesinin bir sonraki değere başarıyla ilerlemiş olduğunu belirten, çağırana döner.The MoveNext method returns true to its caller, indicating that the iteration successfully advanced to the next value.
  • Bir yield break ifadeye rastlandı (yield bildirisi):When a yield break statement is encountered (The yield statement):
    • yield breakDeyimler bir veya daha fazla blok içindeyse try , ilişkili finally bloklar yürütülür.If the yield break statement is within one or more try blocks, the associated finally blocks are executed.
    • Numaralandırıcı nesnesinin durumu, daha sonra olarak değiştirilir.The state of the enumerator object is changed to after.
    • MoveNextYöntemi, false yinelemesinin tamamlandığını belirten, çağırana döner.The MoveNext method returns false to its caller, indicating that the iteration is complete.
  • Yineleyici gövdesinin sonuna rastlandı:When the end of the iterator body is encountered:
    • Numaralandırıcı nesnesinin durumu, daha sonra olarak değiştirilir.The state of the enumerator object is changed to after.
    • MoveNextYöntemi, false yinelemesinin tamamlandığını belirten, çağırana döner.The MoveNext method returns false to its caller, indicating that the iteration is complete.
  • Bir özel durum oluştuğunda ve yineleyici bloğundan yayıldığında:When an exception is thrown and propagated out of the iterator block:
    • finallyYineleyici gövdesinde uygun bloklar özel durum yayma tarafından yürütülür.Appropriate finally blocks in the iterator body will have been executed by the exception propagation.
    • Numaralandırıcı nesnesinin durumu, daha sonra olarak değiştirilir.The state of the enumerator object is changed to after.
    • Özel durum yayma yöntemi çağırana devam eder MoveNext .The exception propagation continues to the caller of the MoveNext method.

Geçerli özellikThe Current property

Numaralandırıcı nesnesinin Current özelliği yield return Yineleyici bloğundaki deyimlerden etkilenir.An enumerator object's Current property is affected by yield return statements in the iterator block.

Bir Numaralandırıcı nesnesi *askıya alınmış _ durumundaysa, değeri, Current Önceki çağrısı tarafından ayarlanan değerdir MoveNext .When an enumerator object is in the *suspended _ state, the value of Current is the value set by the previous call to MoveNext. Bir Numaralandırıcı nesnesi *önce*, *çalışıyor* veya _ sonrasında * durumlardan sonra, erişim sonucu Current belirtilmemiş olur.When an enumerator object is in the before, running, or _ after* states, the result of accessing Current is unspecified.

Dışında bir yield türü olan bir yineleyici için object , Current Numaralandırıcı nesnesinin uygulamasına erişmenin sonucu, IEnumerable Current Numaralandırıcı nesnesinin IEnumerator<T> uygulamasına erişme ve sonucu olarak atama için karşılık gelir object .For an iterator with a yield type other than object, the result of accessing Current through the enumerator object's IEnumerable implementation corresponds to accessing Current through the enumerator object's IEnumerator<T> implementation and casting the result to object.

Dispose yöntemiThe Dispose method

DisposeYöntemi, Numaralandırıcı nesnesini After durumuna getirerek yinelemeyi temizlemek için kullanılır.The Dispose method is used to clean up the iteration by bringing the enumerator object to the after state.

  • Numaralandırıcı nesnesinin durumu *Before _ ise, çağırma, Dispose durumu * *sonrasında _ * olarak değiştirir.If the state of the enumerator object is before _, invoking Dispose changes the state to _after**.
  • Numaralandırıcı nesnesinin durumu çalışıyorsa, çağırma sonucu Dispose belirtilmemiş olur.If the state of the enumerator object is running, the result of invoking Dispose is unspecified.
  • Numaralandırıcı nesnesinin durumu askıya alınırsa, çağırma Dispose :If the state of the enumerator object is suspended, invoking Dispose:
    • Durumu çalışıyor olarak değiştirir.Changes the state to running.
    • Son yürütülen yield return deyimin bir ifademiş olduğu sürece herhangi bir finally bloğunu yürütür yield break .Executes any finally blocks as if the last executed yield return statement were a yield break statement. Bu durum, yineleyici gövdesinden oluşan bir özel durumun oluşturulmasına ve yayılmasına neden olursa, Numaralandırıcı nesnesinin durumu After olarak ayarlanır ve özel durum yöntem çağıranına yayılır Dispose .If this causes an exception to be thrown and propagated out of the iterator body, the state of the enumerator object is set to after and the exception is propagated to the caller of the Dispose method.
    • Durumu sonraki olarak değiştirir.Changes the state to after.
  • Numaralandırıcı nesnesinin durumu After ise, çağırma Dispose hiçbir etkisi olmaz.If the state of the enumerator object is after, invoking Dispose has no affect.

Sıralanabilir nesnelerEnumerable objects

Sıralanabilir bir arabirim türü döndüren bir işlev üyesi Yineleyici bloğu kullanılarak uygulandığında, işlev üyesini çağırmak kodu Yineleyici bloğunda hemen yürütmez.When a function member returning an enumerable interface type is implemented using an iterator block, invoking the function member does not immediately execute the code in the iterator block. Bunun yerine, sıralanabilir bir nesne oluşturulur ve döndürülür.Instead, an enumerable object is created and returned. Sıralanabilir nesne yöntemi, GetEnumerator Yineleyici bloğunda belirtilen kodu kapsülleyen bir Numaralandırıcı nesnesi döndürür ve Numaralandırıcı nesnesinin yöntemi çağrıldığında Yineleyici bloğunda kodun yürütülmesi oluşur MoveNext .The enumerable object's GetEnumerator method returns an enumerator object that encapsulates the code specified in the iterator block, and execution of the code in the iterator block occurs when the enumerator object's MoveNext method is invoked. Sıralanabilir bir nesne aşağıdaki özelliklere sahiptir:An enumerable object has the following characteristics:

  • IEnumerable IEnumerable<T> , Ve ' nin uyguladığı, T yineleyicinin yield türüdür.It implements IEnumerable and IEnumerable<T>, where T is the yield type of the iterator.
  • Bağımsız değişken değerlerinin bir kopyasıyla başlatılır (varsa) ve örnek değeri işlev üyesine geçirilir.It is initialized with a copy of the argument values (if any) and instance value passed to the function member.

Sıralanabilir bir nesne genellikle Yineleyici bloğunda kodu kapsülleyen ve numaralandırılabilir arabirimleri uygulayan, derleyici tarafından oluşturulan bir sıralanabilir sınıfın örneğidir, ancak diğer uygulama yöntemleri mümkündür.An enumerable object is typically an instance of a compiler-generated enumerable class that encapsulates the code in the iterator block and implements the enumerable interfaces, but other methods of implementation are possible. Bir sıralanabilir sınıf derleyici tarafından oluşturulduysa, bu sınıf doğrudan veya dolaylı olarak işlev üyesini içeren sınıfta iç içe gelir, özel erişilebilirliği olur ve derleyici kullanımı (tanımlayıcılar) için ayrılmış bir ada sahip olur.If an enumerable class is generated by the compiler, that class will be nested, directly or indirectly, in the class containing the function member, it will have private accessibility, and it will have a name reserved for compiler use (Identifiers).

Sıralanabilir bir nesne, yukarıda belirtilenden daha fazla arabirim uygulayabilir.An enumerable object may implement more interfaces than those specified above. Özellikle de sıralanabilir bir nesne de uygulayabilir ve IEnumerator IEnumerator<T> Bu, hem numaralandırılabilir hem de numaralandırıcı olarak işlev görmesi sağlar.In particular, an enumerable object may also implement IEnumerator and IEnumerator<T>, enabling it to serve as both an enumerable and an enumerator. Bu tür bir uygulamada, bir sıralanabilir nesnenin yöntemi ilk kez çağrıldığında, GetEnumerator sıralanabilir nesnenin kendisi döndürülür.In that type of implementation, the first time an enumerable object's GetEnumerator method is invoked, the enumerable object itself is returned. Sıralanabilir nesnenin sonraki etkinleştirmeleri GetEnumerator , varsa, sıralanabilir nesnenin bir kopyasını döndürür.Subsequent invocations of the enumerable object's GetEnumerator, if any, return a copy of the enumerable object. Bu nedenle, döndürülen her Numaralandırıcı kendi durumuna sahiptir ve bir Numaralandırıcı içindeki değişiklikler başka bir Numaralandırıcı olur.Thus, each returned enumerator has its own state and changes in one enumerator will not affect another.

GetEnumerator yöntemiThe GetEnumerator method

Sıralanabilir bir nesne GetEnumerator , ve arabirimlerinin yöntemlerinin bir uygulamasını sağlar IEnumerable IEnumerable<T> .An enumerable object provides an implementation of the GetEnumerator methods of the IEnumerable and IEnumerable<T> interfaces. İki GetEnumerator Yöntem, kullanılabilir bir Numaralandırıcı nesnesi elde eden ve döndüren ortak bir uygulamayı paylaşır.The two GetEnumerator methods share a common implementation that acquires and returns an available enumerator object. Numaralandırıcı nesnesi, sıralanabilir nesne başlatıldığında bağımsız değişken değerleri ve örnek değeri ile başlatılır, aksi takdirde Numaralandırıcı nesnesi, Numaralandırıcı nesnelerindeaçıklanan şekilde çalışır.The enumerator object is initialized with the argument values and instance value saved when the enumerable object was initialized, but otherwise the enumerator object functions as described in Enumerator objects.

Uygulama örneğiImplementation example

Bu bölümde, yineleyicilerin standart C# yapıları açısından olası bir uygulama açıklanmaktadır.This section describes a possible implementation of iterators in terms of standard C# constructs. Burada açıklanan uygulama, Microsoft C# derleyicisi tarafından kullanılan ilkelere dayanır, ancak bu, bir uygulanan uygulamasına veya mümkün olan tek bir uygulama anlamına gelir.The implementation described here is based on the same principles used by the Microsoft C# compiler, but it is by no means a mandated implementation or the only one possible.

Aşağıdaki Stack<T> sınıf GetEnumerator yöntemini bir yineleyici kullanarak uygular.The following Stack<T> class implements its GetEnumerator method using an iterator. Yineleyici, yığının öğelerini üstten alta doğru sıralamayla numaralandırır.The iterator enumerates the elements of the stack in top to bottom order.

using System;
using System.Collections;
using System.Collections.Generic;

class Stack<T>: IEnumerable<T>
{
    T[] items;
    int count;

    public void Push(T item) {
        if (items == null) {
            items = new T[4];
        }
        else if (items.Length == count) {
            T[] newItems = new T[count * 2];
            Array.Copy(items, 0, newItems, 0, count);
            items = newItems;
        }
        items[count++] = item;
    }

    public T Pop() {
        T result = items[--count];
        items[count] = default(T);
        return result;
    }

    public IEnumerator<T> GetEnumerator() {
        for (int i = count - 1; i >= 0; --i) yield return items[i];
    }
}

GetEnumeratorYöntemi, aşağıdaki şekilde gösterildiği gibi, yineleyici bloğunda kodu kapsülleyen derleyicinin ürettiği bir Numaralandırıcı sınıfının bir örneklemesine çevrilebilir.The GetEnumerator method can be translated into an instantiation of a compiler-generated enumerator class that encapsulates the code in the iterator block, as shown in the following.

class Stack<T>: IEnumerable<T>
{
    ...

    public IEnumerator<T> GetEnumerator() {
        return new __Enumerator1(this);
    }

    class __Enumerator1: IEnumerator<T>, IEnumerator
    {
        int __state;
        T __current;
        Stack<T> __this;
        int i;

        public __Enumerator1(Stack<T> __this) {
            this.__this = __this;
        }

        public T Current {
            get { return __current; }
        }

        object IEnumerator.Current {
            get { return __current; }
        }

        public bool MoveNext() {
            switch (__state) {
                case 1: goto __state1;
                case 2: goto __state2;
            }
            i = __this.count - 1;
        __loop:
            if (i < 0) goto __state2;
            __current = __this.items[i];
            __state = 1;
            return true;
        __state1:
            --i;
            goto __loop;
        __state2:
            __state = 2;
            return false;
        }

        public void Dispose() {
            __state = 2;
        }

        void IEnumerator.Reset() {
            throw new NotSupportedException();
        }
    }
}

Yukarıdaki çeviride, yineleyici bloğundaki kod bir durum makinesine açılıp MoveNext Numaralandırıcı sınıfının yöntemine yerleştirilir.In the preceding translation, the code in the iterator block is turned into a state machine and placed in the MoveNext method of the enumerator class. Ayrıca yerel değişken, i Numaralandırıcı nesnesindeki bir alana açıktır, bu sayede ' ın çağırmaları arasında olmaya devam edebilir MoveNext .Furthermore, the local variable i is turned into a field in the enumerator object so it can continue to exist across invocations of MoveNext.

Aşağıdaki örnekte, 1 ile 10 arasındaki tamsayıların basit bir çarpma tablosu yazdırılır.The following example prints a simple multiplication table of the integers 1 through 10. FromToÖrnekteki yöntem, sıralanabilir bir nesne döndürüyor ve yineleyici kullanılarak uygulanır.The FromTo method in the example returns an enumerable object and is implemented using an iterator.

using System;
using System.Collections.Generic;

class Test
{
    static IEnumerable<int> FromTo(int from, int to) {
        while (from <= to) yield return from++;
    }

    static void Main() {
        IEnumerable<int> e = FromTo(1, 10);
        foreach (int x in e) {
            foreach (int y in e) {
                Console.Write("{0,3} ", x * y);
            }
            Console.WriteLine();
        }
    }
}

FromToYöntemi, aşağıdaki şekilde gösterildiği gibi, yineleyici bloğunda kodu kapsülleyen derleyici tarafından oluşturulmuş bir sıralanabilir sınıfın bir örneklemesine çevrilebilir.The FromTo method can be translated into an instantiation of a compiler-generated enumerable class that encapsulates the code in the iterator block, as shown in the following.

using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;

class Test
{
    ...

    static IEnumerable<int> FromTo(int from, int to) {
        return new __Enumerable1(from, to);
    }

    class __Enumerable1:
        IEnumerable<int>, IEnumerable,
        IEnumerator<int>, IEnumerator
    {
        int __state;
        int __current;
        int __from;
        int from;
        int to;
        int i;

        public __Enumerable1(int __from, int to) {
            this.__from = __from;
            this.to = to;
        }

        public IEnumerator<int> GetEnumerator() {
            __Enumerable1 result = this;
            if (Interlocked.CompareExchange(ref __state, 1, 0) != 0) {
                result = new __Enumerable1(__from, to);
                result.__state = 1;
            }
            result.from = result.__from;
            return result;
        }

        IEnumerator IEnumerable.GetEnumerator() {
            return (IEnumerator)GetEnumerator();
        }

        public int Current {
            get { return __current; }
        }

        object IEnumerator.Current {
            get { return __current; }
        }

        public bool MoveNext() {
            switch (__state) {
            case 1:
                if (from > to) goto case 2;
                __current = from++;
                __state = 1;
                return true;
            case 2:
                __state = 2;
                return false;
            default:
                throw new InvalidOperationException();
            }
        }

        public void Dispose() {
            __state = 2;
        }

        void IEnumerator.Reset() {
            throw new NotSupportedException();
        }
    }
}

Sıralanabilir sınıf hem numaralandırılabilir arabirimleri hem de Numaralandırıcı arabirimlerini uygular, bu sayede hem numaralandırılabilir hem de numaralandırıcı olarak işlev sağlar.The enumerable class implements both the enumerable interfaces and the enumerator interfaces, enabling it to serve as both an enumerable and an enumerator. Yöntemi ilk kez GetEnumerator çağrıldığında, sıralanabilir nesnenin kendisi döndürülür.The first time the GetEnumerator method is invoked, the enumerable object itself is returned. Sıralanabilir nesnenin sonraki etkinleştirmeleri GetEnumerator , varsa, sıralanabilir nesnenin bir kopyasını döndürür.Subsequent invocations of the enumerable object's GetEnumerator, if any, return a copy of the enumerable object. Bu nedenle, döndürülen her Numaralandırıcı kendi durumuna sahiptir ve bir Numaralandırıcı içindeki değişiklikler başka bir Numaralandırıcı olur.Thus, each returned enumerator has its own state and changes in one enumerator will not affect another. Interlocked.CompareExchangeYöntemi, iş parçacığı güvenli işlemi sağlamak için kullanılır.The Interlocked.CompareExchange method is used to ensure thread-safe operation.

fromVe to parametreleri, sıralanabilir sınıftaki alanlara açıktır.The from and to parameters are turned into fields in the enumerable class. fromYineleyici bloğunda değiştirildiği için, __from Her Numaralandırıcı için verilen ilk değeri tutmak üzere ek bir alan sunulmuştur from .Because from is modified in the iterator block, an additional __from field is introduced to hold the initial value given to from in each enumerator.

MoveNextYöntemi InvalidOperationException , olduğunda çağrılırsa bir oluşturur __state 0 .The MoveNext method throws an InvalidOperationException if it is called when __state is 0. Bu, numaralandırılabilir nesnenin önce çağrılmadan bir Numaralandırıcı nesnesi olarak kullanılmasını önler GetEnumerator .This protects against use of the enumerable object as an enumerator object without first calling GetEnumerator.

Aşağıdaki örnek bir basit ağaç sınıfını göstermektedir.The following example shows a simple tree class. Tree<T>Sınıfı, GetEnumerator bir yineleyici kullanarak metodunu uygular.The Tree<T> class implements its GetEnumerator method using an iterator. Yineleyici, ağaç öğelerini geçersiz kılma sırasında sıralar.The iterator enumerates the elements of the tree in infix order.

using System;
using System.Collections.Generic;

class Tree<T>: IEnumerable<T>
{
    T value;
    Tree<T> left;
    Tree<T> right;

    public Tree(T value, Tree<T> left, Tree<T> right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }

    public IEnumerator<T> GetEnumerator() {
        if (left != null) foreach (T x in left) yield x;
        yield value;
        if (right != null) foreach (T x in right) yield x;
    }
}

class Program
{
    static Tree<T> MakeTree<T>(T[] items, int left, int right) {
        if (left > right) return null;
        int i = (left + right) / 2;
        return new Tree<T>(items[i], 
            MakeTree(items, left, i - 1),
            MakeTree(items, i + 1, right));
    }

    static Tree<T> MakeTree<T>(params T[] items) {
        return MakeTree(items, 0, items.Length - 1);
    }

    // The output of the program is:
    // 1 2 3 4 5 6 7 8 9
    // Mon Tue Wed Thu Fri Sat Sun

    static void Main() {
        Tree<int> ints = MakeTree(1, 2, 3, 4, 5, 6, 7, 8, 9);
        foreach (int i in ints) Console.Write("{0} ", i);
        Console.WriteLine();

        Tree<string> strings = MakeTree(
            "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");
        foreach (string s in strings) Console.Write("{0} ", s);
        Console.WriteLine();
    }
}

GetEnumeratorYöntemi, aşağıdaki şekilde gösterildiği gibi, yineleyici bloğunda kodu kapsülleyen derleyicinin ürettiği bir Numaralandırıcı sınıfının bir örneklemesine çevrilebilir.The GetEnumerator method can be translated into an instantiation of a compiler-generated enumerator class that encapsulates the code in the iterator block, as shown in the following.

class Tree<T>: IEnumerable<T>
{
    ...

    public IEnumerator<T> GetEnumerator() {
        return new __Enumerator1(this);
    }

    class __Enumerator1 : IEnumerator<T>, IEnumerator
    {
        Node<T> __this;
        IEnumerator<T> __left, __right;
        int __state;
        T __current;

        public __Enumerator1(Node<T> __this) {
            this.__this = __this;
        }

        public T Current {
            get { return __current; }
        }

        object IEnumerator.Current {
            get { return __current; }
        }

        public bool MoveNext() {
            try {
                switch (__state) {

                case 0:
                    __state = -1;
                    if (__this.left == null) goto __yield_value;
                    __left = __this.left.GetEnumerator();
                    goto case 1;

                case 1:
                    __state = -2;
                    if (!__left.MoveNext()) goto __left_dispose;
                    __current = __left.Current;
                    __state = 1;
                    return true;

                __left_dispose:
                    __state = -1;
                    __left.Dispose();

                __yield_value:
                    __current = __this.value;
                    __state = 2;
                    return true;

                case 2:
                    __state = -1;
                    if (__this.right == null) goto __end;
                    __right = __this.right.GetEnumerator();
                    goto case 3;

                case 3:
                    __state = -3;
                    if (!__right.MoveNext()) goto __right_dispose;
                    __current = __right.Current;
                    __state = 3;
                    return true;

                __right_dispose:
                    __state = -1;
                    __right.Dispose();

                __end:
                    __state = 4;
                    break;

                }
            }
            finally {
                if (__state < 0) Dispose();
            }
            return false;
        }

        public void Dispose() {
            try {
                switch (__state) {

                case 1:
                case -2:
                    __left.Dispose();
                    break;

                case 3:
                case -3:
                    __right.Dispose();
                    break;

                }
            }
            finally {
                __state = 4;
            }
        }

        void IEnumerator.Reset() {
            throw new NotSupportedException();
        }
    }
}

Deyimlerde kullanılan geçiciler oluşturulan derleyici, foreach __left __right Numaralandırıcı nesnesinin ve alanlarını yükseltilmemiş.The compiler generated temporaries used in the foreach statements are lifted into the __left and __right fields of the enumerator object. __state Dispose() Bir özel durum oluşturulursa doğru yöntem doğru şekilde çağrılabilmesi için, Numaralandırıcı nesnesinin alanı dikkatle güncellenir.The __state field of the enumerator object is carefully updated so that the correct Dispose() method will be called correctly if an exception is thrown. Çevrilmiş kodu basit deyimlerle yazmak mümkün değildir foreach .Note that it is not possible to write the translated code with simple foreach statements.

Zaman uyumsuz işlevlerAsync functions

Değiştirici içeren bir Yöntem (metotlar) veya anonim Işlev (anonim işlev ifadeleri) async *Async işlevi _ olarak adlandırılır.A method (Methods) or anonymous function (Anonymous function expressions) with the async modifier is called an *async function _. Genel olarak, değiştiriciye sahip herhangi bir tür işlevi anlatmak için _ Async* terimi kullanılır async .In general, the term _ async* is used to describe any kind of function that has the async modifier.

Herhangi bir veya parametresi belirtmek için zaman uyumsuz bir işlevin biçimsel parametre listesi için derleme zamanı hatası ref out .It is a compile-time error for the formal parameter list of an async function to specify any ref or out parameters.

Zaman uyumsuz bir metodun return_type ya da void bir görev türü olmalıdır.The return_type of an async method must be either void or a task type. Görev türleri System.Threading.Tasks.Task ve ' den oluşturulan türlerdir System.Threading.Tasks.Task<T> .The task types are System.Threading.Tasks.Task and types constructed from System.Threading.Tasks.Task<T>. Breçekimi 'nin sake 'ı için bu bölümde Task sırasıyla ve olarak başvurulur Task<T> .For the sake of brevity, in this chapter these types are referenced as Task and Task<T>, respectively. Bir görev türü döndüren zaman uyumsuz bir yöntem, görev döndüren olarak kabul edilir.An async method returning a task type is said to be task-returning.

Görev türlerinin tam tanımı uygulama tanımlı, ancak dilin bir görev türü görüntüleme noktasından tamamlanmamış, başarılı veya hatalı durumlardan birinde.The exact definition of the task types is implementation defined, but from the language's point of view a task type is in one of the states incomplete, succeeded or faulted. Hatalı bir görev ilgili özel durumu kaydeder.A faulted task records a pertinent exception. Başarılı bir Task<T> tür sonucunu kaydeder T .A succeeded Task<T> records a result of type T. Görev türleri beklenebilir ve bu nedenle await ifadelerinin işlenenleri (await ifadeleri) olabilir.Task types are awaitable, and can therefore be the operands of await expressions (Await expressions).

Zaman uyumsuz işlev çağırma, kendi gövdesinde await ifadeleri (await ifadeleri) yoluyla değerlendirmeyi askıya alabilir.An async function invocation has the ability to suspend evaluation by means of await expressions (Await expressions) in its body. Değerlendirme daha sonra, bir *sürdürme Delegate _ ile askıya alma await ifadesinin noktasında devam edebilir.Evaluation may later be resumed at the point of the suspending await expression by means of a *resumption delegate _. Sürdürme temsilcisi türündedir System.Action ve çağrıldığında, zaman uyumsuz işlev çağrısının değerlendirmesi, kaldığı Await ifadesinden sürdürülecek.The resumption delegate is of type System.Action, and when it is invoked, evaluation of the async function invocation will resume from the await expression where it left off. Zaman uyumsuz işlev çağrısının _ geçerli çağıranı, işlev çağırma işlemi hiç askıya alınmadıysa veya sürdürme temsilcisinin en son çağıranı yoksa, özgün çağırıcı olur.The _ current caller* of an async function invocation is the original caller if the function invocation has never been suspended, or the most recent caller of the resumption delegate otherwise.

Bir görev döndüren zaman uyumsuz işlev değerlendirmesiEvaluation of a task-returning async function

Bir görev döndüren zaman uyumsuz işlevin çağrılması döndürülen görev türünün bir örneğinin oluşturulmasına neden olur.Invocation of a task-returning async function causes an instance of the returned task type to be generated. Bu, Async işlevinin Return görevi olarak adlandırılır.This is called the return task of the async function. Görev başlangıçta tamamlanmamış bir durumda.The task is initially in an incomplete state.

Zaman uyumsuz işlev gövdesi, askıya alınana kadar (bir await ifadesine ulaşılarak) ya da sona erene kadar değerlendirilir, bu da dönüş göreviyle birlikte çağrı yapana döndürülür.The async function body is then evaluated until it is either suspended (by reaching an await expression) or terminates, at which point control is returned to the caller, along with the return task.

Async işlevinin gövdesi sonlandırıldığında, geri dönüş görevi tamamlanmamış durumdan çıkarılır:When the body of the async function terminates, the return task is moved out of the incomplete state:

  • İşlev gövdesi bir dönüş ifadesine veya gövdenin sonuna ulaşılması sonucu olarak sonlandığında, herhangi bir sonuç değeri, başarılı durumuna yerleştirilen dönüş görevine kaydedilir.If the function body terminates as the result of reaching a return statement or the end of the body, any result value is recorded in the return task, which is put into a succeeded state.
  • İşlev gövdesi yakalanamayan bir özel durum (throw) sonucu olarak sonlandığında, özel durum hatalı duruma yerleştirilen geri dönüş görevine kaydedilir.If the function body terminates as the result of an uncaught exception (The throw statement) the exception is recorded in the return task which is put into a faulted state.

Void döndüren zaman uyumsuz bir işlevin değerlendirmesiEvaluation of a void-returning async function

Async işlevinin dönüş türü ise, void değerlendirme yukarıdan aşağıdaki şekilde farklılık gösterir: hiçbir görev döndürülmediği için, işlev geçerli iş parçacığının eşitleme bağlamına tamamlanma ve özel durumları iletişim kurar.If the return type of the async function is void, evaluation differs from the above in the following way: Because no task is returned, the function instead communicates completion and exceptions to the current thread's synchronization context. Eşitleme bağlamının tam tanımı uygulamaya bağımlıdır, ancak geçerli iş parçacığının çalıştırıldığı "nerede" gösterimidir.The exact definition of synchronization context is implementation-dependent, but is a representation of "where" the current thread is running. Bir void döndüren zaman uyumsuz işlevin değerlendirilmesi, başarıyla tamamlandığında veya yakalanamayan bir özel durumun oluşturulmasına neden olduğunda eşitleme bağlamına bildirim gönderilir.The synchronization context is notified when evaluation of a void-returning async function commences, completes successfully, or causes an uncaught exception to be thrown.

Bu, bağlamın altında kaç tane void döndüren zaman uyumsuz işlev çalıştığını izlemeye ve bunlardan gelen özel durumların nasıl yayabileceğine karar vermesine olanak tanır.This allows the context to keep track of how many void-returning async functions are running under it, and to decide how to propagate exceptions coming out of them.