Podstawowe pojęciaBasic concepts

Uruchamianie aplikacjiApplication Startup

Zestaw, który ma punkt wejścia , nosi nazwę aplikacji.An assembly that has an entry point is called an application. Po uruchomieniu aplikacji zostanie utworzona nowa domena aplikacji .When an application is run, a new application domain is created. Kilka różnych wystąpień aplikacji może istnieć na tym samym komputerze w tym samym czasie, a każda z nich ma własną domenę aplikacji.Several different instantiations of an application may exist on the same machine at the same time, and each has its own application domain.

Domena aplikacji umożliwia izolację aplikacji, działając jako kontener dla stanu aplikacji.An application domain enables application isolation by acting as a container for application state. Domena aplikacji pełni rolę kontenera i granicy dla typów zdefiniowanych w aplikacji i używanych przez niego bibliotek klas.An application domain acts as a container and boundary for the types defined in the application and the class libraries it uses. Typy ładowane do jednej domeny aplikacji różnią się od tego samego typu, który został załadowany do innej domeny aplikacji, a wystąpienia obiektów nie są bezpośrednio udostępniane między domenami aplikacji.Types loaded into one application domain are distinct from the same type loaded into another application domain, and instances of objects are not directly shared between application domains. Na przykład Każda domena aplikacji ma własną kopię zmiennych statycznych dla tych typów, a Konstruktor statyczny dla typu jest uruchamiany maksymalnie raz dla każdej domeny aplikacji.For instance, each application domain has its own copy of static variables for these types, and a static constructor for a type is run at most once per application domain. Implementacje mogą być bezpłatne, aby zapewnić zasady i mechanizmy specyficzne dla implementacji dotyczące tworzenia i niszczenia domen aplikacji.Implementations are free to provide implementation-specific policy or mechanisms for the creation and destruction of application domains.

Uruchamianie aplikacji występuje, gdy środowisko wykonawcze wywołuje wydaną metodę, która jest określana jako punkt wejścia aplikacji.Application startup occurs when the execution environment calls a designated method, which is referred to as the application's entry point. Ta metoda punktu wejścia ma zawsze nazwę Maini może mieć jeden z następujących sygnatur:This entry point method is always named Main, and can have one of the following signatures:

static void Main() {...}

static void Main(string[] args) {...}

static int Main() {...}

static int Main(string[] args) {...}

Jak pokazano, punkt wejścia może opcjonalnie zwrócić wartość int.As shown, the entry point may optionally return an int value. Ta wartość zwracana jest używana podczas kończenia aplikacji (zakończenie aplikacji).This return value is used in application termination (Application termination).

Punkt wejścia może opcjonalnie mieć jeden parametr formalny.The entry point may optionally have one formal parameter. Parametr może mieć dowolną nazwę, ale typem parametru musi być string[].The parameter may have any name, but the type of the parameter must be string[]. Jeśli parametr formalny jest obecny, środowisko wykonawcze tworzy i przekazuje argument string[] zawierający argumenty wiersza polecenia, które zostały określone podczas uruchamiania aplikacji.If the formal parameter is present, the execution environment creates and passes a string[] argument containing the command-line arguments that were specified when the application was started. Argument string[] nigdy nie ma wartości null, ale może mieć długość zero, jeśli nie określono żadnych argumentów wiersza polecenia.The string[] argument is never null, but it may have a length of zero if no command-line arguments were specified.

Ponieważ C# obsługuje Przeciążenie metod, Klasa lub struktura może zawierać wiele definicji niektórych metod, pod warunkiem, że każda z nich ma inną sygnaturę.Since C# supports method overloading, a class or struct may contain multiple definitions of some method, provided each has a different signature. Jednak w ramach jednego programu żadna Klasa lub struktura nie może zawierać więcej niż jednej metody o nazwie Main której definicja kwalifikuje się do użycia jako punkt wejścia aplikacji.However, within a single program, no class or struct may contain more than one method called Main whose definition qualifies it to be used as an application entry point. Inne przeciążone wersje Main są dozwolone, jednak pod warunkiem, że mają więcej niż jeden parametr, lub tylko ich parametr jest inny niż typ string[].Other overloaded versions of Main are permitted, however, provided they have more than one parameter, or their only parameter is other than type string[].

Aplikacja może składać się z wielu klas lub struktur.An application can be made up of multiple classes or structs. Istnieje możliwość, że więcej niż jedna z tych klas lub struktur będzie zawierać metodę o nazwie Main której definicja kwalifikuje się do użycia jako punkt wejścia aplikacji.It is possible for more than one of these classes or structs to contain a method called Main whose definition qualifies it to be used as an application entry point. W takich przypadkach mechanizm zewnętrzny (na przykład opcja kompilatora wiersza polecenia) musi zostać użyty do wybrania jednej z tych Main metod jako punktu wejścia.In such cases, an external mechanism (such as a command-line compiler option) must be used to select one of these Main methods as the entry point.

W C#programie każda metoda musi być zdefiniowana jako element członkowski klasy lub struktury.In C#, every method must be defined as a member of a class or struct. Zwykle zadeklarowana dostępność (zadeklarowana dostępność) metody jest określana przez Modyfikatory dostępu (Modyfikatory dostępu) określone w swojej deklaracji, a podobnie zadeklarowana dostępność typu jest określana przez Modyfikatory dostępu określone w jego deklaracji.Ordinarily, the declared accessibility (Declared accessibility) of a method is determined by the access modifiers (Access modifiers) specified in its declaration, and similarly the declared accessibility of a type is determined by the access modifiers specified in its declaration. Aby można było wywołać daną metodę danego typu, zarówno typ, jak i element członkowski muszą być dostępne.In order for a given method of a given type to be callable, both the type and the member must be accessible. Jednak punkt wejścia aplikacji jest szczególnym przypadkiem.However, the application entry point is a special case. W szczególności środowisko wykonawcze może uzyskać dostęp do punktu wejścia aplikacji niezależnie od jego zadeklarowanej dostępności i bez względu na zadeklarowaną dostępność jego deklaracji typu.Specifically, the execution environment can access the application's entry point regardless of its declared accessibility and regardless of the declared accessibility of its enclosing type declarations.

Metoda punktu wejścia aplikacji nie może znajdować się w deklaracji klasy ogólnej.The application entry point method may not be in a generic class declaration.

We wszystkich innych aspektach metody punktu wejścia zachowują się jak te, które nie są punktami wejścia.In all other respects, entry point methods behave like those that are not entry points.

Zakończenie aplikacjiApplication termination

Zakończenie aplikacji zwraca kontrolę do środowiska wykonawczego.Application termination returns control to the execution environment.

Jeśli zwracany typ metody punktu wejścia aplikacji jest int, zwracana wartość służy jako kod stanu zakończeniaaplikacji.If the return type of the application's entry point method is int, the value returned serves as the application's termination status code. Celem tego kodu jest umożliwienie komunikacji sukcesu lub niepowodzenia środowiska wykonawczego.The purpose of this code is to allow communication of success or failure to the execution environment.

Jeśli zwracanym typem metody punktu wejścia jest void, osiągnięcie prawego nawiasu klamrowego (}), który kończy tę metodę, lub wykonywanie instrukcji return, która nie ma wyrażenia, powoduje kod stanu zakończenia 0.If the return type of the entry point method is void, reaching the right brace (}) which terminates that method, or executing a return statement that has no expression, results in a termination status code of 0.

Przed zakończeniem działania aplikacji są wywoływane destruktory dla wszystkich obiektów, które nie zostały jeszcze pobrane jako elementy bezużyteczne, chyba że takie oczyszczanie zostało pominięte (przez wywołanie metody biblioteki GC.SuppressFinalize, na przykład).Prior to an application's termination, destructors for all of its objects that have not yet been garbage collected are called, unless such cleanup has been suppressed (by a call to the library method GC.SuppressFinalize, for example).

DeklaracjeDeclarations

Deklaracje w C# programie definiują elementy składowe programu.Declarations in a C# program define the constituent elements of the program. C#programy są zorganizowane przy użyciu przestrzeni nazw (przestrzenie nazw), które mogą zawierać deklaracje typów i zagnieżdżone deklaracje przestrzeni nazw.C# programs are organized using namespaces (Namespaces), which can contain type declarations and nested namespace declarations. Deklaracje typów (deklaracje typów) służą do definiowania klas (klas), struktur (struktur), interfejsów (interfejsów), wyliczeniowych (wyliczeniowych) i delegatów (delegatów).Type declarations (Type declarations) are used to define classes (Classes), structs (Structs), interfaces (Interfaces), enums (Enums), and delegates (Delegates). Rodzaje elementów członkowskich dozwolone w deklaracji typu zależą od formy deklaracji typu.The kinds of members permitted in a type declaration depend on the form of the type declaration. Na przykład deklaracji klasy mogą zawierać deklaracje dla stałych (stałych), pól (pól), metod (metod), właściwości (Właściwości), zdarzeń (zdarzeń), indeksatorów (indeksatorów), operatorów (operatorów), konstruktorów wystąpień (konstruktorów wystąpień), konstruktorów statycznych (konstruktorów statycznych), destruktorów (destruktorów) i typów zagnieżdżonych (typy zagnieżdżone).For instance, class declarations can contain declarations for constants (Constants), fields (Fields), methods (Methods), properties (Properties), events (Events), indexers (Indexers), operators (Operators), instance constructors (Instance constructors), static constructors (Static constructors), destructors (Destructors), and nested types (Nested types).

Deklaracja definiuje nazwę w obszarze deklaracji , do którego należy deklaracja.A declaration defines a name in the declaration space to which the declaration belongs. Z wyjątkiem przeciążonych elementów członkowskich (sygnatur i Przeciążenie), jest to błąd czasu kompilacji, który ma dwie lub więcej deklaracji, które wprowadzają elementy członkowskie o tej samej nazwie w obszarze deklaracji.Except for overloaded members (Signatures and overloading), it is a compile-time error to have two or more declarations that introduce members with the same name in a declaration space. Nie jest możliwe, aby miejsce deklaracji zawierało różne rodzaje składowych o tej samej nazwie.It is never possible for a declaration space to contain different kinds of members with the same name. Na przykład obszar deklaracji nigdy nie może zawierać pola i metody o tej samej nazwie.For example, a declaration space can never contain a field and a method by the same name.

Istnieje kilka różnych typów obszarów deklaracji, zgodnie z opisem w poniższej tabeli.There are several different types of declaration spaces, as described in the following.

  • W ramach wszystkich plików źródłowych programu namespace_member_declarations bez otaczających namespace_declaration są członkami pojedynczej, połączonej przestrzeni deklaracji nazywanej przestrzenią globalną deklaracji.Within all source files of a program, namespace_member_declarations with no enclosing namespace_declaration are members of a single combined declaration space called the global declaration space.
  • W ramach wszystkich plików źródłowych programu namespace_member_declarations w namespace_declarations, które mają taką samą w pełni kwalifikowaną nazwę przestrzeni nazw, są członkami pojedynczej złożonej deklaracji.Within all source files of a program, namespace_member_declarations within namespace_declarations that have the same fully qualified namespace name are members of a single combined declaration space.
  • Każda klasa, struktura lub Deklaracja interfejsu tworzy nową przestrzeń deklaracji.Each class, struct, or interface declaration creates a new declaration space. Nazwy są wprowadzane do tego obszaru deklaracji za poorednictwem class_member_declarations, struct_member_declarations, interface_member_declarations lub type_parameters.Names are introduced into this declaration space through class_member_declarations, struct_member_declarations, interface_member_declarations, or type_parameters. Z wyjątkiem deklaracji konstruktora wystąpień przeciążonych i deklaracji konstruktora statycznego Klasa lub struktura nie może zawierać deklaracji składowej o takiej samej nazwie jak Klasa lub struktura.Except for overloaded instance constructor declarations and static constructor declarations, a class or struct cannot contain a member declaration with the same name as the class or struct. Klasa, struktura lub interfejs umożliwia deklarację przeciążonych metod i indeksatorów.A class, struct, or interface permits the declaration of overloaded methods and indexers. Ponadto Klasa lub struktura zezwala na deklarację konstruktorów przeciążonych wystąpień i operatorów.Furthermore, a class or struct permits the declaration of overloaded instance constructors and operators. Na przykład Klasa, struktura lub interfejs może zawierać wiele deklaracji metody o tej samej nazwie, pod warunkiem, że te deklaracje metod różnią się w sygnaturze (sygnatur i Przeciążenie).For example, a class, struct, or interface may contain multiple method declarations with the same name, provided these method declarations differ in their signature (Signatures and overloading). Należy zauważyć, że klasy bazowe nie przyczyniają się do przestrzeni deklaracji klasy, a interfejsy podstawowe nie przyczyniają się do obszaru deklaracji interfejsu.Note that base classes do not contribute to the declaration space of a class, and base interfaces do not contribute to the declaration space of an interface. W ten sposób Klasa pochodna lub interfejs może zadeklarować element członkowski o takiej samej nazwie jak Dziedziczony element członkowski.Thus, a derived class or interface is allowed to declare a member with the same name as an inherited member. Członek ten jest wymieniony do ukrycia dziedziczonego elementu członkowskiego.Such a member is said to hide the inherited member.
  • Każda deklaracja delegata tworzy nową przestrzeń deklaracji.Each delegate declaration creates a new declaration space. Nazwy są wprowadzane do tego obszaru deklaracji za poorednictwem parametrów formalnych (fixed_parameters i parameter_arrays) i type_parameters.Names are introduced into this declaration space through formal parameters (fixed_parameters and parameter_arrays) and type_parameters.
  • Każda deklaracja wyliczenia tworzy nową przestrzeń deklaracji.Each enumeration declaration creates a new declaration space. Nazwy są wprowadzane do tego obszaru deklaracji za poorednictwem enum_member_declarations.Names are introduced into this declaration space through enum_member_declarations.
  • Każda deklaracja metody, deklaracja indeksatora, deklaracja operatora, deklaracja konstruktora wystąpień i funkcja anonimowa tworzą nowe miejsce deklaracji zwane przestrzenią lokalnej deklaracji zmiennej.Each method declaration, indexer declaration, operator declaration, instance constructor declaration and anonymous function creates a new declaration space called a local variable declaration space. Nazwy są wprowadzane do tego obszaru deklaracji za poorednictwem parametrów formalnych (fixed_parameters i parameter_arrays) i type_parameters.Names are introduced into this declaration space through formal parameters (fixed_parameters and parameter_arrays) and type_parameters. Treść składowej funkcji lub funkcji anonimowej, jeśli istnieje, jest uznawana za zagnieżdżoną w obrębie przestrzeni deklaracji zmiennej lokalnej.The body of the function member or anonymous function, if any, is considered to be nested within the local variable declaration space. Jest to błąd dla przestrzeni lokalnej deklaracji zmiennej i zagnieżdżona przestrzeń deklaracji zmiennej lokalnej, która zawiera elementy o tej samej nazwie.It is an error for a local variable declaration space and a nested local variable declaration space to contain elements with the same name. W tym celu w ramach zagnieżdżonej deklaracji nie można zadeklarować zmiennej lokalnej ani stałej o takiej samej nazwie jak zmienna lokalna lub stała w otaczającym obszarze deklaracji.Thus, within a nested declaration space it is not possible to declare a local variable or constant with the same name as a local variable or constant in an enclosing declaration space. Możliwe jest, aby dwie spacje deklaracji zawierały elementy o tej samej nazwie, o ile nie zawiera ona żadnej z nich.It is possible for two declaration spaces to contain elements with the same name as long as neither declaration space contains the other.
  • Każdy blok lub switch_block , jak również instrukcja for, foreach i using , tworzy przestrzeń lokalnej deklaracji zmiennej dla zmiennych lokalnych i stałych lokalnych.Each block or switch_block , as well as a for, foreach and using statement, creates a local variable declaration space for local variables and local constants . Nazwy są wprowadzane do tego obszaru deklaracji za poorednictwem local_variable_declarations i local_constant_declarations.Names are introduced into this declaration space through local_variable_declarations and local_constant_declarations. Należy zauważyć, że Bloki występujące jako lub w treści elementu członkowskiego funkcji lub funkcji anonimowej są zagnieżdżone w obszarze deklaracji zmiennej lokalnej zadeklarowanej przez te funkcje dla ich parametrów.Note that blocks that occur as or within the body of a function member or anonymous function are nested within the local variable declaration space declared by those functions for their parameters. W rezultacie jest to błąd, na przykład, Metoda ze zmienną lokalną i parametr o tej samej nazwie.Thus it is an error to have e.g. a method with a local variable and a parameter of the same name.
  • Każdy blok lub switch_block tworzy oddzielne miejsce deklaracji dla etykiet.Each block or switch_block creates a separate declaration space for labels. Nazwy są wprowadzane do tego obszaru deklaracji za pomocą labeled_statements, a nazwy są przywoływane przez goto_statements.Names are introduced into this declaration space through labeled_statements, and the names are referenced through goto_statements. Miejsce deklaracji etykiety bloku zawiera wszystkie zagnieżdżone bloki.The label declaration space of a block includes any nested blocks. W tym celu w bloku zagnieżdżonym nie można zadeklarować etykiety o takiej samej nazwie jak etykieta w otaczającym bloku.Thus, within a nested block it is not possible to declare a label with the same name as a label in an enclosing block.

Kolejność tekstu, w której zadeklarowane są nazwy, zazwyczaj nie ma znaczenia.The textual order in which names are declared is generally of no significance. W szczególności kolejność tekstu nie jest istotna dla deklaracji i użycia przestrzeni nazw, stałych, metod, właściwości, zdarzeń, indeksatorów, konstruktorów wystąpień, destruktorów, konstruktorów statycznych i typów.In particular, textual order is not significant for the declaration and use of namespaces, constants, methods, properties, events, indexers, operators, instance constructors, destructors, static constructors, and types. Kolejność deklaracji jest istotna w następujący sposób:Declaration order is significant in the following ways:

  • Kolejność deklaracji dla deklaracji pola i deklaracji zmiennych lokalnych określa kolejność, w jakiej są wykonywane ich inicjatory (jeśli istnieją).Declaration order for field declarations and local variable declarations determines the order in which their initializers (if any) are executed.
  • Zmienne lokalne muszą być zdefiniowane przed użyciem (zakresy).Local variables must be defined before they are used (Scopes).
  • Kolejność deklaracji deklaracji elementu członkowskiego wyliczenia (składowe wyliczenia) jest istotna, gdy wartości constant_expression są pomijane.Declaration order for enum member declarations (Enum members) is significant when constant_expression values are omitted.

Obszar deklaracji przestrzeni nazw to "otwarta zakończona", a dwie deklaracje przestrzeni nazw o tej samej w pełni kwalifikowanej nazwie współtworzą ten sam obszar deklaracji.The declaration space of a namespace is "open ended", and two namespace declarations with the same fully qualified name contribute to the same declaration space. Na przykład:For example

namespace Megacorp.Data
{
    class Customer
    {
        ...
    }
}

namespace Megacorp.Data
{
    class Order
    {
        ...
    }
}

Powyższe dwie deklaracje przestrzeni nazw składają się na ten sam obszar deklaracji, w tym przypadku deklarując dwie klasy z w pełni kwalifikowanymi nazwami Megacorp.Data.Customer i Megacorp.Data.Order.The two namespace declarations above contribute to the same declaration space, in this case declaring two classes with the fully qualified names Megacorp.Data.Customer and Megacorp.Data.Order. Ponieważ dwie deklaracje przyczyniają się do tego samego obszaru deklaracji, powodowały to błąd czasu kompilacji, jeśli każda z nich zawiera deklarację klasy o tej samej nazwie.Because the two declarations contribute to the same declaration space, it would have caused a compile-time error if each contained a declaration of a class with the same name.

Jak określono powyżej, obszar deklaracji bloku zawiera wszystkie zagnieżdżone bloki.As specified above, the declaration space of a block includes any nested blocks. W związku z tym w poniższym przykładzie metody F i G powodują błąd czasu kompilacji, ponieważ nazwa i jest zadeklarowana w bloku zewnętrznym i nie może być ponownie zadeklarowana w bloku wewnętrznym.Thus, in the following example, the F and G methods result in a compile-time error because the name i is declared in the outer block and cannot be redeclared in the inner block. Jednakże metody H i I są prawidłowe, ponieważ dwa isą zadeklarowane w oddzielnych blokach niezagnieżdżonych.However, the H and I methods are valid since the two i's are declared in separate non-nested blocks.

class A
{
    void F() {
        int i = 0;
        if (true) {
            int i = 1;            
        }
    }

    void G() {
        if (true) {
            int i = 0;
        }
        int i = 1;                
    }

    void H() {
        if (true) {
            int i = 0;
        }
        if (true) {
            int i = 1;
        }
    }

    void I() {
        for (int i = 0; i < 10; i++)
            H();
        for (int i = 0; i < 10; i++)
            H();
    }
}

MembersMembers

Przestrzenie nazw i typy mają składowe.Namespaces and types have members. Elementy członkowskie jednostki są ogólnie dostępne przy użyciu kwalifikowanej nazwy, która rozpoczyna się od odwołania do jednostki, po której następuje token ".", po którym następuje nazwa elementu członkowskiego.The members of an entity are generally available through the use of a qualified name that starts with a reference to the entity, followed by a "." token, followed by the name of the member.

Elementy członkowskie typu są zadeklarowane w deklaracji typu lub dziedziczone z klasy bazowej typu.Members of a type are either declared in the type declaration or inherited from the base class of the type. Gdy typ dziedziczy z klasy bazowej, wszystkie elementy członkowskie klasy podstawowej, z wyjątkiem konstruktorów wystąpień, destruktorów i konstruktorów statycznych, stają się elementami członkowskimi typu pochodnego.When a type inherits from a base class, all members of the base class, except instance constructors, destructors and static constructors, become members of the derived type. Zadeklarowana dostępność składowej klasy bazowej nie kontroluje, czy element członkowski jest dziedziczony — dziedziczenie rozciąga się do dowolnego elementu członkowskiego, który nie jest konstruktorem wystąpienia, konstruktorem statycznym ani destruktorem.The declared accessibility of a base class member does not control whether the member is inherited—inheritance extends to any member that isn't an instance constructor, static constructor, or destructor. Jednak Dziedziczony element członkowski może nie być dostępny w typie pochodnym, z powodu jego zadeklarowanej dostępności (zadeklarowanej dostępności) lub jest ukryty przez deklarację w samym typie (ukrywając poprzez dziedziczenie).However, an inherited member may not be accessible in a derived type, either because of its declared accessibility (Declared accessibility) or because it is hidden by a declaration in the type itself (Hiding through inheritance).

Elementy członkowskie przestrzeni nazwNamespace members

Przestrzenie nazw i typy, które nie mają otaczającej przestrzeni nazw, są elementami członkowskimi globalnej przestrzeni nazw.Namespaces and types that have no enclosing namespace are members of the global namespace. Odnosi się to bezpośrednio do nazw zadeklarowanych w globalnej przestrzeni deklaracji.This corresponds directly to the names declared in the global declaration space.

Przestrzenie nazw i typy zadeklarowane w przestrzeni nazw są elementami członkowskimi tej przestrzeni nazw.Namespaces and types declared within a namespace are members of that namespace. Odnosi się to bezpośrednio do nazw zadeklarowanych w obszarze deklaracji przestrzeni nazw.This corresponds directly to the names declared in the declaration space of the namespace.

Przestrzenie nazw nie mają ograniczeń dostępu.Namespaces have no access restrictions. Nie można zadeklarować prywatnych, chronionych lub wewnętrznych przestrzeni nazw, a nazwy przestrzeni nazw są zawsze publicznie dostępne.It is not possible to declare private, protected, or internal namespaces, and namespace names are always publicly accessible.

Elementy członkowskie strukturyStruct members

Elementy członkowskie struktury to elementy członkowskie zadeklarowane w strukturze i składowe dziedziczone z bezpośredniej klasy podstawowej struktury System.ValueType i pośredniej klasy bazowej object.The members of a struct are the members declared in the struct and the members inherited from the struct's direct base class System.ValueType and the indirect base class object.

Elementy członkowskie typu prostego odpowiadają bezpośrednio elementom członkowskim typu struct, które są aliase według typu prostego:The members of a simple type correspond directly to the members of the struct type aliased by the simple type:

  • Członkowie sbyte są członkami struktury System.SByte.The members of sbyte are the members of the System.SByte struct.
  • Członkowie byte są członkami struktury System.Byte.The members of byte are the members of the System.Byte struct.
  • Członkowie short są członkami struktury System.Int16.The members of short are the members of the System.Int16 struct.
  • Członkowie ushort są członkami struktury System.UInt16.The members of ushort are the members of the System.UInt16 struct.
  • Członkowie int są członkami struktury System.Int32.The members of int are the members of the System.Int32 struct.
  • Członkowie uint są członkami struktury System.UInt32.The members of uint are the members of the System.UInt32 struct.
  • Członkowie long są członkami struktury System.Int64.The members of long are the members of the System.Int64 struct.
  • Członkowie ulong są członkami struktury System.UInt64.The members of ulong are the members of the System.UInt64 struct.
  • Członkowie char są członkami struktury System.Char.The members of char are the members of the System.Char struct.
  • Członkowie float są członkami struktury System.Single.The members of float are the members of the System.Single struct.
  • Członkowie double są członkami struktury System.Double.The members of double are the members of the System.Double struct.
  • Członkowie decimal są członkami struktury System.Decimal.The members of decimal are the members of the System.Decimal struct.
  • Członkowie bool są członkami struktury System.Boolean.The members of bool are the members of the System.Boolean struct.

Elementy członkowskie wyliczeniaEnumeration members

Elementy członkowskie wyliczenia to stałe zadeklarowane w wyliczeniu i składowe dziedziczone z bezpośredniej klasy podstawowej wyliczenia System.Enum i pośrednich klas bazowych System.ValueType i object.The members of an enumeration are the constants declared in the enumeration and the members inherited from the enumeration's direct base class System.Enum and the indirect base classes System.ValueType and object.

Elementy członkowskie klasyClass members

Elementy członkowskie klasy są składowymi zadeklarowanymi w klasie i składowymi dziedziczonymi z klasy podstawowej (z wyjątkiem klasy object, która nie ma klasy bazowej).The members of a class are the members declared in the class and the members inherited from the base class (except for class object which has no base class). Elementy członkowskie dziedziczone z klasy bazowej obejmują stałe, pola, metody, właściwości, zdarzenia, indeksatory, operatory i typy klasy bazowej, ale nie konstruktorów wystąpień, destruktorów i konstruktorów statycznych klasy bazowej.The members inherited from the base class include the constants, fields, methods, properties, events, indexers, operators, and types of the base class, but not the instance constructors, destructors and static constructors of the base class. Składowe klasy bazowej są dziedziczone bez względu na ich dostępność.Base class members are inherited without regard to their accessibility.

Deklaracja klasy może zawierać deklaracje stałych, pól, metod, właściwości, zdarzeń, indeksatorów, operatorów, konstruktorów wystąpień, destruktorów, konstruktorów statycznych i typów.A class declaration may contain declarations of constants, fields, methods, properties, events, indexers, operators, instance constructors, destructors, static constructors and types.

Elementy członkowskie object i string odpowiadają bezpośrednio członkom typów klas, których aliasy:The members of object and string correspond directly to the members of the class types they alias:

  • Członkowie object są członkami klasy System.Object.The members of object are the members of the System.Object class.
  • Członkowie string są członkami klasy System.String.The members of string are the members of the System.String class.

Elementy członkowskie interfejsuInterface members

Elementy członkowskie interfejsu są elementami zadeklarowanymi w interfejsie i we wszystkich interfejsach podstawowych interfejsu.The members of an interface are the members declared in the interface and in all base interfaces of the interface. Elementy członkowskie w klasie object nie są, ściśle mówiące, członkami dowolnego interfejsu (elementy członkowskie interfejsu).The members in class object are not, strictly speaking, members of any interface (Interface members). Jednakże elementy członkowskie klasy object są dostępne za pośrednictwem wyszukiwania elementów członkowskich w dowolnym typie interfejsu (wyszukiwanie elementu członkowskiego).However, the members in class object are available via member lookup in any interface type (Member lookup).

Elementy członkowskie tablicyArray members

Elementy członkowskie tablicy są elementami dziedziczonymi z klasy System.Array.The members of an array are the members inherited from class System.Array.

Deleguj członkówDelegate members

Elementy członkowskie delegata są elementami dziedziczonymi z klasy System.Delegate.The members of a delegate are the members inherited from class System.Delegate.

Dostęp do elementu członkowskiegoMember access

Deklaracje elementów członkowskich umożliwiają kontrolę dostępu do elementów członkowskich.Declarations of members allow control over member access. Dostępność elementu członkowskiego jest określana przez zadeklarowane dostępność (zadeklarowane dostępność) elementu członkowskiego połączonego z ułatwieniami dostępu do typu, jeśli istnieje.The accessibility of a member is established by the declared accessibility (Declared accessibility) of the member combined with the accessibility of the immediately containing type, if any.

Gdy dostęp do określonego elementu członkowskiego jest dozwolony, członek jest uznawany za dostępny.When access to a particular member is allowed, the member is said to be accessible. Z drugiej strony, gdy dostęp do określonego elementu członkowskiego jest niedozwolony, członek jest uznawany za niedostępny.Conversely, when access to a particular member is disallowed, the member is said to be inaccessible. Dostęp do elementu członkowskiego jest dozwolony, gdy lokalizacja tekstowa, w której odbywa się dostęp, jest uwzględniona w domenie dostępności (domeny ułatwieńdostępu) elementu członkowskiego.Access to a member is permitted when the textual location in which the access takes place is included in the accessibility domain (Accessibility domains) of the member.

Zadeklarowane ułatwienia dostępuDeclared accessibility

Zadeklarowana dostępność elementu członkowskiego może być jedną z następujących czynności:The declared accessibility of a member can be one of the following:

  • Public, który jest wybierany przez dołączenie modyfikatora public w deklaracji elementu członkowskiego.Public, which is selected by including a public modifier in the member declaration. Intuicyjne znaczenie public ma wartość "dostęp nieograniczony".The intuitive meaning of public is "access not limited".
  • Chroniony, który jest wybierany przez dołączenie modyfikatora protected w deklaracji elementu członkowskiego.Protected, which is selected by including a protected modifier in the member declaration. Intuicyjne znaczenie protected jest "dostęp ograniczony do klasy zawierającej lub typów pochodzących od klasy zawierającej".The intuitive meaning of protected is "access limited to the containing class or types derived from the containing class".
  • Wewnętrzna, która jest wybierana przez dołączenie modyfikatora internal w deklaracji elementu członkowskiego.Internal, which is selected by including an internal modifier in the member declaration. Intuicyjne znaczenie internal jest "dostęp ograniczony do tego programu".The intuitive meaning of internal is "access limited to this program".
  • Chroniona wewnętrznie (czyli chroniona lub wewnętrzna), która jest wybierana przez uwzględnienie zarówno protected, jak i modyfikatora internal w deklaracji elementu członkowskiego.Protected internal (meaning protected or internal), which is selected by including both a protected and an internal modifier in the member declaration. Intuicyjne znaczenie protected internal jest "dostęp ograniczony do tego programu lub typów pochodzących od klasy zawierającej".The intuitive meaning of protected internal is "access limited to this program or types derived from the containing class".
  • Prywatny, który jest wybierany przez dołączenie modyfikatora private w deklaracji elementu członkowskiego.Private, which is selected by including a private modifier in the member declaration. Intuicyjne znaczenie private jest "dostęp ograniczony do typu zawierającego".The intuitive meaning of private is "access limited to the containing type".

W zależności od kontekstu, w którym jest realizowana Deklaracja elementu członkowskiego, dozwolone są tylko niektóre typy zadeklarowanych ułatwień dostępu.Depending on the context in which a member declaration takes place, only certain types of declared accessibility are permitted. Ponadto, gdy Deklaracja elementu członkowskiego nie zawiera żadnych modyfikatorów dostępu, kontekst, w którym odbywa się deklaracja, określa domyślny dostępną dostępność.Furthermore, when a member declaration does not include any access modifiers, the context in which the declaration takes place determines the default declared accessibility.

  • Przestrzenie nazw niejawnie mają public zadeklarowane ułatwienia dostępu.Namespaces implicitly have public declared accessibility. W deklaracjach przestrzeni nazw nie są dozwolone Modyfikatory dostępu.No access modifiers are allowed on namespace declarations.
  • Typy zadeklarowane w jednostkach kompilacji lub przestrzeniach nazw mogą mieć public lub internal zadeklarowane ułatwienia dostępu i domyślne do internal zadeklarowanej dostępności.Types declared in compilation units or namespaces can have public or internal declared accessibility and default to internal declared accessibility.
  • Elementy członkowskie klasy mogą mieć dowolne pięć rodzajów zadeklarowanych ułatwień dostępu i wartości domyślnych, aby private zadeklarowane ułatwienia dostępu.Class members can have any of the five kinds of declared accessibility and default to private declared accessibility. (Należy zauważyć, że typ zadeklarowany jako element członkowski klasy może mieć którykolwiek z pięciu rodzajów zadeklarowanej dostępności, podczas gdy typ zadeklarowany jako składowa przestrzeni nazw może mieć tylko public lub internal zadeklarowane ułatwienia dostępu).(Note that a type declared as a member of a class can have any of the five kinds of declared accessibility, whereas a type declared as a member of a namespace can have only public or internal declared accessibility.)
  • Elementy członkowskie struktury mogą mieć public, internallub private zadeklarowane ułatwienia dostępu i domyślne do private zadeklarowanej dostępności, ponieważ struktury są niejawnie zapieczętowane.Struct members can have public, internal, or private declared accessibility and default to private declared accessibility because structs are implicitly sealed. Elementy członkowskie struktury wprowadzone w strukturze (która nie jest dziedziczona przez tę strukturę) nie mogą mieć protected ani protected internal zadeklarowanej dostępności.Struct members introduced in a struct (that is, not inherited by that struct) cannot have protected or protected internal declared accessibility. (Należy zauważyć, że typ zadeklarowany jako element członkowski struktury może mieć public, internallub private zadeklarowanej dostępności, podczas gdy typ zadeklarowany jako składowa przestrzeni nazw może mieć tylko public lub internal zadeklarowane ułatwienia dostępu.)(Note that a type declared as a member of a struct can have public, internal, or private declared accessibility, whereas a type declared as a member of a namespace can have only public or internal declared accessibility.)
  • Elementy członkowskie interfejsu niejawnie mają public zadeklarowane ułatwienia dostępu.Interface members implicitly have public declared accessibility. W deklaracjach składowych interfejsu nie można używać modyfikatorów dostępu.No access modifiers are allowed on interface member declarations.
  • Elementy członkowskie wyliczenia niejawnie mają public zadeklarowane ułatwienia dostępu.Enumeration members implicitly have public declared accessibility. Modyfikatory dostępu są niedozwolone w deklaracjach składowych wyliczenia.No access modifiers are allowed on enumeration member declarations.

Domeny ułatwień dostępuAccessibility domains

Domena dostępności elementu członkowskiego składa się z sekcji (ewentualnie rozłączonych) tekstu programu, w którym dozwolony jest dostęp do elementu członkowskiego.The accessibility domain of a member consists of the (possibly disjoint) sections of program text in which access to the member is permitted. Aby można było zdefiniować domenę dostępności elementu członkowskiego, członek jest nazywany najwyższego poziomu , jeśli nie jest zadeklarowany w obrębie typu, a element członkowski jest określany jako zagnieżdżony , jeśli jest zadeklarowany w innym typie.For purposes of defining the accessibility domain of a member, a member is said to be top-level if it is not declared within a type, and a member is said to be nested if it is declared within another type. Ponadto tekst programu w programie jest zdefiniowany jako cały tekst programu zawarty we wszystkich plikach źródłowych programu, a tekst programu typu jest zdefiniowany jako cały tekst programu zawarty w type_declarations tego typu (w tym, ewentualnie, typy, które są zagnieżdżone w typie).Furthermore, the program text of a program is defined as all program text contained in all source files of the program, and the program text of a type is defined as all program text contained in the type_declarations of that type (including, possibly, types that are nested within the type).

Domena dostępności wstępnie zdefiniowanego typu (na przykład object, intlub double) jest nieograniczona.The accessibility domain of a predefined type (such as object, int, or double) is unlimited.

Domena dostępności niepowiązanego typu najwyższego poziomu T (powiązane i niepowiązane typy) zadeklarowane w programie P definiuje się w następujący sposób:The accessibility domain of a top-level unbound type T (Bound and unbound types) that is declared in a program P is defined as follows:

  • Jeśli deklarowana dostępność T jest public, domena dostępności T jest tekstem programu P i dowolnym programem, który odwołuje się do P.If the declared accessibility of T is public, the accessibility domain of T is the program text of P and any program that references P.
  • Jeśli deklarowana dostępność T jest internal, domena dostępności T jest tekstem programu P.If the declared accessibility of T is internal, the accessibility domain of T is the program text of P.

Z tych definicji wynika, że domena dostępności niepowiązanego typu najwyższego poziomu jest zawsze co najmniej programem tekstowym programu, w którym ten typ jest zadeklarowany.From these definitions it follows that the accessibility domain of a top-level unbound type is always at least the program text of the program in which that type is declared.

Domena dostępności dla konstruowanego typu T<A1, ..., An> jest częścią wspólną domeny dostępności niepowiązanego typu ogólnego T i domen dostępności argumentów typu A1, ..., An.The accessibility domain for a constructed type T<A1, ..., An> is the intersection of the accessibility domain of the unbound generic type T and the accessibility domains of the type arguments A1, ..., An.

Domena dostępności zagnieżdżonego elementu członkowskiego M zadeklarowana w typie T w ramach programu P jest zdefiniowana w następujący sposób (zwracając uwagę, że M może być typem):The accessibility domain of a nested member M declared in a type T within a program P is defined as follows (noting that M itself may possibly be a type):

  • Jeśli deklarowana dostępność M jest public, domena dostępności M jest domeną dostępności T.If the declared accessibility of M is public, the accessibility domain of M is the accessibility domain of T.
  • Jeśli deklarowana dostępność M jest protected internal, niech D być złożeniem tekstu programu P i tekstu programu dowolnego typu pochodzącego od T, który jest zadeklarowany poza P.If the declared accessibility of M is protected internal, let D be the union of the program text of P and the program text of any type derived from T, which is declared outside P. Domena dostępności M jest częścią wspólną domeny dostępności T z D.The accessibility domain of M is the intersection of the accessibility domain of T with D.
  • Jeśli deklarowana dostępność M jest protected, niech D być złożeniem tekstu programu T i tekstu programu dowolnego typu pochodzącego od T.If the declared accessibility of M is protected, let D be the union of the program text of T and the program text of any type derived from T. Domena dostępności M jest częścią wspólną domeny dostępności T z D.The accessibility domain of M is the intersection of the accessibility domain of T with D.
  • Jeśli deklarowana dostępność M jest internal, domena dostępności M jest częścią wspólną domeny dostępności T z tekstem programu P.If the declared accessibility of M is internal, the accessibility domain of M is the intersection of the accessibility domain of T with the program text of P.
  • Jeśli deklarowana dostępność M jest private, domena dostępności M jest tekstem programu T.If the declared accessibility of M is private, the accessibility domain of M is the program text of T.

Z tych definicji następuje, że domena dostępności zagnieżdżonego elementu członkowskiego jest zawsze co najmniej tekstem programu typu, w którym jest zadeklarowany element członkowski.From these definitions it follows that the accessibility domain of a nested member is always at least the program text of the type in which the member is declared. Ponadto, gdy domena dostępności elementu członkowskiego nigdy nie jest większa niż domena dostępności typu, w którym jest zadeklarowany element członkowski.Furthermore, it follows that the accessibility domain of a member is never more inclusive than the accessibility domain of the type in which the member is declared.

W intuicyjnych terminach podczas uzyskiwania dostępu do typu lub elementu członkowskiego M są oceniane następujące kroki, aby upewnić się, że dostęp jest dozwolony:In intuitive terms, when a type or member M is accessed, the following steps are evaluated to ensure that the access is permitted:

  • Po pierwsze, jeśli M jest zadeklarowany w obrębie typu (w przeciwieństwie do jednostki kompilacji lub przestrzeni nazw), wystąpi błąd w czasie kompilacji, jeśli ten typ nie jest dostępny.First, if M is declared within a type (as opposed to a compilation unit or a namespace), a compile-time error occurs if that type is not accessible.
  • Następnie Jeśli M jest public, dostęp jest dozwolony.Then, if M is public, the access is permitted.
  • W przeciwnym razie, jeśli M jest protected internal, dostęp jest dozwolony, jeśli występuje w ramach programu, w którym M jest zadeklarowana, lub jeśli występuje w klasie pochodzącej od klasy, w której M jest zadeklarowana, i odbywa się za pośrednictwem typu klasy pochodnej (chroniony dostęp dla członków wystąpienia).Otherwise, if M is protected internal, the access is permitted if it occurs within the program in which M is declared, or if it occurs within a class derived from the class in which M is declared and takes place through the derived class type (Protected access for instance members).
  • W przeciwnym razie, jeśli M jest protected, dostęp jest dozwolony, jeśli występuje w klasie, w której M jest zadeklarowana, lub jeśli występuje w klasie pochodzącej od klasy, w której M jest zadeklarowana, i odbywa się za pośrednictwem typu klasy pochodnej (chroniony dostęp dla członków wystąpienia).Otherwise, if M is protected, the access is permitted if it occurs within the class in which M is declared, or if it occurs within a class derived from the class in which M is declared and takes place through the derived class type (Protected access for instance members).
  • W przeciwnym razie, jeśli M jest internal, dostęp jest dozwolony, jeśli występuje w ramach programu, w którym M jest zadeklarowana.Otherwise, if M is internal, the access is permitted if it occurs within the program in which M is declared.
  • W przeciwnym razie, jeśli M jest private, dostęp jest dozwolony, jeśli występuje w ramach typu, w którym M jest zadeklarowana.Otherwise, if M is private, the access is permitted if it occurs within the type in which M is declared.
  • W przeciwnym razie typ lub element członkowski jest niedostępny i wystąpi błąd kompilacji.Otherwise, the type or member is inaccessible, and a compile-time error occurs.

w przykładzieIn the example

public class A
{
    public static int X;
    internal static int Y;
    private static int Z;
}

internal class B
{
    public static int X;
    internal static int Y;
    private static int Z;

    public class C
    {
        public static int X;
        internal static int Y;
        private static int Z;
    }

    private class D
    {
        public static int X;
        internal static int Y;
        private static int Z;
    }
}

klasy i składowe mają następujące domeny ułatwień dostępu:the classes and members have the following accessibility domains:

  • Domena dostępności A i A.X jest nieograniczona.The accessibility domain of A and A.X is unlimited.
  • Domena dostępności A.Y, B, B.X, B.Y, B.C, B.C.Xi B.C.Y to tekst programu zawierającego program zawierający.The accessibility domain of A.Y, B, B.X, B.Y, B.C, B.C.X, and B.C.Y is the program text of the containing program.
  • Domena dostępności A.Z jest tekstem programu A.The accessibility domain of A.Z is the program text of A.
  • Domena dostępności B.Z i B.D to tekst programu B, w tym tekst programu B.C i B.D.The accessibility domain of B.Z and B.D is the program text of B, including the program text of B.C and B.D.
  • Domena dostępności B.C.Z jest tekstem programu B.C.The accessibility domain of B.C.Z is the program text of B.C.
  • Domena dostępności B.D.X i B.D.Y to tekst programu B, w tym tekst programu B.C i B.D.The accessibility domain of B.D.X and B.D.Y is the program text of B, including the program text of B.C and B.D.
  • Domena dostępności B.D.Z jest tekstem programu B.D.The accessibility domain of B.D.Z is the program text of B.D.

Jak pokazano na przykładzie, domena dostępności elementu członkowskiego nigdy nie jest większa niż typ zawierającego.As the example illustrates, the accessibility domain of a member is never larger than that of a containing type. Na przykład mimo że wszyscy członkowie X mają publicznie zadeklarowane ułatwienia dostępu, a wszystkie A.X mają domeny dostępności, które są ograniczone przez typ zawierający.For example, even though all X members have public declared accessibility, all but A.X have accessibility domains that are constrained by a containing type.

Zgodnie z opisem w części Członkowie, wszyscy członkowie klasy podstawowej, z wyjątkiem konstruktorów wystąpień, destruktory i konstruktory statyczne są dziedziczone przez typy pochodne.As described in Members, all members of a base class, except for instance constructors, destructors and static constructors, are inherited by derived types. Obejmuje to nawet prywatne elementy członkowskie klasy bazowej.This includes even private members of a base class. Jednak domena dostępności prywatnego elementu członkowskiego zawiera tylko tekst programu typu, w którym jest zadeklarowany element członkowski.However, the accessibility domain of a private member includes only the program text of the type in which the member is declared. w przykładzieIn the example

class A
{
    int x;

    static void F(B b) {
        b.x = 1;        // Ok
    }
}

class B: A
{
    static void F(B b) {
        b.x = 1;        // Error, x not accessible
    }
}

Klasa B dziedziczy prywatny element członkowski x z klasy A.the B class inherits the private member x from the A class. Ponieważ element członkowski jest prywatny, jest dostępny tylko w class_body A.Because the member is private, it is only accessible within the class_body of A. W ten sposób dostęp do b.x powiedzie się w metodzie A.F, ale w metodzie B.F nie powiedzie się.Thus, the access to b.x succeeds in the A.F method, but fails in the B.F method.

Chroniony dostęp dla członków wystąpieniaProtected access for instance members

Gdy jest uzyskiwany dostęp do elementu członkowskiego wystąpienia protected poza tekstem programu klasy, w którym jest zadeklarowany, a gdy członek wystąpienia protected internal jest dostępny poza tekstem programu w programie, w którym jest zadeklarowany, dostęp musi odbywać się w deklaracji klasy, która pochodzi od klasy, w której jest zadeklarowana.When a protected instance member is accessed outside the program text of the class in which it is declared, and when a protected internal instance member is accessed outside the program text of the program in which it is declared, the access must take place within a class declaration that derives from the class in which it is declared. Ponadto dostęp musi odbywać się za pośrednictwem wystąpienia tego typu klasy pochodnej lub klasy z tego typu.Furthermore, the access is required to take place through an instance of that derived class type or a class type constructed from it. To ograniczenie uniemożliwia jednej klasie pochodnej dostęp do chronionych elementów członkowskich innych klas pochodnych, nawet gdy elementy członkowskie są dziedziczone z tej samej klasy bazowej.This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class.

Niech B być klasą bazową, która deklaruje element członkowski chronionego wystąpienia Mi niech D być klasą pochodzącą z B.Let B be a base class that declares a protected instance member M, and let D be a class that derives from B. W class_body Ddostęp do M może mieć jedną z następujących form:Within the class_body of D, access to M can take one of the following forms:

  • Niekwalifikowana TYPE_NAME lub primary_expression formularza M.An unqualified type_name or primary_expression of the form M.
  • Primary_expression formularza E.M, pod warunkiem, że typ E jest T lub Klasa pochodna z T, gdzie T jest typem klasy Dlub typ klasy zbudowany z DA primary_expression of the form E.M, provided the type of E is T or a class derived from T, where T is the class type D, or a class type constructed from D
  • Primary_expression base.Mformularza.A primary_expression of the form base.M.

Oprócz tych formularzy dostępu Klasa pochodna może uzyskać dostęp do konstruktora chronionych wystąpień klasy bazowej w constructor_initializer (inicjatory konstruktora).In addition to these forms of access, a derived class can access a protected instance constructor of a base class in a constructor_initializer (Constructor initializers).

w przykładzieIn the example

public class A
{
    protected int x;

    static void F(A a, B b) {
        a.x = 1;        // Ok
        b.x = 1;        // Ok
    }
}

public class B: A
{
    static void F(A a, B b) {
        a.x = 1;        // Error, must access through instance of B
        b.x = 1;        // Ok
    }
}

w Amożna uzyskać dostęp do x przez wystąpienia obu A i B, ponieważ w obu przypadkach dostęp odbywa się za pośrednictwem wystąpienia A lub klasy pochodnej z A.within A, it is possible to access x through instances of both A and B, since in either case the access takes place through an instance of A or a class derived from A. Jednak w Bnie jest możliwe uzyskanie dostępu do x za pośrednictwem wystąpienia A, ponieważ A nie pochodzi od B.However, within B, it is not possible to access x through an instance of A, since A does not derive from B.

w przykładzieIn the example

class C<T>
{
    protected T x;
}

class D<T>: C<T>
{
    static void F() {
        D<T> dt = new D<T>();
        D<int> di = new D<int>();
        D<string> ds = new D<string>();
        dt.x = default(T);
        di.x = 123;
        ds.x = "test";
    }
}

trzy przypisania do x są dozwolone, ponieważ są one wykonywane za pośrednictwem wystąpień typów klas zbudowanych z typu ogólnego.the three assignments to x are permitted because they all take place through instances of class types constructed from the generic type.

Ograniczenia dotyczące ułatwień dostępuAccessibility constraints

Kilka konstrukcji w C# języku wymaga, aby typ był co najmniej taki sam jak element członkowski lub inny typ.Several constructs in the C# language require a type to be at least as accessible as a member or another type. Typ T jest uznawany za co najmniej jako element członkowski lub typ M, jeśli domena dostępności T jest nadzbiorem domeny dostępności M.A type T is said to be at least as accessible as a member or type M if the accessibility domain of T is a superset of the accessibility domain of M. Innymi słowy, T jest co najmniej tak samo, jak M, jeśli T jest dostępny we wszystkich kontekstach, w których M jest dostępny.In other words, T is at least as accessible as M if T is accessible in all contexts in which M is accessible.

Istnieją następujące ograniczenia dotyczące ułatwień dostępu:The following accessibility constraints exist:

  • Bezpośrednia klasa bazowa typu klasy musi być co najmniej równa dostępności jako samego typu klasy.The direct base class of a class type must be at least as accessible as the class type itself.
  • Jawne interfejsy podstawowe typu interfejsu muszą być co najmniej takie same jak typ interfejsu.The explicit base interfaces of an interface type must be at least as accessible as the interface type itself.
  • Typ zwracany i typy parametrów typu delegata muszą być co najmniej tak samo jak typ delegata.The return type and parameter types of a delegate type must be at least as accessible as the delegate type itself.
  • Typ stałej musi być co najmniej tak samo jak jako stała.The type of a constant must be at least as accessible as the constant itself.
  • Typ pola musi być co najmniej tak samo jak w przypadku samego pola.The type of a field must be at least as accessible as the field itself.
  • Typ zwracany i typy parametrów metody muszą być co najmniej tak samo samo jak metoda.The return type and parameter types of a method must be at least as accessible as the method itself.
  • Typ właściwości musi być co najmniej taki sam jak wartość właściwości.The type of a property must be at least as accessible as the property itself.
  • Typ zdarzenia musi być co najmniej tak samo jak w przypadku samego zdarzenia.The type of an event must be at least as accessible as the event itself.
  • Typ i typy parametrów indeksatora muszą być co najmniej tak samo dostępne jak indeksator.The type and parameter types of an indexer must be at least as accessible as the indexer itself.
  • Typ zwracany i typy parametrów operatora muszą być co najmniej takie same jak dla samego operatora.The return type and parameter types of an operator must be at least as accessible as the operator itself.
  • Typy parametrów konstruktora wystąpienia muszą być co najmniej tak samo samo jak Konstruktor wystąpień.The parameter types of an instance constructor must be at least as accessible as the instance constructor itself.

w przykładzieIn the example

class A {...}

public class B: A {...}

Klasa B powoduje błąd czasu kompilacji, ponieważ A nie jest co najmniej równa dostępności jako B.the B class results in a compile-time error because A is not at least as accessible as B.

Podobnie, w przykładzieLikewise, in the example

class A {...}

public class B
{
    A F() {...}

    internal A G() {...}

    public A H() {...}
}

Metoda H w B powoduje błąd czasu kompilacji, ponieważ typ zwracany A nie jest co najmniej taki sam jak metoda.the H method in B results in a compile-time error because the return type A is not at least as accessible as the method.

Sygnatury i PrzeciążenieSignatures and overloading

Metody, konstruktory wystąpień, indeksatory i operatory są scharakteryzowane przez ich sygnatury:Methods, instance constructors, indexers, and operators are characterized by their signatures:

  • Podpis metody składa się z nazwy metody, liczby parametrów typu i typu i rodzaju (wartości, odwołania lub danych wyjściowych) każdego z parametrów formalnych, które są uwzględniane w kolejności od lewej do prawej.The signature of a method consists of the name of the method, the number of type parameters and the type and kind (value, reference, or output) of each of its formal parameters, considered in the order left to right. W tym celu wszelkie parametry typu metody, która występuje w typie parametru formalnego, nie są identyfikowane przez jego nazwę, ale według pozycji porządkowej na liście argumentów typu metody.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. Sygnatura metody w szczególności nie obejmuje typu zwracanego, modyfikatora params, który może być określony dla najwyższego parametru lub opcjonalnych ograniczeń parametrów typu.The signature of a method specifically does not include the return type, the params modifier that may be specified for the right-most parameter, nor the optional type parameter constraints.
  • Sygnatura konstruktora wystąpienia składa się z typu i rodzaju (wartości, odwołania lub danych wyjściowych) każdego z jego parametrów formalnych, w kolejności od lewej do prawej.The signature of an instance constructor consists of the type and kind (value, reference, or output) of each of its formal parameters, considered in the order left to right. Podpis konstruktora wystąpienia w szczególności nie zawiera modyfikatora params, który może być określony dla każdego parametru z prawej strony.The signature of an instance constructor specifically does not include the params modifier that may be specified for the right-most parameter.
  • Podpis indeksatora składa się z typu każdego z parametrów formalnych, który jest traktowany w kolejności od lewej do prawej.The signature of an indexer consists of the type of each of its formal parameters, considered in the order left to right. Podpis indeksatora w szczególności nie zawiera typu elementu ani nie zawiera modyfikatora params, który może być określony dla tego parametru.The signature of an indexer specifically does not include the element type, nor does it include the params modifier that may be specified for the right-most parameter.
  • Podpis operatora składa się z nazwy operatora i typu każdego z jego parametrów formalnych, w kolejności od lewej do prawej.The signature of an operator consists of the name of the operator and the type of each of its formal parameters, considered in the order left to right. Podpis operatora jawnie nie zawiera typu wyniku.The signature of an operator specifically does not include the result type.

Sygnatury są mechanizmem włączania do przeciążenia elementów członkowskich w klasach, strukturach i interfejsach:Signatures are the enabling mechanism for overloading of members in classes, structs, and interfaces:

  • Przeciążanie metod pozwala klasy, struktury lub interfejsu zadeklarować wiele metod o tej samej nazwie, pod warunkiem, że ich sygnatury są unikatowe w ramach tej klasy, struktury lub interfejsu.Overloading of methods permits a class, struct, or interface to declare multiple methods with the same name, provided their signatures are unique within that class, struct, or interface.
  • Przeciążanie konstruktorów wystąpień pozwala klasie lub strukturze zadeklarować wiele konstruktorów wystąpień, pod warunkiem, że ich sygnatury są unikatowe w obrębie tej klasy lub struktury.Overloading of instance constructors permits a class or struct to declare multiple instance constructors, provided their signatures are unique within that class or struct.
  • Przeciążanie indeksatorów umożliwia klasy, struktury lub interfejsu zadeklarować wiele indeksatorów, pod warunkiem, że ich sygnatury są unikatowe w ramach tej klasy, struktury lub interfejsu.Overloading of indexers permits a class, struct, or interface to declare multiple indexers, provided their signatures are unique within that class, struct, or interface.
  • Przeciążanie operatorów pozwala klasie lub strukturze zadeklarować wiele operatorów o tej samej nazwie, pod warunkiem, że ich sygnatury są unikatowe w tej klasie lub strukturze.Overloading of operators permits a class or struct to declare multiple operators with the same name, provided their signatures are unique within that class or struct.

Mimo że Modyfikatory parametrów out i ref są uważane za część podpisu, składowe zadeklarowane w pojedynczym typie nie mogą różnić się w podpisie wyłącznie przez ref i out.Although out and ref parameter modifiers are considered part of a signature, members declared in a single type cannot differ in signature solely by ref and out. Błąd czasu kompilacji występuje, jeśli dwa składowe są zadeklarowane w tym samym typie z podpisami, które byłyby takie same, jeśli wszystkie parametry w obu metodach z modyfikatorami out zostały zmienione na ref modyfikatory.A compile-time error occurs if two members are declared in the same type with signatures that would be the same if all parameters in both methods with out modifiers were changed to ref modifiers. Do innych celów dopasowywania podpisów (np. ukrycia lub przesłaniania) ref i out są uważane za część podpisu i nie pasują do siebie nawzajem.For other purposes of signature matching (e.g., hiding or overriding), ref and out are considered part of the signature and do not match each other. (To ograniczenie umożliwia łatwe tłumaczenie C# programów na Common Language Infrastructure (CLI), które nie udostępniają sposobu definiowania metod, które różnią się wyłącznie w ref i out.)(This restriction is to allow C#  programs to be easily translated to run on the Common Language Infrastructure (CLI), which does not provide a way to define methods that differ solely in ref and out.)

Na potrzeby podpisów typy object i dynamic są uważane za takie same.For the purposes of signatures, the types object and dynamic are considered the same. Elementy członkowskie zadeklarowane w pojedynczym typie mogą nie różnić się w podpisie wyłącznie przez object i dynamic.Members declared in a single type can therefore not differ in signature solely by object and dynamic.

Poniższy przykład pokazuje zestaw przeciążonych deklaracji metod wraz z ich podpisami.The following example shows a set of overloaded method declarations along with their signatures.

interface ITest
{
    void F();                        // F()

    void F(int x);                   // F(int)

    void F(ref int x);               // F(ref int)

    void F(out int x);               // F(out int)      error

    void F(int x, int y);            // F(int, int)

    int F(string s);                 // F(string)

    int F(int x);                    // F(int)          error

    void F(string[] a);              // F(string[])

    void F(params string[] a);       // F(string[])     error
}

Należy zauważyć, że wszystkie ref i out Modyfikatory parametrów (Parametry metody) są częścią sygnatury.Note that any ref and out parameter modifiers (Method parameters) are part of a signature. W ten sposób F(int) i F(ref int) są unikatowymi sygnaturami.Thus, F(int) and F(ref int) are unique signatures. Nie można jednak zadeklarować F(ref int) i F(out int) w tym samym interfejsie, ponieważ ich podpisy różnią się wyłącznie ref i out.However, F(ref int) and F(out int) cannot be declared within the same interface because their signatures differ solely by ref and out. Należy również zauważyć, że typ zwracany i modyfikator params nie są częścią podpisu, więc nie jest możliwe przeciążanie wyłącznie na podstawie typu zwracanego lub przy włączaniu lub wykluczeniu modyfikatora params.Also, note that the return type and the params modifier are not part of a signature, so it is not possible to overload solely based on return type or on the inclusion or exclusion of the params modifier. W związku z tym deklaracje metod F(int) i F(params string[]) zidentyfikowane powyżej powodują błąd w czasie kompilacji.As such, the declarations of the methods F(int) and F(params string[]) identified above result in a compile-time error.

ZakresyScopes

Zakres nazwy jest regionem tekstu programu, w którym można odwołać się do jednostki zadeklarowanej przez nazwę bez kwalifikacji nazwy.The scope of a name is the region of program text within which it is possible to refer to the entity declared by the name without qualification of the name. Zakresy mogą być zagnieżdżane, a zakres wewnętrzny może redeklarować znaczenie nazwy z zewnętrznego zakresu (nie jest to jednak konieczne usunięcie ograniczenia wynikającego z deklaracji , które w bloku zagnieżdżonym nie można zadeklarować zmiennej lokalnej o takiej samej nazwie jak zmienna lokalna w otaczającym bloku).Scopes can be nested, and an inner scope may redeclare the meaning of a name from an outer scope (this does not, however, remove the restriction imposed by Declarations that within a nested block it is not possible to declare a local variable with the same name as a local variable in an enclosing block). Nazwa z zewnętrznego zakresu jest następnie określana jako Ukryta w regionie tekstu programu objętego zakresem wewnętrznym, a dostęp do nazwy zewnętrznej jest możliwy tylko przez zakwalifikowanie nazwy.The name from the outer scope is then said to be hidden in the region of program text covered by the inner scope, and access to the outer name is only possible by qualifying the name.

  • Zakres elementu członkowskiego przestrzeni nazw zadeklarowany przez namespace_member_declaration (elementy członkowskie obszaru nazw) bez otaczającego namespace_declaration jest całym tekstem programu.The scope of a namespace member declared by a namespace_member_declaration (Namespace members) with no enclosing namespace_declaration is the entire program text.
  • Zakres elementu członkowskiego przestrzeni nazw zadeklarowany przez namespace_member_declaration w namespace_declaration , którego w pełni kwalifikowana nazwa jest N jest namespace_body każdego namespace_declaration , którego w pełni kwalifikowana nazwa jest N lub rozpoczyna się od N, po którym następuje kropka.The scope of a namespace member declared by a namespace_member_declaration within a namespace_declaration whose fully qualified name is N is the namespace_body of every namespace_declaration whose fully qualified name is N or starts with N, followed by a period.
  • Zakres nazwy zdefiniowany przez extern_alias_directive rozciąga się na using_directives, global_attributes i namespace_member_declarations jego bezpośrednio zawierający jednostkę kompilacji lub treść przestrzeni nazw.The scope of name defined by an extern_alias_directive extends over the using_directives, global_attributes and namespace_member_declarations of its immediately containing compilation unit or namespace body. Extern_alias_directive nie współtworzy żadnych nowych członków do bazowego obszaru deklaracji.An extern_alias_directive does not contribute any new members to the underlying declaration space. Inaczej mówiąc, extern_alias_directive nie jest przechodnia, ale ma wpływ tylko na jednostkę kompilacji lub treść przestrzeni nazw, w której występuje.In other words, an extern_alias_directive is not transitive, but, rather, affects only the compilation unit or namespace body in which it occurs.
  • Zakres nazwy zdefiniowany lub zaimportowany przez using_directive (dyrektywy using) rozciąga się na namespace_member_declarations compilation_unit lub namespace_body , w których występuje using_directive .The scope of a name defined or imported by a using_directive (Using directives) extends over the namespace_member_declarations of the compilation_unit or namespace_body in which the using_directive occurs. Using_directive może wprowadzać zero lub większą liczbę nazw, typów lub elementów członkowskich, które są dostępne w ramach określonego compilation_unit lub namespace_body, ale nie współtworzy żadnych nowych członków do źródłowej przestrzeni deklaracji.A using_directive may make zero or more namespace, type or member names available within a particular compilation_unit or namespace_body, but does not contribute any new members to the underlying declaration space. Innymi słowy using_directive nie jest przechodnia, ale ma wpływ tylko na compilation_unit lub namespace_body , w których występuje.In other words, a using_directive is not transitive but rather affects only the compilation_unit or namespace_body in which it occurs.
  • Zakres parametru typu zadeklarowanego przez type_parameter_list na class_declaration (deklaracji klas) to class_base, type_parameter_constraints_clauses i class_body tego class_declaration.The scope of a type parameter declared by a type_parameter_list on a class_declaration (Class declarations) is the class_base, type_parameter_constraints_clauses, and class_body of that class_declaration.
  • Zakres parametru typu zadeklarowany przez type_parameter_list na struct_declaration (deklaracje struktury) to struct_interfaces, type_parameter_constraints_clauses i struct_body tego struct_declaration.The scope of a type parameter declared by a type_parameter_list on a struct_declaration (Struct declarations) is the struct_interfaces, type_parameter_constraints_clauses, and struct_body of that struct_declaration.
  • Zakres parametru typu zadeklarowanego przez type_parameter_list na interface_declaration (deklaracji interfejsu) to interface_base, type_parameter_constraints_clauses i interface_body tego interface_declaration.The scope of a type parameter declared by a type_parameter_list on an interface_declaration (Interface declarations) is the interface_base, type_parameter_constraints_clauses, and interface_body of that interface_declaration.
  • Zakres parametru typu zadeklarowany przez type_parameter_list na delegate_declaration (deklaracje delegatów) to return_type, formal_parameter_listi type_parameter_constraints_clauses tego delegate_declaration.The scope of a type parameter declared by a type_parameter_list on a delegate_declaration (Delegate declarations) is the return_type, formal_parameter_list, and type_parameter_constraints_clauses of that delegate_declaration.
  • Zakres składowej zadeklarowanej przez class_member_declaration (Treść klasy) to class_body , w której występuje deklaracja.The scope of a member declared by a class_member_declaration (Class body) is the class_body in which the declaration occurs. Ponadto zakres elementu członkowskiego klasy rozciąga się na class_body tych klas pochodnych, które znajdują się w domenie dostępności (domeny ułatwień dostępu) elementu członkowskiego.In addition, the scope of a class member extends to the class_body of those derived classes that are included in the accessibility domain (Accessibility domains) of the member.
  • Zakres elementu członkowskiego zadeklarowany przez struct_member_declaration (elementy członkowskie struktury) to struct_body , w którym występuje deklaracja.The scope of a member declared by a struct_member_declaration (Struct members) is the struct_body in which the declaration occurs.
  • Zakres elementu członkowskiego zadeklarowany przez enum_member_declaration (elementy członkowskie wyliczenia) to enum_body , w którym występuje deklaracja.The scope of a member declared by an enum_member_declaration (Enum members) is the enum_body in which the declaration occurs.
  • Zakres parametru zadeklarowany w method_declaration (metody) to method_body tego method_declaration.The scope of a parameter declared in a method_declaration (Methods) is the method_body of that method_declaration.
  • Zakres parametru zadeklarowany w indexer_declaration (indeksatory) to accessor_declarations tego indexer_declaration.The scope of a parameter declared in an indexer_declaration (Indexers) is the accessor_declarations of that indexer_declaration.
  • Zakres parametru zadeklarowany w operator_declaration (Operatory) jest blokiem tego operator_declaration.The scope of a parameter declared in an operator_declaration (Operators) is the block of that operator_declaration.
  • Zakres parametru zadeklarowany w constructor_declaration (konstruktory wystąpień) to constructor_initializer i blok tego constructor_declaration.The scope of a parameter declared in a constructor_declaration (Instance constructors) is the constructor_initializer and block of that constructor_declaration.
  • Zakres parametru zadeklarowany w lambda_expression (wyrażenia funkcji anonimowej) to anonymous_function_body lambda_expressionThe scope of a parameter declared in a lambda_expression (Anonymous function expressions) is the anonymous_function_body of that lambda_expression
  • Zakres parametru zadeklarowany w anonymous_method_expression (wyrażenia funkcji anonimowej) jest blokiem tego anonymous_method_expression.The scope of a parameter declared in an anonymous_method_expression (Anonymous function expressions) is the block of that anonymous_method_expression.
  • Zakres etykiety zadeklarowanej w labeled_statement (instrukcje z etykietą) to blok , w którym występuje deklaracja.The scope of a label declared in a labeled_statement (Labeled statements) is the block in which the declaration occurs.
  • Zakres zmiennej lokalnej zadeklarowanej w local_variable_declaration (lokalna deklaracja zmiennej) to blok, w którym występuje deklaracja.The scope of a local variable declared in a local_variable_declaration (Local variable declarations) is the block in which the declaration occurs.
  • Zakres zmiennej lokalnej zadeklarowanej w switch_block instrukcji switch (instrukcja switch) to switch_block.The scope of a local variable declared in a switch_block of a switch statement (The switch statement) is the switch_block.
  • Zakres zmiennej lokalnej zadeklarowanej w for_initializer instrukcji for (instrukcja for) to for_initializer, for_condition, for_iteratori zawartej instrukcji instrukcji for.The scope of a local variable declared in a for_initializer of a for statement (The for statement) is the for_initializer, the for_condition, the for_iterator, and the contained statement of the for statement.
  • Zakres stałej lokalnej zadeklarowanej w local_constant_declaration (lokalna deklaracja stała) to blok, w którym występuje deklaracja.The scope of a local constant declared in a local_constant_declaration (Local constant declarations) is the block in which the declaration occurs. Jest to błąd czasu kompilacji, który odwołuje się do lokalnej stałej w pozycji tekstowej, która poprzedza jej constant_declarator.It is a compile-time error to refer to a local constant in a textual position that precedes its constant_declarator.
  • Zakres zmiennej zadeklarowanej jako część foreach_statement, using_statement, lock_statement lub query_expression jest określany przez rozszerzenie danej konstrukcji.The scope of a variable declared as part of a foreach_statement, using_statement, lock_statement or query_expression is determined by the expansion of the given construct.

W zakresie przestrzeni nazw, klasy, struktury lub składowej wyliczenia można odwołać się do elementu członkowskiego w pozycji tekstowej, która poprzedza deklarację elementu członkowskiego.Within the scope of a namespace, class, struct, or enumeration member it is possible to refer to the member in a textual position that precedes the declaration of the member. Na przykład:For example

class A
{
    void F() {
        i = 1;
    }

    int i = 0;
}

W tym miejscu jest ważne, aby F odwoływać się do i przed zadeklarowaniem.Here, it is valid for F to refer to i before it is declared.

W zakresie zmiennej lokalnej jest to błąd czasu kompilacji, który odwołuje się do zmiennej lokalnej w pozycji tekstowej, która poprzedza local_variable_declarator zmiennej lokalnej.Within the scope of a local variable, it is a compile-time error to refer to the local variable in a textual position that precedes the local_variable_declarator of the local variable. Na przykład:For example

class A
{
    int i = 0;

    void F() {
        i = 1;                  // Error, use precedes declaration
        int i;
        i = 2;
    }

    void G() {
        int j = (j = 1);        // Valid
    }

    void H() {
        int a = 1, b = ++a;    // Valid
    }
}

W powyższej metodzie F pierwsze przypisanie do i szczególne nie odwołuje się do pola zadeklarowanego w zewnętrznym zakresie.In the F method above, the first assignment to i specifically does not refer to the field declared in the outer scope. Nie odnosi się do zmiennej lokalnej i powoduje błąd czasu kompilacji, ponieważ jest ona poprzedzona znakiem deklaracji zmiennej.Rather, it refers to the local variable and it results in a compile-time error because it textually precedes the declaration of the variable. W metodzie G użycie j w inicjatorze dla deklaracji j jest prawidłowe, ponieważ użycie nie poprzedza local_variable_declarator.In the G method, the use of j in the initializer for the declaration of j is valid because the use does not precede the local_variable_declarator. W metodzie H kolejne local_variable_declarator prawidłowo odwołują się do zmiennej lokalnej zadeklarowanej we wcześniejszym local_variable_declarator w ramach tego samego local_variable_declarationu.In the H method, a subsequent local_variable_declarator correctly refers to a local variable declared in an earlier local_variable_declarator within the same local_variable_declaration.

Reguły określania zakresu dla zmiennych lokalnych są zaprojektowane w celu zagwarantowania, że znaczenie nazwy używanej w kontekście wyrażenia jest zawsze takie samo w bloku.The scoping rules for local variables are designed to guarantee that the meaning of a name used in an expression context is always the same within a block. Jeśli zakres zmiennej lokalnej miał zostać rozbudowany tylko od jej deklaracji do końca bloku, wówczas w powyższym przykładzie pierwsze przypisanie zostanie przypisane do zmiennej wystąpienia, a drugie przypisanie zostanie przypisane do zmiennej lokalnej, co może prowadzić do Błędy czasu kompilacji, jeśli instrukcje bloku były później zmieniane.If the scope of a local variable were to extend only from its declaration to the end of the block, then in the example above, the first assignment would assign to the instance variable and the second assignment would assign to the local variable, possibly leading to compile-time errors if the statements of the block were later to be rearranged.

Znaczenie nazwy w bloku może się różnić w zależności od kontekstu, w którym jest używana nazwa.The meaning of a name within a block may differ based on the context in which the name is used. w przykładzieIn the example

using System;

class A {}

class Test
{
    static void Main() {
        string A = "hello, world";
        string s = A;                            // expression context

        Type t = typeof(A);                      // type context

        Console.WriteLine(s);                    // writes "hello, world"
        Console.WriteLine(t);                    // writes "A"
    }
}

Nazwa A jest używana w kontekście wyrażenia do odwoływania się do zmiennej lokalnej A i w kontekście typu, aby odwołać się do klasy A.the name A is used in an expression context to refer to the local variable A and in a type context to refer to the class A.

Ukrywanie nazwyName hiding

Zakres jednostki zwykle obejmuje więcej tekstu programu niż miejsce zadeklarowane w jednostce.The scope of an entity typically encompasses more program text than the declaration space of the entity. W szczególności zakres jednostki może zawierać deklaracje wprowadzające nowe obszary deklaracji zawierające jednostki o tej samej nazwie.In particular, the scope of an entity may include declarations that introduce new declaration spaces containing entities of the same name. Takie deklaracje powodują, że oryginalna jednostka zostanie Ukryta.Such declarations cause the original entity to become hidden. Z drugiej strony jednostka jest widoczna , gdy nie jest ukryta.Conversely, an entity is said to be visible when it is not hidden.

Ukrywanie nazw występuje, gdy zakresy nakładają się na zagnieżdżenie i gdy zakresy nakładają się na dziedziczenie.Name hiding occurs when scopes overlap through nesting and when scopes overlap through inheritance. Właściwości dwóch typów ukrywania są opisane w poniższych sekcjach.The characteristics of the two types of hiding are described in the following sections.

Ukrywanie przez zagnieżdżanieHiding through nesting

Nazwa ukrywająca przy użyciu zagnieżdżenia może wystąpić w wyniku zagnieżdżania przestrzeni nazw lub typów w przestrzeni nazw, w wyniku zagnieżdżania typów w obrębie klas lub struktur, a także jako wynik deklaracji parametrów i zmiennych lokalnych.Name hiding through nesting can occur as a result of nesting namespaces or types within namespaces, as a result of nesting types within classes or structs, and as a result of parameter and local variable declarations.

w przykładzieIn the example

class A
{
    int i = 0;

    void F() {
        int i = 1;
    }

    void G() {
        i = 1;
    }
}

w metodzie F zmienna wystąpienia i jest ukryta przez zmienną lokalną i, ale w ramach metody G, i nadal odwołuje się do zmiennej wystąpienia.within the F method, the instance variable i is hidden by the local variable i, but within the G method, i still refers to the instance variable.

Gdy nazwa w zakresie wewnętrznym ukrywa nazwę w zewnętrznym zakresie, ukrywa wszystkie załadowane wystąpienia tej nazwy.When a name in an inner scope hides a name in an outer scope, it hides all overloaded occurrences of that name. w przykładzieIn the example

class Outer
{
    static void F(int i) {}

    static void F(string s) {}

    class Inner
    {
        void G() {
            F(1);              // Invokes Outer.Inner.F
            F("Hello");        // Error
        }

        static void F(long l) {}
    }
}

Wywołanie F(1) wywołuje F zadeklarowane w Inner, ponieważ wszystkie zewnętrzne wystąpienia F są ukryte przez wewnętrzną deklarację.the call F(1) invokes the F declared in Inner because all outer occurrences of F are hidden by the inner declaration. Z tego samego powodu wywołanie F("Hello") powoduje błąd w czasie kompilacji.For the same reason, the call F("Hello") results in a compile-time error.

Ukrywanie poprzez dziedziczenieHiding through inheritance

Nazwa ukrywając przy użyciu dziedziczenia występuje, gdy klasy lub struktury ponownie deklarują nazwy dziedziczone z klas bazowych.Name hiding through inheritance occurs when classes or structs redeclare names that were inherited from base classes. Ten typ ukrywania nazwy ma jedną z następujących form:This type of name hiding takes one of the following forms:

  • Stałe, pole, właściwość, zdarzenie lub typ wprowadzone w klasie lub strukturze ukrywa wszystkie składowe klasy bazowej o tej samej nazwie.A constant, field, property, event, or type introduced in a class or struct hides all base class members with the same name.
  • Metoda wprowadzona w klasie lub strukturze ukrywa wszystkie składowe klas podstawowych niebędących metodami o tej samej nazwie i wszystkie metody klasy bazowej o tej samej sygnaturze (nazwa metody i liczba parametrów, modyfikatory i typy).A method introduced in a class or struct hides all non-method base class members with the same name, and all base class methods with the same signature (method name and parameter count, modifiers, and types).
  • Indeksator wprowadzony w klasie lub strukturze ukrywa wszystkie indeksatory klasy bazowej o tej samej sygnaturze (liczba parametrów i typy).An indexer introduced in a class or struct hides all base class indexers with the same signature (parameter count and types).

Reguły dotyczące deklaracji operatora (Operatory) sprawiają, że Klasa pochodna nie może deklarować operatora z tym samym podpisem jako operatora w klasie bazowej.The rules governing operator declarations (Operators) make it impossible for a derived class to declare an operator with the same signature as an operator in a base class. W tym celu operatory nigdy nie są ukrywane.Thus, operators never hide one another.

W przeciwieństwie do ukrywania nazwy z zewnętrznego zakresu ukrycie dostępnej nazwy z dziedziczonego zakresu powoduje ostrzeżenie o zgłoszeniu.Contrary to hiding a name from an outer scope, hiding an accessible name from an inherited scope causes a warning to be reported. w przykładzieIn the example

class Base
{
    public void F() {}
}

class Derived: Base
{
    public void F() {}        // Warning, hiding an inherited name
}

Deklaracja F w Derived powoduje zgłoszenie ostrzeżenia.the declaration of F in Derived causes a warning to be reported. Ukrycie dziedziczonej nazwy nie jest jawnie błędem, ponieważ spowodowałoby to wykluczenie oddzielnego ewolucji klas bazowych.Hiding an inherited name is specifically not an error, since that would preclude separate evolution of base classes. Na przykład Powyższa sytuacja może być spowodowana tym, że w nowszej wersji Base wprowadzono metodę F, która nie jest obecna we wcześniejszej wersji klasy.For example, the above situation might have come about because a later version of Base introduced an F method that wasn't present in an earlier version of the class. W przypadku powyższej sytuacji Wystąpił błąd, a następnie wszelkie zmiany wprowadzone do klasy podstawowej w bibliotece klas z odrębną wersją mogą potencjalnie spowodować, że klasy pochodne staną się nieprawidłowe.Had the above situation been an error, then any change made to a base class in a separately versioned class library could potentially cause derived classes to become invalid.

Ostrzeżenie spowodowane ukrywaniem dziedziczonej nazwy można wyeliminować za pomocą modyfikatora new:The warning caused by hiding an inherited name can be eliminated through use of the new modifier:

class Base
{
    public void F() {}
}

class Derived: Base
{
    new public void F() {}
}

Modyfikator new wskazuje, że F w Derived jest "New" i że rzeczywiście jest przeznaczony do ukrycia dziedziczonego elementu członkowskiego.The new modifier indicates that the F in Derived is "new", and that it is indeed intended to hide the inherited member.

Deklaracja nowego elementu członkowskiego powoduje ukrycie dziedziczonego elementu członkowskiego tylko w zakresie nowego elementu członkowskiego.A declaration of a new member hides an inherited member only within the scope of the new member.

class Base
{
    public static void F() {}
}

class Derived: Base
{
    new private static void F() {}    // Hides Base.F in Derived only
}

class MoreDerived: Derived
{
    static void G() { F(); }          // Invokes Base.F
}

W powyższym przykładzie deklaracja F w Derived powoduje ukrycie F, która była dziedziczona z Base, ale ponieważ nowy F w Derived ma dostęp prywatny, jego zakres nie obejmuje MoreDerived.In the example above, the declaration of F in Derived hides the F that was inherited from Base, but since the new F in Derived has private access, its scope does not extend to MoreDerived. W tym celu F() wywołań w MoreDerived.G jest prawidłowy i wywoła Base.F.Thus, the call F() in MoreDerived.G is valid and will invoke Base.F.

Nazwa przestrzeni nazw i typówNamespace and type names

Kilka kontekstów w C# programie wymaga określenia namespace_name lub TYPE_NAME .Several contexts in a C# program require a namespace_name or a type_name to be specified.

namespace_name
    : namespace_or_type_name
    ;

type_name
    : namespace_or_type_name
    ;

namespace_or_type_name
    : identifier type_argument_list?
    | namespace_or_type_name '.' identifier type_argument_list?
    | qualified_alias_member
    ;

Namespace_name jest namespace_or_type_name , który odwołuje się do przestrzeni nazw.A namespace_name is a namespace_or_type_name that refers to a namespace. Poniższe rozwiązanie, jak opisano poniżej, namespace_or_type_name namespace_name musi odwoływać się do przestrzeni nazw lub w przeciwnym razie wystąpi błąd w czasie kompilacji.Following resolution as described below, the namespace_or_type_name of a namespace_name must refer to a namespace, or otherwise a compile-time error occurs. Brak argumentów typu (argumenty typu) w namespace_name (tylko typy mogą mieć argumenty typu).No type arguments (Type arguments) can be present in a namespace_name (only types can have type arguments).

TYPE_NAME jest namespace_or_type_name , który odwołuje się do typu.A type_name is a namespace_or_type_name that refers to a type. Poniższe rozwiązanie, jak opisano poniżej, namespace_or_type_name TYPE_NAME musi odwoływać się do typu lub w przeciwnym razie wystąpi błąd w czasie kompilacji.Following resolution as described below, the namespace_or_type_name of a type_name must refer to a type, or otherwise a compile-time error occurs.

Jeśli namespace_or_type_name jest aliasem kwalifikowanym, jego znaczenie jest zgodnie z opisem w kwalifikatorach aliasów przestrzeni nazw.If the namespace_or_type_name is a qualified-alias-member its meaning is as described in Namespace alias qualifiers. W przeciwnym razie namespace_or_type_name ma jedną z czterech postaci:Otherwise, a namespace_or_type_name has one of four forms:

  • I
  • I<A1, ..., Ak>
  • N.I
  • N.I<A1, ..., Ak>

gdzie I jest pojedynczym identyfikatorem, N jest namespace_or_type_name , a <A1, ..., Ak> jest opcjonalną type_argument_list.where I is a single identifier, N is a namespace_or_type_name and <A1, ..., Ak> is an optional type_argument_list. Gdy nie określono type_argument_list , należy wziąć pod uwagę k wartość zero.When no type_argument_list is specified, consider k to be zero.

Znaczenie namespace_or_type_name jest określane w następujący sposób:The meaning of a namespace_or_type_name is determined as follows:

  • Jeśli namespace_or_type_name ma postać I lub formularza I<A1, ..., Ak>:If the namespace_or_type_name is of the form I or of the form I<A1, ..., Ak>:
    • Jeśli K ma wartość zero, a namespace_or_type_name pojawia się w deklaracji metody ogólnej (metody), a jeśli ta deklaracja zawiera parametr typu (parametry typu) o nazwie I, namespace_or_type_name odwołuje się do tego parametru typu.If K is zero and the namespace_or_type_name appears within a generic method declaration (Methods) and if that declaration includes a type parameter (Type parameters) with name I, then the namespace_or_type_name refers to that type parameter.
    • W przeciwnym razie, jeśli namespace_or_type_name pojawia się w deklaracji typu, wówczas dla każdego typu wystąpienia T (Typ wystąpienia), rozpoczynając od typu wystąpienia tego typu deklaracji i kontynuując typ wystąpienia każdej klasy lub deklaracji struktury (jeśli istnieje):Otherwise, if the namespace_or_type_name appears within a type declaration, then for each instance type T (The instance type), starting with the instance type of that type declaration and continuing with the instance type of each enclosing class or struct declaration (if any):
      • Jeśli K ma wartość zero, a deklaracja T zawiera parametr typu o nazwie I, wówczas namespace_or_type_name odwołuje się do tego parametru typu.If K is zero and the declaration of T includes a type parameter with name I, then the namespace_or_type_name refers to that type parameter.
      • W przeciwnym razie, jeśli namespace_or_type_name pojawia się w treści deklaracji typu, a T lub dowolny z jej typów podstawowych zawiera zagnieżdżony dostępny typ o nazwie I i K parametry typu, wówczas namespace_or_type_name odwołuje się do tego typu skonstruowanego za pomocą podanych argumentów typu.Otherwise, if the namespace_or_type_name appears within the body of the type declaration, and T or any of its base types contain a nested accessible type having name I and K type parameters, then the namespace_or_type_name refers to that type constructed with the given type arguments. Jeśli jest więcej niż jeden taki typ, zostanie wybrany typ zadeklarowany w ramach bardziej pochodnego typu.If there is more than one such type, the type declared within the more derived type is selected. Należy zauważyć, że elementy członkowskie inne niż typy (stałe, pola, metody, właściwości, indeksatory, operatory, konstruktory wystąpień, destruktory i konstruktory statyczne) i elementy członkowskie typu z inną liczbą parametrów typu są ignorowane podczas określania znaczenia namespace_or_type_name.Note that non-type members (constants, fields, methods, properties, indexers, operators, instance constructors, destructors, and static constructors) and type members with a different number of type parameters are ignored when determining the meaning of the namespace_or_type_name.
    • Jeśli poprzednie kroki nie powiodły się, dla każdej przestrzeni nazw N, rozpoczynając od przestrzeni nazw, w której występuje namespace_or_type_name , kontynuując z każdą otaczającą przestrzeń nazw (jeśli istnieje) i kończąc z globalną przestrzenią nazw, następujące kroki są oceniane do momentu zlokalizowania jednostki:If the previous steps were unsuccessful then, for each namespace N, starting with the namespace in which the namespace_or_type_name occurs, continuing with each enclosing namespace (if any), and ending with the global namespace, the following steps are evaluated until an entity is located:
      • Jeśli K ma wartość zero, a I to nazwa przestrzeni nazw w N, wówczas:If K is zero and I is the name of a namespace in N, then:
        • Jeśli lokalizacja, w której występuje namespace_or_type_name , jest ujęta w deklarację przestrzeni nazw dla N, a Deklaracja przestrzeni nazw zawiera extern_alias_directive lub using_alias_directive , która kojarzy nazwę I z przestrzenią nazw lub typem, wówczas namespace_or_type_name jest niejednoznaczna i wystąpi błąd w czasie kompilacji.If the location where the namespace_or_type_name occurs is enclosed by a namespace declaration for N and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with a namespace or type, then the namespace_or_type_name is ambiguous and a compile-time error occurs.
        • W przeciwnym razie namespace_or_type_name odwołuje się do przestrzeni nazw o nazwie I w N.Otherwise, the namespace_or_type_name refers to the namespace named I in N.
      • W przeciwnym razie, jeśli N zawiera dostępny typ o nazwie I i Kparametrów typu  , wówczas:Otherwise, if N contains an accessible type having name I and K type parameters, then:
        • Jeśli K ma wartość zero, a lokalizacja, w której występuje namespace_or_type_name , jest ujęta w deklarację przestrzeni nazw dla N a Deklaracja przestrzeni nazw zawiera extern_alias_directive lub using_alias_directive , który kojarzy nazwę I z przestrzenią nazw lub typem, wówczas namespace_or_type_name jest niejednoznaczna i wystąpi błąd kompilacji.If K is zero and the location where the namespace_or_type_name occurs is enclosed by a namespace declaration for N and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with a namespace or type, then the namespace_or_type_name is ambiguous and a compile-time error occurs.
        • W przeciwnym razie namespace_or_type_name odwołuje się do typu złożonego za pomocą podanych argumentów typu.Otherwise, the namespace_or_type_name refers to the type constructed with the given type arguments.
      • W przeciwnym razie, jeśli lokalizacja, w której występuje namespace_or_type_name , jest ujęta w deklarację przestrzeni nazw dla N:Otherwise, if the location where the namespace_or_type_name occurs is enclosed by a namespace declaration for N:
        • Jeśli K ma wartość zero, a Deklaracja przestrzeni nazw zawiera extern_alias_directive lub using_alias_directive , które kojarzą nazwę I z zaimportowaną przestrzenią nazw lub typem, wówczas namespace_or_type_name odwołuje się do tej przestrzeni nazw lub typu.If K is zero and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with an imported namespace or type, then the namespace_or_type_name refers to that namespace or type.
        • W przeciwnym razie, jeśli przestrzenie nazw i deklaracje typów zaimportowane przez using_namespace_directives i using_alias_directives deklaracji przestrzeni nazw zawierają dokładnie jeden dostępny typ o nazwie I i K parametry typu, a następnie namespace_or_type_name odwołuje się do tego typu skonstruowanego za pomocą podanych argumentów typu.Otherwise, if the namespaces and type declarations imported by the using_namespace_directives and using_alias_directives of the namespace declaration contain exactly one accessible type having name I and K type parameters, then the namespace_or_type_name refers to that type constructed with the given type arguments.
        • W przeciwnym razie, jeśli przestrzenie nazw i deklaracje typów zaimportowane przez using_namespace_directives i using_alias_directives deklaracji przestrzeni nazw zawierają więcej niż jeden dostępny typ o nazwie I i K parametry typu, wówczas namespace_or_type_name jest niejednoznaczny i wystąpi błąd.Otherwise, if the namespaces and type declarations imported by the using_namespace_directives and using_alias_directives of the namespace declaration contain more than one accessible type having name I and K type parameters, then the namespace_or_type_name is ambiguous and an error occurs.
    • W przeciwnym razie namespace_or_type_name jest niezdefiniowana i wystąpi błąd w czasie kompilacji.Otherwise, the namespace_or_type_name is undefined and a compile-time error occurs.
  • W przeciwnym razie namespace_or_type_name ma postać N.I lub N.I<A1, ..., Ak>.Otherwise, the namespace_or_type_name is of the form N.I or of the form N.I<A1, ..., Ak>. N został najpierw rozpoznany jako namespace_or_type_name.N is first resolved as a namespace_or_type_name. Jeśli rozwiązanie N nie powiedzie się, wystąpi błąd w czasie kompilacji.If the resolution of N is not successful, a compile-time error occurs. W przeciwnym razie N.I lub N.I<A1, ..., Ak> są rozwiązywane w następujący sposób:Otherwise, N.I or N.I<A1, ..., Ak> is resolved as follows:
    • Jeśli K ma wartość zero i N odwołuje się do przestrzeni nazw, a N zawiera zagnieżdżoną przestrzeń nazw o nazwie I, wówczas namespace_or_type_name odwołuje się do tej zagnieżdżonej przestrzeni nazw.If K is zero and N refers to a namespace and N contains a nested namespace with name I, then the namespace_or_type_name refers to that nested namespace.
    • W przeciwnym razie, jeśli N odwołuje się do przestrzeni nazw, a N zawiera dostępny typ o nazwie I i K parametry typu, wówczas namespace_or_type_name odwołuje się do tego typu skonstruowanego za pomocą podanych argumentów typu.Otherwise, if N refers to a namespace and N contains an accessible type having name I and K type parameters, then the namespace_or_type_name refers to that type constructed with the given type arguments.
    • W przeciwnym razie, jeśli N odwołuje się do klasy lub typu struktury, a N lub dowolna z jej klas podstawowych zawiera zagnieżdżony dostępny typ o nazwie I i K parametry typu, a następnie namespace_or_type_name odwołuje się do tego typu skonstruowanego za pomocą podanych argumentów typu.Otherwise, if N refers to a (possibly constructed) class or struct type and N or any of its base classes contain a nested accessible type having name I and K type parameters, then the namespace_or_type_name refers to that type constructed with the given type arguments. Jeśli jest więcej niż jeden taki typ, zostanie wybrany typ zadeklarowany w ramach bardziej pochodnego typu.If there is more than one such type, the type declared within the more derived type is selected. Należy pamiętać, że jeśli znaczenie N.I jest określane jako część rozpoznawania specyfikacji klasy bazowej N, bezpośrednia klasa bazowa N jest uznawana za obiekt (klasy bazowe).Note that if the meaning of N.I is being determined as part of resolving the base class specification of N then the direct base class of N is considered to be object (Base classes).
    • W przeciwnym razie N.I jest nieprawidłowym namespace_or_type_namei wystąpi błąd w czasie kompilacji.Otherwise, N.I is an invalid namespace_or_type_name, and a compile-time error occurs.

Namespace_or_type_name może odwoływać się do klasy statycznej (klasy statyczne) tylko wtedy, gdyA namespace_or_type_name is permitted to reference a static class (Static classes) only if

  • Namespace_or_type_name jest T w namespace_or_type_name T.Iformularz, lubThe namespace_or_type_name is the T in a namespace_or_type_name of the form T.I, or
  • Namespace_or_type_name jest T w typeof_expression (Argument Lists1) typeof(T)formularza.The namespace_or_type_name is the T in a typeof_expression (Argument lists1) of the form typeof(T).

W pełni kwalifikowane nazwyFully qualified names

Każda przestrzeń nazw i typ mają w pełni kwalifikowaną nazwę, która jednoznacznie identyfikuje przestrzeń nazw lub typ między wszystkimi innymi.Every namespace and type has a fully qualified name, which uniquely identifies the namespace or type amongst all others. W pełni kwalifikowana nazwa przestrzeni nazw lub typu N jest określana w następujący sposób:The fully qualified name of a namespace or type N is determined as follows:

  • Jeśli N jest członkiem globalnej przestrzeni nazw, jego w pełni kwalifikowana nazwa jest N.If N is a member of the global namespace, its fully qualified name is N.
  • W przeciwnym razie jego w pełni kwalifikowana nazwa jest S.N, gdzie S to w pełni kwalifikowana nazwa przestrzeni nazw lub typu, w którym N jest zadeklarowana.Otherwise, its fully qualified name is S.N, where S is the fully qualified name of the namespace or type in which N is declared.

Innymi słowy, w pełni kwalifikowana nazwa N jest pełną ścieżką hierarchiczną identyfikatorów, które prowadzą do N, rozpoczynając od globalnej przestrzeni nazw.In other words, the fully qualified name of N is the complete hierarchical path of identifiers that lead to N, starting from the global namespace. Ponieważ każdy element członkowski przestrzeni nazw lub typu musi mieć unikatową nazwę, następuje, że w pełni kwalifikowana nazwa przestrzeni nazw lub typu jest zawsze unikatowa.Because every member of a namespace or type must have a unique name, it follows that the fully qualified name of a namespace or type is always unique.

W poniższym przykładzie przedstawiono kilka nazw i deklaracji typów wraz z ich skojarzonymi w pełni kwalifikowanymi nazwami.The example below shows several namespace and type declarations along with their associated fully qualified names.

class A {}                // A

namespace X               // X
{
    class B               // X.B
    {
        class C {}        // X.B.C
    }

    namespace Y           // X.Y
    {
        class D {}        // X.Y.D
    }
}

namespace X.Y             // X.Y
{
    class E {}            // X.Y.E
}

Automatyczne zarządzanie pamięciąAutomatic memory management

C#Program wykorzystuje automatyczne zarządzanie pamięcią, dzięki czemu deweloperzy mogą bezpłatnie przydzielać i zwalniać pamięć zajmowaną przez obiekty.C# employs automatic memory management, which frees developers from manually allocating and freeing the memory occupied by objects. Automatyczne zasady zarządzania pamięcią są implementowane przez Moduł wyrzucania elementów bezużytecznych.Automatic memory management policies are implemented by a garbage collector. Cykl życia zarządzania pamięcią obiektu jest następujący:The memory management life cycle of an object is as follows:

  1. Po utworzeniu obiektu zostanie do niego przydzielono pamięć, Konstruktor zostanie uruchomiony, a obiekt jest uznawany za aktywny.When the object is created, memory is allocated for it, the constructor is run, and the object is considered live.
  2. Jeśli obiektu lub dowolnej jego części nie można uzyskać dostępu do żadnego możliwej kontynuacji wykonywania, z wyjątkiem uruchamiania destruktorów, obiekt jest uważany za nieużywany i będzie uprawniony do zniszczenia.If the object, or any part of it, cannot be accessed by any possible continuation of execution, other than the running of destructors, the object is considered no longer in use, and it becomes eligible for destruction. C# Kompilator i moduł wyrzucania elementów bezużytecznych mogą analizować kod, aby określić, które odwołania do obiektu mogą być używane w przyszłości.The C# compiler and the garbage collector may choose to analyze code to determine which references to an object may be used in the future. Na przykład jeśli zmienna lokalna, która znajduje się w zakresie, jest jedynym istniejącym odwołaniem do obiektu, ale ta zmienna lokalna nigdy nie jest określana w żadnej możliwej kontynuacji wykonywania z bieżącego punktu wykonywania w procedurze, Moduł wyrzucania elementów bezużytecznych może (ale nie) wymagane do) traktuje obiekt jako nieużywany.For instance, if a local variable that is in scope is the only existing reference to an object, but that local variable is never referred to in any possible continuation of execution from the current execution point in the procedure, the garbage collector may (but is not required to) treat the object as no longer in use.
  3. Gdy obiekt kwalifikuje się do zniszczenia, w przypadku, gdy nie zostanie określony później destruktor (destruktory) (jeśli istnieje) dla obiektu jest uruchamiany.Once the object is eligible for destruction, at some unspecified later time the destructor (Destructors) (if any) for the object is run. W normalnych warunkach destruktor dla obiektu jest uruchamiany tylko raz, ale interfejsy API specyficzne dla implementacji mogą zezwalać na przesłanianie tego zachowania.Under normal circumstances the destructor for the object is run once only, though implementation-specific APIs may allow this behavior to be overridden.
  4. Po uruchomieniu destruktora obiektu, jeśli ten obiekt lub jakakolwiek jego część nie są dostępne w żadnej możliwej kontynuacji wykonywania, w tym uruchamiania destruktorów, obiekt jest uznawany za niedostępny i obiekt kwalifikuje się do kolekcji.Once the destructor for an object is run, if that object, or any part of it, cannot be accessed by any possible continuation of execution, including the running of destructors, the object is considered inaccessible and the object becomes eligible for collection.
  5. Na koniec po pewnym czasie po przypisaniu obiektu do kolekcji moduł wyrzucania elementów bezużytecznych zwolni pamięć skojarzoną z tym obiektem.Finally, at some time after the object becomes eligible for collection, the garbage collector frees the memory associated with that object.

Moduł wyrzucania elementów bezużytecznych przechowuje informacje o użyciu obiektów i używa tych informacji do podejmowania decyzji dotyczących zarządzania pamięcią, takich jak miejsce w pamięci do lokalizowania nowo utworzonego obiektu, kiedy przemieszczenie obiektu, gdy obiekt nie jest już używany lub niedostępny.The garbage collector maintains information about object usage, and uses this information to make memory management decisions, such as where in memory to locate a newly created object, when to relocate an object, and when an object is no longer in use or inaccessible.

Podobnie jak w przypadku innych języków, które zakładają istnienie C# wyrzucania elementów bezużytecznych, zaprojektowano tak, aby moduł zbierający elementy bezużyteczne mógł zaimplementować szeroką gamę zasad zarządzania pamięciąLike other languages that assume the existence of a garbage collector, C# is designed so that the garbage collector may implement a wide range of memory management policies. Na przykład program C# nie wymaga uruchomienia destruktorów lub obiektów, które są zbierane zaraz po ich zakwalifikowaniu lub że destruktory są uruchamiane w określonej kolejności lub w dowolnym wątku.For instance, C# does not require that destructors be run or that objects be collected as soon as they are eligible, or that destructors be run in any particular order, or on any particular thread.

Zachowanie modułu wyrzucania elementów bezużytecznych może być kontrolowane w pewnym stopniu za pomocą metod statycznych w klasie System.GC.The behavior of the garbage collector can be controlled, to some degree, via static methods on the class System.GC. Ta klasa może służyć do żądania kolekcji, destruktorów, które mają być uruchamiane (lub nie są uruchamiane) i tak dalej.This class can be used to request a collection to occur, destructors to be run (or not run), and so forth.

Ponieważ moduł wyrzucania elementów bezużytecznych jest dozwolony szerokiej szerokości geograficznej podczas wybierania obiektów i destruktorów, implementacja zgodna może generować dane wyjściowe, które różnią się od pokazanego w poniższym kodzie.Since the garbage collector is allowed wide latitude in deciding when to collect objects and run destructors, a conforming implementation may produce output that differs from that shown by the following code. ProgramThe program

using System;

class A
{
    ~A() {
        Console.WriteLine("Destruct instance of A");
    }
}

class B
{
    object Ref;

    public B(object o) {
        Ref = o;
    }

    ~B() {
        Console.WriteLine("Destruct instance of B");
    }
}

class Test
{
    static void Main() {
        B b = new B(new A());
        b = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}

tworzy wystąpienie klasy A i wystąpienie klasy B.creates an instance of class A and an instance of class B. Te obiekty stają się kwalifikować do wyrzucania elementów bezużytecznych, gdy zmienna b ma przypisaną wartość null, ponieważ po tym czasie nie jest możliwe uzyskanie dostępu do nich przez każdy kod pisany przez użytkownika.These objects become eligible for garbage collection when the variable b is assigned the value null, since after this time it is impossible for any user-written code to access them. Dane wyjściowe mogą być alboThe output could be either

Destruct instance of A
Destruct instance of B

lubor

Destruct instance of B
Destruct instance of A

Ponieważ język nie nakłada żadnych ograniczeń w kolejności, w której obiekty są odbierane jako elementy bezużyteczne.because the language imposes no constraints on the order in which objects are garbage collected.

W delikatnych przypadkach rozróżnienie między elementami "kwalifikujące się do zniszczenia" i "kwalifikujące się do kolekcji" może być ważne.In subtle cases, the distinction between "eligible for destruction" and "eligible for collection" can be important. Na przykładFor example,

using System;

class A
{
    ~A() {
        Console.WriteLine("Destruct instance of A");
    }

    public void F() {
        Console.WriteLine("A.F");
        Test.RefA = this;
    }
}

class B
{
    public A Ref;

    ~B() {
        Console.WriteLine("Destruct instance of B");
        Ref.F();
    }
}

class Test
{
    public static A RefA;
    public static B RefB;

    static void Main() {
        RefB = new B();
        RefA = new A();
        RefB.Ref = RefA;
        RefB = null;
        RefA = null;

        // A and B now eligible for destruction
        GC.Collect();
        GC.WaitForPendingFinalizers();

        // B now eligible for collection, but A is not
        if (RefA != null)
            Console.WriteLine("RefA is not null");
    }
}

Jeśli moduł wyrzucania elementów bezużytecznych wybierze uruchomienie destruktora A przed destruktorem B, dane wyjściowe tego programu mogą być następujące:In the above program, if the garbage collector chooses to run the destructor of A before the destructor of B, then the output of this program might be:

Destruct instance of A
Destruct instance of B
A.F
RefA is not null

Należy zauważyć, że chociaż wystąpienie A było nieużywane i nie uruchomiono destruktora A, nadal jest możliwe Metoda A (w tym przypadku F) do wywołania z innego destruktora.Note that although the instance of A was not in use and A's destructor was run, it is still possible for methods of A (in this case, F) to be called from another destructor. Należy również pamiętać, że uruchomienie destruktora może spowodować, że obiekt będzie można użyć ponownie z programu linii głównej.Also, note that running of a destructor may cause an object to become usable from the mainline program again. W takim przypadku uruchomienie destruktora Bspowodowało wystąpienie A, które wcześniej nie było używane do uzyskania dostępu z Test.RefAna żywo odwołania.In this case, the running of B's destructor caused an instance of A that was previously not in use to become accessible from the live reference Test.RefA. Po wywołaniu WaitForPendingFinalizerswystąpienie B jest uprawnione do kolekcji, ale wystąpienie A nie jest, ze względu na Test.RefAodwołania.After the call to WaitForPendingFinalizers, the instance of B is eligible for collection, but the instance of A is not, because of the reference Test.RefA.

Aby uniknąć nieporozumień i nieoczekiwanego zachowania, zwykle dobrym pomysłem jest, aby destruktory wykonywały tylko oczyszczanie danych przechowywanych w własnych polach obiektu, a nie do wykonywania żadnych akcji na obiektach, do których istnieją odwołania lub pola statyczne.To avoid confusion and unexpected behavior, it is generally a good idea for destructors to only perform cleanup on data stored in their object's own fields, and not to perform any actions on referenced objects or static fields.

Alternatywą dla korzystania z destruktorów jest umożliwienie klasy implementującej interfejs System.IDisposable.An alternative to using destructors is to let a class implement the System.IDisposable interface. Umożliwia to klientowi obiektu określenie czasu zwolnienia zasobów obiektu, zazwyczaj przez uzyskanie dostępu do obiektu jako zasobu w instrukcji using (instrukcja using).This allows the client of the object to determine when to release the resources of the object, typically by accessing the object as a resource in a using statement (The using statement).

Kolejność wykonywaniaExecution order

Wykonanie C# programu jest wykonywane w taki sposób, że efekty uboczne każdego wątku wykonywanego są zachowywane w kluczowych punktach wykonania.Execution of a C# program proceeds such that the side effects of each executing thread are preserved at critical execution points. Efekt uboczny jest definiowany jako Odczyt lub zapis pola nietrwałego, zapis do zmiennej nietrwałej, zapis do zasobu zewnętrznego i wyrzucanie wyjątku.A side effect is defined as a read or write of a volatile field, a write to a non-volatile variable, a write to an external resource, and the throwing of an exception. Krytyczne punkty wykonywania, w których kolejność tych efektów ubocznych muszą być zachowywane, są odwołaniami do pól nietrwałych (pól nietrwałych), instrukcji lock (instrukcja Lock) oraz tworzenia i kończenia wątku.The critical execution points at which the order of these side effects must be preserved are references to volatile fields (Volatile fields), lock statements (The lock statement), and thread creation and termination. Środowisko wykonawcze jest bezpłatne, aby zmienić kolejność wykonywania C# programu, zgodnie z następującymi ograniczeniami:The execution environment is free to change the order of execution of a C# program, subject to the following constraints:

  • Zależność danych jest zachowywana w wątku wykonywania.Data dependence is preserved within a thread of execution. Oznacza to, że wartość każdej zmiennej jest obliczana tak, jakby wszystkie instrukcje w wątku były wykonywane w oryginalnej kolejności programu.That is, the value of each variable is computed as if all statements in the thread were executed in original program order.
  • Reguły porządkowania inicjalizacji są zachowywane (Inicjalizacja pola i inicjatory zmiennych).Initialization ordering rules are preserved (Field initialization and Variable initializers).
  • Porządkowanie efektów ubocznych jest zachowywane w odniesieniu do nietrwałych odczytów i zapisów (pola nietrwałe).The ordering of side effects is preserved with respect to volatile reads and writes (Volatile fields). Ponadto środowisko wykonawcze nie musi obliczać części wyrażenia, jeśli może wywnioskować, że wartość tego wyrażenia nie jest używana i że nie są generowane żadne niepotrzebne efekty uboczne (w tym wszelkie powodowane przez wywołanie metody lub uzyskanie dostępu do pola nietrwałego).Additionally, the execution environment need not evaluate part of an expression if it can deduce that that expression's value is not used and that no needed side effects are produced (including any caused by calling a method or accessing a volatile field). Po przerwaniu wykonywania programu przez zdarzenie asynchroniczne (takie jak wyjątek zgłoszony przez inny wątek) nie jest gwarantowane, że zauważalne efekty uboczne są widoczne w oryginalnym porządku programu.When program execution is interrupted by an asynchronous event (such as an exception thrown by another thread), it is not guaranteed that the observable side effects are visible in the original program order.