WprowadzenieIntroduction

C# (wymawiane "Zobacz Sharp") to prosty, nowoczesny, zorientowany obiektowo i bezpieczny dla typu język programowania.C# (pronounced "See Sharp") is a simple, modern, object-oriented, and type-safe programming language. Język C# ma swoje elementy główne w rodzinie C i będzie od razu zaznajomiony z programistami C, C++ i Java.C# has its roots in the C family of languages and will be immediately familiar to C, C++, and Java programmers. Język C# jest ustandaryzowany przez ECMA International jako ECMA-334 _ Standard i ISO/IEC jako iso/IEC 23270 Standard.C# is standardized by ECMA International as the ECMA-334 _ standard and by ISO/IEC as the _ ISO/IEC 23270 standard. Kompilator języka C# firmy Microsoft dla .NET Framework jest zgodny z implementacją obu tych standardów.Microsoft's C# compiler for the .NET Framework is a conforming implementation of both of these standards.

C# jest językiem zorientowanym na obiekt, ale w języku C# jest dodatkowo obsługiwane programowanie zorientowane na składniki .C# is an object-oriented language, but C# further includes support for component-oriented programming. Współczesny projekt oprogramowania jest coraz bardziej oparty na składnikach oprogramowania w postaci samodzielnych i samodzielnych pakietów funkcji.Contemporary software design increasingly relies on software components in the form of self-contained and self-describing packages of functionality. Klucz do takich składników polega na tym, że stanowią one model programowania z właściwościami, metodami i zdarzeniami; mają one atrybuty, które dostarczają deklaracyjne informacje o składniku; i zawierają własną dokumentację.Key to such components is that they present a programming model with properties, methods, and events; they have attributes that provide declarative information about the component; and they incorporate their own documentation. Język c# udostępnia konstrukcje języka, aby bezpośrednio obsługiwać te koncepcje, co sprawia, że język C# jest bardzo naturalny, w którym można tworzyć i używać składników oprogramowania.C# provides language constructs to directly support these concepts, making C# a very natural language in which to create and use software components.

Kilka funkcji języka C# pomaga w konstruowaniu niezawodnych i trwałych aplikacji: wyrzucanie elementów bezużytecznych automatycznie odzyskuje pamięć zajmowaną przez nieużywane obiekty; _Obsługa wyjątków_ zapewnia strukturalne i rozszerzalne podejście do wykrywania błędów i odzyskiwania. a symbol _ typu-bezpieczny projektowanie języka sprawia, że nie można odczytać z niezainicjowanych zmiennych, indeksować tablice poza ich granicami lub wykonywać rzutowania typu unchecked.Several C# features aid in the construction of robust and durable applications: Garbage collection _ automatically reclaims memory occupied by unused objects; _exception handling_ provides a structured and extensible approach to error detection and recovery; and the _ type-safe design of the language makes it impossible to read from uninitialized variables, to index arrays beyond their bounds, or to perform unchecked type casts.

Język C# ma ujednolicony system typów.C# has a unified type system. Wszystkie typy C#, w tym typy pierwotne, takie jak int i double , dziedziczą z jednego object typu głównego.All C# types, including primitive types such as int and double, inherit from a single root object type. W związku z tym wszystkie typy używają zestawu typowych operacji, a wartości dowolnego typu mogą być przechowywane, transportowane i obsługiwane w spójny sposób.Thus, all types share a set of common operations, and values of any type can be stored, transported, and operated upon in a consistent manner. Ponadto w języku C# obsługiwane są zarówno typy odwołań zdefiniowane przez użytkownika, jak i typy wartości, co umożliwia dynamiczne przydzielanie obiektów oraz przechowywanie w wierszu lekkich struktur.Furthermore, C# supports both user-defined reference types and value types, allowing dynamic allocation of objects as well as in-line storage of lightweight structures.

Aby upewnić się, że programy i biblioteki C# mogą się rozwijać w czasie w zgodnym zakresie, znacznie przeznaczenie zostało umieszczone w projekcie w języku c#.To ensure that C# programs and libraries can evolve over time in a compatible manner, much emphasis has been placed on versioning in C#'s design. W wielu językach programowania jest mało uwagi na ten problem, a w efekcie programy w tych językach są częściej częściej niż to konieczne, gdy są wprowadzane nowsze wersje bibliotek zależnych.Many programming languages pay little attention to this issue, and, as a result, programs written in those languages break more often than necessary when newer versions of dependent libraries are introduced. Aspekty projektu języka C#, które miały bezpośrednio wpływ na kwestie związane z obsługą wersji, obejmują oddzielność virtual i override modyfikatory, reguły rozpoznawania przeciążania metod oraz obsługę jawnych deklaracji elementów członkowskich interfejsu.Aspects of C#'s design that were directly influenced by versioning considerations include the separate virtual and override modifiers, the rules for method overload resolution, and support for explicit interface member declarations.

Pozostała część tego rozdziału zawiera opis najważniejszych funkcji języka C#.The rest of this chapter describes the essential features of the C# language. Chociaż dalsze rozdziały opisują reguły i wyjątki w szczegółowo zorientowanym i niekiedy w sposób matematyczny, ten rozdział dąży do przejrzystości i zwięzłości na koszt kompletności.Although later chapters describe rules and exceptions in a detail-oriented and sometimes mathematical manner, this chapter strives for clarity and brevity at the expense of completeness. Celem jest zapewnienie czytelnikowi wprowadzenia do języka, który ułatwia pisanie wczesnych programów i odczytywanie dalszych rozdziałów.The intent is to provide the reader with an introduction to the language that will facilitate the writing of early programs and the reading of later chapters.

Hello worldHello world

Program "Hello, World" jest tradycyjnie używany do wprowadzania języka programowania.The "Hello, World" program is traditionally used to introduce a programming language. W tym miejscu jest w języku C#:Here it is in C#:

using System;

class Hello
{
    static void Main() {
        Console.WriteLine("Hello, World");
    }
}

Pliki źródłowe języka C# mają zwykle rozszerzenie pliku .cs .C# source files typically have the file extension .cs. Przy założeniu, że program "Hello, World" jest przechowywany w pliku hello.cs , program można skompilować za pomocą kompilatora języka C# firmy Microsoft przy użyciu wiersza poleceniaAssuming that the "Hello, World" program is stored in the file hello.cs, the program can be compiled with the Microsoft C# compiler using the command line

csc hello.cs

tworzy zestaw wykonywalny o nazwie hello.exe .which produces an executable assembly named hello.exe. Dane wyjściowe generowane przez tę aplikację po jej uruchomieniu toThe output produced by this application when it is run is

Hello, World

Program "Hello, World" rozpoczyna się od using dyrektywy, która odwołuje się do System przestrzeni nazw.The "Hello, World" program starts with a using directive that references the System namespace. Przestrzenie nazw zapewniają hierarchiczny sposób organizowania programów i bibliotek w języku C#.Namespaces provide a hierarchical means of organizing C# programs and libraries. Przestrzenie nazw zawierają typy i inne przestrzenie nazw — na przykład System przestrzeń nazw zawiera wiele typów, takich jak Console Klasa, do której odwołuje się program, oraz liczba innych przestrzeni nazw, takich jak IO i Collections .Namespaces contain types and other namespaces—for example, the System namespace contains a number of types, such as the Console class referenced in the program, and a number of other namespaces, such as IO and Collections. usingDyrektywa odwołująca się do danej przestrzeni nazw umożliwia niekwalifikowane użycie typów, które są elementami członkowskimi tej przestrzeni nazw.A using directive that references a given namespace enables unqualified use of the types that are members of that namespace. Ze względu na using dyrektywę program może użyć Console.WriteLine jako skrótu dla elementu System.Console.WriteLine .Because of the using directive, the program can use Console.WriteLine as shorthand for System.Console.WriteLine.

HelloKlasa zadeklarowana przez program "Hello, World" ma jeden element członkowski, Metoda o nazwie Main .The Hello class declared by the "Hello, World" program has a single member, the method named Main. MainMetoda jest zadeklarowana z static modyfikatorem.The Main method is declared with the static modifier. Chociaż metody wystąpień mogą odwoływać się do określonego wystąpienia obiektu otaczającego za pomocą słowa kluczowego this , metody statyczne działają bez odwołania do określonego obiektu.While instance methods can reference a particular enclosing object instance using the keyword this, static methods operate without reference to a particular object. Zgodnie z Konwencją metoda statyczna o nazwie Main służy jako punkt wejścia programu.By convention, a static method named Main serves as the entry point of a program.

Dane wyjściowe programu są tworzone przez WriteLine metodę Console klasy w System przestrzeni nazw.The output of the program is produced by the WriteLine method of the Console class in the System namespace. Ta klasa jest dostarczana przez .NET Framework biblioteki klas, które domyślnie są przywoływane przez kompilator języka C# firmy Microsoft.This class is provided by the .NET Framework class libraries, which, by default, are automatically referenced by the Microsoft C# compiler. Należy zauważyć, że język C# nie ma oddzielnej biblioteki środowiska uruchomieniowego.Note that C# itself does not have a separate runtime library. Zamiast tego .NET Framework jest biblioteką środowiska uruchomieniowego języka C#.Instead, the .NET Framework is the runtime library of C#.

Struktura programuProgram structure

Kluczowe koncepcje organizacyjne w języku C# to programy _, _przestrzenie nazw_, _typy_, _elementy członkowskie_ i _zestawy*.The key organizational concepts in C# are programs _, _namespaces*, types, members, and *assemblies*. Programy w języku C# składają się z co najmniej jednego pliku źródłowego.C# programs consist of one or more source files. Programy deklarują typy, które zawierają składowe i mogą być zorganizowane w przestrzenie nazw.Programs declare types, which contain members and can be organized into namespaces. Klasy i interfejsy są przykładami typów.Classes and interfaces are examples of types. Pola, metody, właściwości i zdarzenia są przykładami elementów członkowskich.Fields, methods, properties, and events are examples of members. Po skompilowaniu programów C# są one fizycznie spakowane do zestawów.When C# programs are compiled, they are physically packaged into assemblies. Zestawy zazwyczaj mają rozszerzenie pliku .exe lub, w zależności od tego .dll , czy implementują aplikacje , czy _ biblioteki *.Assemblies typically have the file extension .exe or .dll, depending on whether they implement applications or _*libraries**.

PrzykładThe example

using System;

namespace Acme.Collections
{
    public class Stack
    {
        Entry top;

        public void Push(object data) {
            top = new Entry(top, data);
        }

        public object Pop() {
            if (top == null) throw new InvalidOperationException();
            object result = top.data;
            top = top.next;
            return result;
        }

        class Entry
        {
            public Entry next;
            public object data;
    
            public Entry(Entry next, object data) {
                this.next = next;
                this.data = data;
            }
        }
    }
}

deklaruje klasę o nazwie Stack w przestrzeni nazw o nazwie Acme.Collections .declares a class named Stack in a namespace called Acme.Collections. W pełni kwalifikowana nazwa tej klasy to Acme.Collections.Stack .The fully qualified name of this class is Acme.Collections.Stack. Klasa zawiera kilka elementów członkowskich: pole o nazwie top , dwie metody o nazwie Push i Pop i zagnieżdżoną klasę o nazwie Entry .The class contains several members: a field named top, two methods named Push and Pop, and a nested class named Entry. EntryKlasa dodatkowo zawiera trzy elementy członkowskie: pole o nazwie next , pole o nazwie data i Konstruktor.The Entry class further contains three members: a field named next, a field named data, and a constructor. Przy założeniu, że kod źródłowy przykładu jest przechowywany w pliku acme.cs , wiersz poleceniaAssuming that the source code of the example is stored in the file acme.cs, the command line

csc /t:library acme.cs

kompiluje przykład jako bibliotekę (kod bez Main punktu wejścia) i tworzy zestaw o nazwie acme.dll .compiles the example as a library (code without a Main entry point) and produces an assembly named acme.dll.

Zestawy zawierają kod wykonywalny w formie * instrukcje języka pośredniego _ (IL) i informacje symboliczne w formie _ Metadata *.Assemblies contain executable code in the form of Intermediate Language _ (IL) instructions, and symbolic information in the form of _metadata**. Przed wykonaniem kod IL w zestawie jest automatycznie konwertowany na kod specyficzny dla procesora przez kompilator just-in-Time (JIT) środowiska uruchomieniowego języka wspólnego platformy .NET.Before it is executed, the IL code in an assembly is automatically converted to processor-specific code by the Just-In-Time (JIT) compiler of .NET Common Language Runtime.

Ponieważ zestaw jest samoopisującą się jednostką funkcji obejmujących zarówno kod, jak i metadane, nie ma potrzeby stosowania #include dyrektyw i plików nagłówkowe w języku C#.Because an assembly is a self-describing unit of functionality containing both code and metadata, there is no need for #include directives and header files in C#. Typy publiczne i składowe zawarte w określonym zestawie są udostępniane w programie C# po prostu przez odwołanie się do tego zestawu podczas kompilowania programu.The public types and members contained in a particular assembly are made available in a C# program simply by referencing that assembly when compiling the program. Na przykład ten program używa Acme.Collections.Stack klasy z acme.dll zestawu:For example, this program uses the Acme.Collections.Stack class from the acme.dll assembly:

using System;
using Acme.Collections;

class Test
{
    static void Main() {
        Stack s = new Stack();
        s.Push(1);
        s.Push(10);
        s.Push(100);
        Console.WriteLine(s.Pop());
        Console.WriteLine(s.Pop());
        Console.WriteLine(s.Pop());
    }
}

Jeśli program jest przechowywany w pliku test.cs , po test.cs skompilowaniu acme.dll zestawu można odwoływać się za pomocą /r opcji kompilatora:If the program is stored in the file test.cs, when test.cs is compiled, the acme.dll assembly can be referenced using the compiler's /r option:

csc /r:acme.dll test.cs

Spowoduje to utworzenie zestawu wykonywalnego o nazwie test.exe , który w przypadku uruchamiania generuje dane wyjściowe:This creates an executable assembly named test.exe, which, when run, produces the output:

100
10
1

Język C# umożliwia przechowywanie tekstu źródłowego programu w kilku plikach źródłowych.C# permits the source text of a program to be stored in several source files. Podczas kompilowania wieloplikowego programu w języku C# wszystkie pliki źródłowe są przetwarzane razem, a pliki źródłowe mogą swobodnie odwoływać się do siebie nawzajem — jest to tak samo, jakby wszystkie pliki źródłowe zostały połączone w jeden duży plik przed przetworzeniem.When a multi-file C# program is compiled, all of the source files are processed together, and the source files can freely reference each other—conceptually, it is as if all the source files were concatenated into one large file before being processed. Deklaracje przesyłania dalej nie są nigdy konieczne w języku C#, ponieważ z kilkoma wyjątkami, zamówienie deklaracji jest nieważne.Forward declarations are never needed in C# because, with very few exceptions, declaration order is insignificant. Język C# nie ogranicza pliku źródłowego do deklarowania tylko jednego typu publicznego ani nie wymaga, aby nazwa pliku źródłowego była zgodna z typem zadeklarowanym w pliku źródłowym.C# does not limit a source file to declaring only one public type nor does it require the name of the source file to match a type declared in the source file.

Typy i zmienneTypes and variables

Istnieją dwa rodzaje typów w języku C#: *typy wartości _ i _ typy odwołań *.There are two kinds of types in C#: value types _ and _reference types**. Zmienne typów wartości bezpośrednio zawierają swoje dane, a zmienne typów referencyjnych przechowują odwołania do danych, które są znane jako obiekty.Variables of value types directly contain their data whereas variables of reference types store references to their data, the latter being known as objects. W przypadku typów referencyjnych istnieje możliwość, że dwie zmienne odwołują się do tego samego obiektu, w tym przypadku operacje na jednej zmiennej mają wpływ na obiekt, do którego odwołuje się inna zmienna.With reference types, it is possible for two variables to reference the same object and thus possible for operations on one variable to affect the object referenced by the other variable. W przypadku typów wartości zmiennych każda z nich ma własną kopię danych i nie jest możliwe wykonywanie operacji na nich, aby wpływać na inne (z wyjątkiem ref out zmiennych i parametrów).With value types, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other (except in the case of ref and out parameter variables).

Typy wartości języka C# są dalej podzielone na proste typy _, typy _wyliczeniowe_, _typy struktur_ i _Typy dopuszczające wartość null_, a typy odwołań języka C# są dalej podzielone na _typy klas_, _typy interfejsów_, _Typy tablic*_ i _ typy delegatów *.C#'s value types are further divided into simple types _, _enum types_, _struct types_, and _nullable types_, and C#'s reference types are further divided into _class types_, _interface types_, _array types_, and _delegate types**.

Poniższa tabela zawiera omówienie systemu typów języka C#.The following table provides an overview of C#'s type system.

KategoriaCategory OpisDescription
Typy wartościValue types Typy prosteSimple types Całkowita część ze znakiem: sbyte ,, short int , longSigned integral: sbyte, short, int, long
Całka bez znaku: byte ,, ushort uint , ulongUnsigned integral: byte, ushort, uint, ulong
Znaki Unicode: charUnicode characters: char
Liczba zmiennoprzecinkowa IEEE: float , doubleIEEE floating point: float, double
Liczba dziesiętna o dużej precyzji: decimalHigh-precision decimal: decimal
Typu boolBoolean: bool
Typy wyliczenioweEnum types Typy formularza zdefiniowane przez użytkownika enum E {...}User-defined types of the form enum E {...}
Typy strukturStruct types Typy formularza zdefiniowane przez użytkownika struct S {...}User-defined types of the form struct S {...}
Typy dopuszczające wartości nullNullable types Rozszerzenia wszystkich innych typów wartości z null wartościąExtensions of all other value types with a null value
Typy odwołańReference types Typy klasClass types Ostateczna Klasa bazowa dla wszystkich innych typów: objectUltimate base class of all other types: object
Ciągi Unicode: stringUnicode strings: string
Typy formularza zdefiniowane przez użytkownika class C {...}User-defined types of the form class C {...}
Typy interfejsówInterface types Typy formularza zdefiniowane przez użytkownika interface I {...}User-defined types of the form interface I {...}
Typy tablicArray types Pojedyncze i wielowymiarowe, na przykład int[] i int[,]Single- and multi-dimensional, for example, int[] and int[,]
Typy delegatówDelegate types Typy formularzy zdefiniowane przez użytkownika, np. delegate int D(...)User-defined types of the form e.g. delegate int D(...)

Osiem typów całkowitych zapewnia obsługę 8-bitowych, 16-bitowych, 32-bitowych i 64-bitowych wartości w postaci podpisanej lub niepodpisanej.The eight integral types provide support for 8-bit, 16-bit, 32-bit, and 64-bit values in signed or unsigned form.

Dwa typy zmiennoprzecinkowe, float i double , są reprezentowane przy użyciu 32-bitowej pojedynczej precyzji i 64-BITOWE formatów IEEE 754 o podwójnej precyzji.The two floating point types, float and double, are represented using the 32-bit single-precision and 64-bit double-precision IEEE 754 formats.

decimalTyp jest 128-bitowym typem danych odpowiednim dla obliczeń finansowych i pieniężnych.The decimal type is a 128-bit data type suitable for financial and monetary calculations.

Typ języka C# bool jest używany do reprezentowania wartości logicznych — wartości, które są albo true lub false .C#'s bool type is used to represent boolean values—values that are either true or false.

Przetwarzanie znaków i ciągów w języku C# używa kodowania Unicode.Character and string processing in C# uses Unicode encoding. charTyp reprezentuje jednostkę kodu UTF-16, a string Typ reprezentuje sekwencję jednostek kodu UTF-16.The char type represents a UTF-16 code unit, and the string type represents a sequence of UTF-16 code units.

Poniższa tabela zawiera podsumowanie typów liczbowych języka C#.The following table summarizes C#'s numeric types.

KategoriaCategory BitówBits TypType Zakres/precyzjaRange/Precision
Całkowita ze znakiemSigned integral 88 sbyte -128... 127-128...127
1616 short -32768... 32, 767-32,768...32,767
3232 int -2147483648... 2, 147, 483 647-2,147,483,648...2,147,483,647
6464 long -zakresu od... 9, 223, 372, 036, 854, 775,-9,223,372,036,854,775,808...9,223,372,036,854,775,807
Całkowita bez znakuUnsigned integral 88 byte 0... 2550...255
1616 ushort 0... 65, 5350...65,535
3232 uint 0... 4, 294, 967, 2950...4,294,967,295
6464 ulong 0... 18, 446, 744, 073, 709, 551, 6150...18,446,744,073,709,551,615
Liczba zmiennoprzecinkowaFloating point 3232 float 1,5 × 10 ^ − 45 do 3,4 × 10 ^ 38, 7-cyfrowa precyzja1.5 × 10^−45 to 3.4 × 10^38, 7-digit precision
6464 double 5,0 × 10 ^ − 324 do 1,7 × 10 ^ 308, 15-cyfrowa precyzja5.0 × 10^−324 to 1.7 × 10^308, 15-digit precision
Liczba dziesiętnaDecimal 128128 decimal 1,0 × 10 ^ − 28 do 7,9 × 10 ^ 28, 28-cyfrowa precyzja1.0 × 10^−28 to 7.9 × 10^28, 28-digit precision

Programy w języku C# używają deklaracji typów do tworzenia nowych typów.C# programs use type declarations to create new types. Deklaracja typu określa nazwę i składowe nowego typu.A type declaration specifies the name and the members of the new type. Pięć kategorii typów języka C# jest definiowanych przez użytkownika: typy klas, typy struktur, typy interfejsów, typy wyliczeniowe i typy delegatów.Five of C#'s categories of types are user-definable: class types, struct types, interface types, enum types, and delegate types.

Typ klasy definiuje strukturę danych, która zawiera składowe danych (pola) i składowe funkcji (metody, właściwości i inne).A class type defines a data structure that contains data members (fields) and function members (methods, properties, and others). Typy klas obsługują pojedyncze dziedziczenie i polimorfizm, czyli mechanizmy, w których klasy pochodne mogą poszerzać i specjalizację klas bazowych.Class types support single inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes.

Typ struktury jest podobny do typu klasy w tym, że reprezentuje strukturę z składowymi danych i składowymi funkcji.A struct type is similar to a class type in that it represents a structure with data members and function members. Jednak w przeciwieństwie do klas, struktury są typami wartości i nie wymagają przydziału sterty.However, unlike classes, structs are value types and do not require heap allocation. Typy struktur nie obsługują dziedziczenia określonego przez użytkownika, a wszystkie typy struktur niejawnie dziedziczą po typie object .Struct types do not support user-specified inheritance, and all struct types implicitly inherit from type object.

Typ interfejsu definiuje kontrakt jako nazwany zestaw elementów członkowskich funkcji publicznych.An interface type defines a contract as a named set of public function members. Klasa lub struktura implementująca interfejs musi zapewniać implementacje składowych funkcji interfejsu.A class or struct that implements an interface must provide implementations of the interface's function members. Interfejs może dziedziczyć z wielu interfejsów podstawowych, a Klasa lub struktura może zaimplementować wiele interfejsów.An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

Typ delegata reprezentuje odwołania do metod z określoną listą parametrów i zwracanym typem.A delegate type represents references to methods with a particular parameter list and return type. Delegaty umożliwiają traktowanie metod jako jednostek, które mogą być przypisane do zmiennych i przekazane jako parametry.Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Delegaty są podobne do koncepcji wskaźników funkcji, które znajdują się w innych językach, ale w przeciwieństwie do wskaźników funkcji Delegaty są zorientowane obiektowo i są bezpieczne dla typów.Delegates are similar to the concept of function pointers found in some other languages, but unlike function pointers, delegates are object-oriented and type-safe.

Typy klas, struktur, interfejsów i delegatów obsługują ogólne, dzięki czemu można je sparametryzowane z innymi typami.Class, struct, interface and delegate types all support generics, whereby they can be parameterized with other types.

Typ wyliczeniowy jest typem odrębnym o nazwanych stałych.An enum type is a distinct type with named constants. Każdy typ wyliczeniowy ma typ podstawowy, który musi być jednym z ośmiu typów całkowitych.Every enum type has an underlying type, which must be one of the eight integral types. Zestaw wartości typu wyliczeniowego jest taki sam jak zestaw wartości typu podstawowego.The set of values of an enum type is the same as the set of values of the underlying type.

Język C# obsługuje tablice o pojedynczym i wielowymiarowym dowolnego typu.C# supports single- and multi-dimensional arrays of any type. W przeciwieństwie do typów wymienionych powyżej, typy tablicy nie muszą być zadeklarowane przed użyciem.Unlike the types listed above, array types do not have to be declared before they can be used. Zamiast tego typy tablic są konstruowane przez następujące nazwy typu z nawiasami kwadratowymi.Instead, array types are constructed by following a type name with square brackets. Na przykład int[] jest tablicą jednowymiarową int , int[,] która jest tablicą dwuwymiarową int , i int[][] jest tablicą jednowymiarową tablic int jednowymiarowych.For example, int[] is a single-dimensional array of int, int[,] is a two-dimensional array of int, and int[][] is a single-dimensional array of single-dimensional arrays of int.

Typy dopuszczające wartość null nie muszą również być zadeklarowane, aby można było ich używać.Nullable types also do not have to be declared before they can be used. Dla każdego typu wartości niedopuszczających wartości null T istnieje odpowiedni typ dopuszczający wartość null T? , który może zawierać dodatkowe wartości null .For each non-nullable value type T there is a corresponding nullable type T?, which can hold an additional value null. Na przykład int? jest typem, który może zawierać dowolną 32 bitową liczbę całkowitą lub wartość null .For instance, int? is a type that can hold any 32 bit integer or the value null.

System typów języka C# jest jednorodny tak, że wartość dowolnego typu może być traktowana jako obiekt.C#'s type system is unified such that a value of any type can be treated as an object. Każdy typ w języku C# bezpośrednio lub pośrednio pochodzi od object typu klasy i object jest ostateczną klasą bazową wszystkich typów.Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. Wartości typów referencyjnych są traktowane jako obiekty, po prostu wyświetlając wartości jako typ object .Values of reference types are treated as objects simply by viewing the values as type object. Wartości typów wartości są traktowane jako obiekty przez wykonywanie opakowania i depakowanie _ operacji_*.Values of value types are treated as objects by performing boxing _ and _ unboxing operations. W poniższym przykładzie int wartość jest konwertowana na object i z powrotem do int .In the following example, an int value is converted to object and back again to int.

using System;

class Test
{
    static void Main() {
        int i = 123;
        object o = i;          // Boxing
        int j = (int)o;        // Unboxing
    }
}

Gdy wartość typu wartości jest konwertowana na typ object , wystąpienie obiektu, nazywane również "polem", jest przydzielone do przechowywania wartości, a wartość jest kopiowana do tego pola.When a value of a value type is converted to type object, an object instance, also called a "box," is allocated to hold the value, and the value is copied into that box. Z drugiej strony, gdy object odwołanie jest rzutowane na typ wartości, jest przeprowadzane sprawdzenie, że przywoływany obiekt jest polem poprawnego typu wartości i, jeśli sprawdzenie zakończy się powodzeniem, wartość w polu jest kopiowana.Conversely, when an object reference is cast to a value type, a check is made that the referenced object is a box of the correct value type, and, if the check succeeds, the value in the box is copied out.

Ujednolicony system typów języka C# efektywnie oznacza, że typy wartości mogą stać się obiektami "na żądanie".C#'s unified type system effectively means that value types can become objects "on demand." Ze względu na niezjednoczenie bibliotek ogólnego przeznaczenia, które używają typu, object można używać zarówno z typami referencyjnymi, jak i typami wartości.Because of the unification, general-purpose libraries that use type object can be used with both reference types and value types.

W języku C# istnieje kilka rodzajów zmiennych , w tym pola, elementy tablicy, zmienne lokalne i parametry.There are several kinds of variables in C#, including fields, array elements, local variables, and parameters. Zmienne reprezentują lokalizacje przechowywania, a Każda zmienna ma typ, który określa, jakie wartości mogą być przechowywane w zmiennej, jak pokazano w poniższej tabeli.Variables represent storage locations, and every variable has a type that determines what values can be stored in the variable, as shown by the following table.

Typ zmiennejType of Variable Możliwa zawartośćPossible Contents
Typ wartości niedopuszczający wartości nullNon-nullable value type Wartość tego dokładnego typuA value of that exact type
Typ wartości nullNullable value type Wartość null lub wartość tego dokładnego typuA null value or a value of that exact type
object Odwołanie o wartości null, odwołanie do obiektu dowolnego typu odwołania lub odwołanie do wartości opakowanej dowolnego typu wartościA null reference, a reference to an object of any reference type, or a reference to a boxed value of any value type
Typ klasyClass type Odwołanie o wartości null, odwołanie do wystąpienia tego typu klasy lub odwołanie do wystąpienia klasy pochodzącej od tego typu klasy.A null reference, a reference to an instance of that class type, or a reference to an instance of a class derived from that class type
Typ interfejsuInterface type Odwołanie o wartości null, odwołanie do wystąpienia typu klasy implementującego ten typ interfejsu lub odwołanie do wartości opakowanej typu wartości implementującej ten typ interfejsuA null reference, a reference to an instance of a class type that implements that interface type, or a reference to a boxed value of a value type that implements that interface type
Typ tablicyArray type Odwołanie o wartości null, odwołanie do wystąpienia tego typu tablicy lub odwołanie do wystąpienia zgodnego typu tablicyA null reference, a reference to an instance of that array type, or a reference to an instance of a compatible array type
Typ delegataDelegate type Odwołanie o wartości null lub odwołanie do wystąpienia tego typu delegataA null reference or a reference to an instance of that delegate type

WyrażeniaExpressions

Wyrażenia _ są zbudowane z _argumentów operacji_ i _operatorów*.Expressions _ are constructed from _operands* and *operators*. Operatory wyrażenia wskazują, które operacje mają być stosowane do operandów.The operators of an expression indicate which operations to apply to the operands. Przykłady operatorów obejmują + , - , _ , / , i new .Examples of operators include +, -, _, /, and new. Przykłady operandów obejmują literały, pola, zmienne lokalne i wyrażenia.Examples of operands include literals, fields, local variables, and expressions.

Gdy wyrażenie zawiera wiele operatorów, *pierwszeństwo _ operatorów określa kolejność, w której są oceniane poszczególne operatory.When an expression contains multiple operators, the *precedence _ of the operators controls the order in which the individual operators are evaluated. Na przykład wyrażenie x + y _ z jest oceniane tak, jakby x + (y * z) * operator miał wyższy priorytet niż + operator.For example, the expression x + y _ z is evaluated as x + (y * z) because the * operator has higher precedence than the + operator.

Większość operatorów może być przeciążona.Most operators can be overloaded. Przeciążanie operatora umożliwia określenie implementacji operatora zdefiniowanego przez użytkownika dla operacji, w których jeden lub oba operandy są klasy lub typu struktury zdefiniowanej przez użytkownika.Operator overloading permits user-defined operator implementations to be specified for operations where one or both of the operands are of a user-defined class or struct type.

Poniższa tabela podsumowuje operatory języka C#, wymieniając kategorie operatorów w kolejności od najwyższego do najniższego.The following table summarizes C#'s operators, listing the operator categories in order of precedence from highest to lowest. Operatory w tej samej kategorii mają równy priorytet.Operators in the same category have equal precedence.

KategoriaCategory WyrażenieExpression OpisDescription
PodstawowePrimary x.m Dostęp do elementu członkowskiegoMember access
x(...) Wywołanie metody i delegataMethod and delegate invocation
x[...] Dostęp do tablicy i indeksatoraArray and indexer access
x++ PostinkrementacjaPost-increment
x-- PostdekrementacjaPost-decrement
new T(...) Utworzenie obiektu i delegataObject and delegate creation
new T(...){...} Tworzenie obiektu z inicjatoremObject creation with initializer
new {...} Inicjator obiektu anonimowegoAnonymous object initializer
new T[...] Tworzenie tablicyArray creation
typeof(T) Uzyskaj System.Type obiekt dla TObtain System.Type object for T
checked(x) Obliczenie wyrażenia w kontekście sprawdzanymEvaluate expression in checked context
unchecked(x) Obliczenie wyrażenia w kontekście niesprawdzanymEvaluate expression in unchecked context
default(T) Uzyskaj wartość domyślną typu TObtain default value of type T
delegate {...} Funkcja anonimowa (metoda anonimowa)Anonymous function (anonymous method)
JednoargumentowyUnary +x TożsamośćIdentity
-x NegacjaNegation
!x Logiczna negacjaLogical negation
~x Negacja bitowaBitwise negation
++x PreinkrementacjaPre-increment
--x PredekrementacjaPre-decrement
(T)x Jawnie Konwertuj x na typ TExplicitly convert x to type T
await x Asynchroniczne oczekiwanie na x zakończenieAsynchronously wait for x to complete
MnożenieMultiplicative x * y MnożenieMultiplication
x / y DzielenieDivision
x % y ResztaRemainder
DodawanieAdditive x + y Dodawanie, łączenie ciągów, łączenie delegatówAddition, string concatenation, delegate combination
x - y Odejmowanie, usuwanie delegataSubtraction, delegate removal
PrzesunięciaShift x << y Przesunięcie w lewoShift left
x >> y Przesunięcie w prawoShift right
Testowanie relacyjne i typuRelational and type testing x < y Mniejsze niżLess than
x > y Większe niżGreater than
x <= y Mniejsze niż lub równeLess than or equal
x >= y Większe niż lub równeGreater than or equal
x is T Zwracaj true x , jeśli jest T , false w przeciwnym razieReturn true if x is a T, false otherwise
x as T Zwraca x wartość wpisaną jako T , lub null Jeśli x nie jest TReturn x typed as T, or null if x is not a T
RównośćEquality x == y RówneEqual
x != y Nie równa sięNot equal
Logiczne ANDLogical AND x & y Liczba całkowita bitowa, koniunkcja logiczna iInteger bitwise AND, boolean logical AND
XOR logiczneLogical XOR x ^ y Bitowe XOR (Integer), Boolean logiczna XORInteger bitwise XOR, boolean logical XOR
Logiczne ORLogical OR x | y Liczba całkowita bitowa, wartość logiczna logiczne orInteger bitwise OR, boolean logical OR
AND warunkoweConditional AND x && y Oblicza tylko wtedy, y gdy x jest trueEvaluates y only if x is true
OR warunkoweConditional OR x || y Oblicza tylko wtedy, y gdy x jest falseEvaluates y only if x is false
Łączenie wartości nullNull coalescing x ?? y y x Jest wynikiem null , aby w x przeciwnym razieEvaluates to y if x is null, to x otherwise
WarunkoweConditional x ? y : z Daje y w przypadku x true , gdy z x jest falseEvaluates y if x is true, z if x is false
Przypisanie lub funkcja anonimowaAssignment or anonymous function x = y PrzypisanieAssignment
x op= y Przypisanie złożone; obsługiwane operatory *= /= %= += to -= <<= >>= &= ^=|=Compound assignment; supported operators are *= /= %= += -= <<= >>= &= ^= |=
(T x) => y Funkcja anonimowa (wyrażenie lambda)Anonymous function (lambda expression)

InstrukcjeStatements

Akcje programu są wyrażane przy użyciu instrukcji.The actions of a program are expressed using statements. Język C# obsługuje kilka różnych rodzajów instrukcji, które są zdefiniowane w postaci instrukcji osadzonych.C# supports several different kinds of statements, a number of which are defined in terms of embedded statements.

Blok umożliwia zapisanie wielu instrukcji w kontekstach, w których Pojedyncza instrukcja jest dozwolona.A block permits multiple statements to be written in contexts where a single statement is allowed. Blok składa się z listy instrukcji pisanych między ogranicznikami { i } .A block consists of a list of statements written between the delimiters { and }.

Instrukcje deklaracji są używane do deklarowania zmiennych lokalnych i stałych.Declaration statements are used to declare local variables and constants.

Instrukcje wyrażeń są używane do obliczania wyrażeń.Expression statements are used to evaluate expressions. Wyrażenia, które mogą być używane jako instrukcje, obejmują wywołania metod, alokacje obiektów za pomocą new operatora, przypisania przy użyciu = i operatorów przypisania złożonego, operacji zwiększania i zmniejszania przy użyciu ++ -- operatorów operatory i await.Expressions that can be used as statements include method invocations, object allocations using the new operator, assignments using = and the compound assignment operators, increment and decrement operations using the ++ and -- operators and await expressions.

Instrukcje wyboru są używane do wybierania jednej z wielu możliwych instrukcji do wykonania na podstawie wartości niektórych wyrażeń.Selection statements are used to select one of a number of possible statements for execution based on the value of some expression. W tej grupie są if instrukcje i switch .In this group are the if and switch statements.

Instrukcje iteracji są używane do wielokrotnego wykonywania osadzonej instrukcji.Iteration statements are used to repeatedly execute an embedded statement. W tej grupie są while instrukcje, do , for , i foreach .In this group are the while, do, for, and foreach statements.

Instrukcje skoku są używane do transferowania kontroli.Jump statements are used to transfer control. W tej grupie są break instrukcje, continue ,,, goto throw return i yield .In this group are the break, continue, goto, throw, return, and yield statements.

tryInstrukcja... służy catch do przechwytywania wyjątków, które występują podczas wykonywania bloku, a try instrukcja... finally jest używana do określania kodu finalizacji, który jest zawsze wykonywany, niezależnie od tego, czy wystąpił wyjątek, czy nie.The try...catch statement is used to catch exceptions that occur during execution of a block, and the try...finally statement is used to specify finalization code that is always executed, whether an exception occurred or not.

checkedInstrukcje and unchecked są używane do kontrolowania kontekstu sprawdzania przepełnienia dla operacji arytmetycznych typu całkowitego i konwersji.The checked and unchecked statements are used to control the overflow checking context for integral-type arithmetic operations and conversions.

lockInstrukcja służy do uzyskiwania blokady wzajemnego wykluczania dla danego obiektu, wykonywania instrukcji i zwalniania blokady.The lock statement is used to obtain the mutual-exclusion lock for a given object, execute a statement, and then release the lock.

usingInstrukcja służy do uzyskiwania zasobu, wykonywania instrukcji, a następnie usuwania tego zasobu.The using statement is used to obtain a resource, execute a statement, and then dispose of that resource.

Poniżej przedstawiono przykłady poszczególnych rodzajów instrukcjiBelow are examples of each kind of statement

Deklaracje zmiennej lokalnejLocal variable declarations

static void Main() {
   int a;
   int b = 2, c = 3;
   a = 1;
   Console.WriteLine(a + b + c);
}

Lokalna deklaracja stałaLocal constant declaration

static void Main() {
    const float pi = 3.1415927f;
    const int r = 25;
    Console.WriteLine(pi * r * r);
}

Instrukcja wyrażeńExpression statement

static void Main() {
    int i;
    i = 123;                // Expression statement
    Console.WriteLine(i);   // Expression statement
    i++;                    // Expression statement
    Console.WriteLine(i);   // Expression statement
}

if Mergeif statement

static void Main(string[] args) {
    if (args.Length == 0) {
        Console.WriteLine("No arguments");
    }
    else {
        Console.WriteLine("One or more arguments");
    }
}

switch Mergeswitch statement

static void Main(string[] args) {
    int n = args.Length;
    switch (n) {
        case 0:
            Console.WriteLine("No arguments");
            break;
        case 1:
            Console.WriteLine("One argument");
            break;
        default:
            Console.WriteLine("{0} arguments", n);
            break;
    }
}

while Mergewhile statement

static void Main(string[] args) {
    int i = 0;
    while (i < args.Length) {
        Console.WriteLine(args[i]);
        i++;
    }
}

do Mergedo statement

static void Main() {
    string s;
    do {
        s = Console.ReadLine();
        if (s != null) Console.WriteLine(s);
    } while (s != null);
}

for Mergefor statement

static void Main(string[] args) {
    for (int i = 0; i < args.Length; i++) {
        Console.WriteLine(args[i]);
    }
}

foreach Mergeforeach statement

static void Main(string[] args) {
    foreach (string s in args) {
        Console.WriteLine(s);
    }
}

break Mergebreak statement

static void Main() {
    while (true) {
        string s = Console.ReadLine();
        if (s == null) break;
        Console.WriteLine(s);
    }
}

continue Mergecontinue statement

static void Main(string[] args) {
    for (int i = 0; i < args.Length; i++) {
        if (args[i].StartsWith("/")) continue;
        Console.WriteLine(args[i]);
    }
}

goto Mergegoto statement

static void Main(string[] args) {
    int i = 0;
    goto check;
    loop:
    Console.WriteLine(args[i++]);
    check:
    if (i < args.Length) goto loop;
}

return Mergereturn statement

static int Add(int a, int b) {
    return a + b;
}

static void Main() {
    Console.WriteLine(Add(1, 2));
    return;
}

yield Mergeyield statement

static IEnumerable<int> Range(int from, int to) {
    for (int i = from; i < to; i++) {
        yield return i;
    }
    yield break;
}

static void Main() {
    foreach (int x in Range(-10,10)) {
        Console.WriteLine(x);
    }
}

throw and — try instrukcjethrow and try statements

static double Divide(double x, double y) {
    if (y == 0) throw new DivideByZeroException();
    return x / y;
}

static void Main(string[] args) {
    try {
        if (args.Length != 2) {
            throw new Exception("Two numbers required");
        }
        double x = double.Parse(args[0]);
        double y = double.Parse(args[1]);
        Console.WriteLine(Divide(x, y));
    }
    catch (Exception e) {
        Console.WriteLine(e.Message);
    }
    finally {
        Console.WriteLine("Good bye!");
    }
}

checked and — unchecked instrukcjechecked and unchecked statements

static void Main() {
    int i = int.MaxValue;
    checked {
        Console.WriteLine(i + 1);        // Exception
    }
    unchecked {
        Console.WriteLine(i + 1);        // Overflow
    }
}

lock Mergelock statement

class Account
{
    decimal balance;
    public void Withdraw(decimal amount) {
        lock (this) {
            if (amount > balance) {
                throw new Exception("Insufficient funds");
            }
            balance -= amount;
        }
    }
}

using Mergeusing statement

static void Main() {
    using (TextWriter w = File.CreateText("test.txt")) {
        w.WriteLine("Line one");
        w.WriteLine("Line two");
        w.WriteLine("Line three");
    }
}

Klasy i obiektyClasses and objects

*Klasy _ są największą podstawą typów języka C#.*Classes _ are the most fundamental of C#'s types. Klasa jest strukturą danych, która łączy stan (pola) i akcje (metody i inne elementy członkowskie funkcji) w jednej jednostce.A class is a data structure that combines state (fields) and actions (methods and other function members) in a single unit. Klasa zawiera definicję dla dynamicznie utworzonych wystąpień klasy, znanych również jako obiekty.A class provides a definition for dynamically created instances of the class, also known as objects. Klasy obsługują dziedziczenie i polimorfizm, czyli mechanizmy, w których klasy pochodne mogą poszerzać i specialize _ klasy bazowe *.Classes support inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize _*base classes**.

Nowe klasy są tworzone za pomocą deklaracji klasy.New classes are created using class declarations. Deklaracja klasy rozpoczyna się od nagłówka, który określa atrybuty i Modyfikatory klasy, nazwę klasy, klasę bazową (jeśli ma to zastosowanie) i interfejsy zaimplementowane przez klasę.A class declaration starts with a header that specifies the attributes and modifiers of the class, the name of the class, the base class (if given), and the interfaces implemented by the class. Po tym nagłówku następuje treść klasy, która składa się z listy deklaracji elementów członkowskich, które są zapisywane między ogranicznikami { i } .The header is followed by the class body, which consists of a list of member declarations written between the delimiters { and }.

Poniżej znajduje się deklaracja klasy prostej o nazwie Point :The following is a declaration of a simple class named Point:

public class Point
{
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

Wystąpienia klas są tworzone przy użyciu new operatora, który przydziela pamięć dla nowego wystąpienia, wywołuje konstruktora w celu zainicjowania wystąpienia i zwraca odwołanie do wystąpienia.Instances of classes are created using the new operator, which allocates memory for a new instance, invokes a constructor to initialize the instance, and returns a reference to the instance. Poniższe instrukcje tworzą dwa Point obiekty i przechowują odwołania do tych obiektów w dwóch zmiennych:The following statements create two Point objects and store references to those objects in two variables:

Point p1 = new Point(0, 0);
Point p2 = new Point(10, 20);

Pamięć zajęta przez obiekt jest automatycznie odzyskiwana, gdy obiekt nie jest już używany.The memory occupied by an object is automatically reclaimed when the object is no longer in use. Nie jest to konieczne ani możliwe, aby jawnie cofnąć alokację obiektów w języku C#.It is neither necessary nor possible to explicitly deallocate objects in C#.

Elementy członkowskieMembers

Elementy członkowskie klasy są *statycznymi składowymi _ lub _ elementy członkowskie wystąpienia *.The members of a class are either static members _ or _instance members**. Statyczne składowe należą do klas, a elementy członkowskie wystąpienia należą do obiektów (wystąpień klas).Static members belong to classes, and instance members belong to objects (instances of classes).

Poniższa tabela zawiera omówienie rodzajów elementów członkowskich, które może zawierać Klasa.The following table provides an overview of the kinds of members a class can contain.

CzłonekMember OpisDescription
StałeConstants Wartości stałe skojarzone z klasąConstant values associated with the class
PolaFields Zmienne klasyVariables of the class
MetodyMethods Obliczenia i akcje, które mogą być wykonywane przez klasęComputations and actions that can be performed by the class
WłaściwościProperties Akcje skojarzone z odczytem i pisaniem nazwanych właściwości klasyActions associated with reading and writing named properties of the class
Indexers (Indeksatory)Indexers Akcje skojarzone z wystąpieniami indeksowania klasy, takimi jak tablicaActions associated with indexing instances of the class like an array
ZdarzeniaEvents Powiadomienia, które mogą zostać wygenerowane przez klasęNotifications that can be generated by the class
OperatoryOperators Konwersje i operatory wyrażeń obsługiwane przez klasęConversions and expression operators supported by the class
KonstruktoryConstructors Akcje wymagane do zainicjowania wystąpień klasy lub samej klasyActions required to initialize instances of the class or the class itself
DestruktoryDestructors Akcje do wykonania przed trwałe odrzuceniem wystąpień klasyActions to perform before instances of the class are permanently discarded
TypyTypes Zagnieżdżone typy zadeklarowane przez klasęNested types declared by the class

Ułatwienia dostępuAccessibility

Każdy element członkowski klasy ma skojarzoną dostępność, która kontroluje regiony tekstu programu, które mogą uzyskać dostęp do elementu członkowskiego.Each member of a class has an associated accessibility, which controls the regions of program text that are able to access the member. Istnieje pięć możliwych form ułatwień dostępu.There are five possible forms of accessibility. Podsumowanie dotyczące tych raportów można znaleźć w poniższej tabeli.These are summarized in the following table.

Ułatwienia dostępuAccessibility ZnaczenieMeaning
public Dostęp nie jest ograniczonyAccess not limited
protected Dostęp ograniczony do tej klasy lub klas pochodnych od tej klasyAccess limited to this class or classes derived from this class
internal Dostęp ograniczony do tego programuAccess limited to this program
protected internal Dostęp ograniczony do tego programu lub klas pochodzących od tej klasyAccess limited to this program or classes derived from this class
private Dostęp ograniczony do tej klasyAccess limited to this class

Parametry typuType parameters

Definicja klasy może określać zestaw parametrów typu przez poniższą nazwę klasy z nawiasami kątowymi zawierającymi listę nazw parametrów typu.A class definition may specify a set of type parameters by following the class name with angle brackets enclosing a list of type parameter names. Parametry typu mogą być następnie używane w treści deklaracji klasy do definiowania elementów członkowskich klasy.The type parameters can then be used in the body of the class declarations to define the members of the class. W poniższym przykładzie parametry typu PairTFirst i TSecond :In the following example, the type parameters of Pair are TFirst and TSecond:

public class Pair<TFirst,TSecond>
{
    public TFirst First;
    public TSecond Second;
}

Typ klasy zadeklarowanej do wykonania parametrów typu jest nazywany typem klasy generycznej.A class type that is declared to take type parameters is called a generic class type. Typy struktur, interfejsów i delegatów mogą być również rodzajowe.Struct, interface and delegate types can also be generic.

Gdy używana jest Klasa generyczna, należy podać argumenty typu dla każdego z parametrów typu:When the generic class is used, type arguments must be provided for each of the type parameters:

Pair<int,string> pair = new Pair<int,string> { First = 1, Second = "two" };
int i = pair.First;     // TFirst is int
string s = pair.Second; // TSecond is string

Typ ogólny z podanymi argumentami typu, jak Pair<int,string> powyżej, jest nazywany typem skonstruowanym.A generic type with type arguments provided, like Pair<int,string> above, is called a constructed type.

Klas podstawowychBase classes

Deklaracja klasy może określać klasę bazową, postępując według nazwy klasy i parametrów typu z dwukropkiem i nazwą klasy bazowej.A class declaration may specify a base class by following the class name and type parameters with a colon and the name of the base class. Pominięcie specyfikacji klasy bazowej jest taka sama jak pochodna typu object .Omitting a base class specification is the same as deriving from type object. W poniższym przykładzie klasą bazową Point3D jest Point , a klasą bazową Point jest object :In the following example, the base class of Point3D is Point, and the base class of Point is object:

public class Point
{
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

public class Point3D: Point
{
    public int z;

    public Point3D(int x, int y, int z): base(x, y) {
        this.z = z;
    }
}

Klasa dziedziczy elementy członkowskie swojej klasy bazowej.A class inherits the members of its base class. Dziedziczenie oznacza, że Klasa niejawnie zawiera wszystkie elementy członkowskie swojej klasy podstawowej, z wyjątkiem dla wystąpienia i konstruktorów statycznych i destruktorów klasy bazowej.Inheritance means that a class implicitly contains all members of its base class, except for the instance and static constructors, and the destructors of the base class. Klasa pochodna może dodawać nowych członków do tych, które dziedziczy, ale nie może usunąć definicji dziedziczonego elementu członkowskiego.A derived class can add new members to those it inherits, but it cannot remove the definition of an inherited member. W poprzednim przykładzie Point3D dziedziczy x y pola i z Point , i każde Point3D wystąpienie zawiera trzy pola, x , y , i z .In the previous example, Point3D inherits the x and y fields from Point, and every Point3D instance contains three fields, x, y, and z.

Niejawna konwersja istnieje z typu klasy do dowolnego z jego typów klas podstawowych.An implicit conversion exists from a class type to any of its base class types. W związku z tym zmienna typu klasy może odwoływać się do wystąpienia tej klasy lub wystąpienia dowolnej klasy pochodnej.Therefore, a variable of a class type can reference an instance of that class or an instance of any derived class. Na przykład uwzględniając poprzednie deklaracje klas, zmienna typu Point może odwoływać się do Point lub Point3D :For example, given the previous class declarations, a variable of type Point can reference either a Point or a Point3D:

Point a = new Point(10, 20);
Point b = new Point3D(10, 20, 30);

PolaFields

Pole jest zmienną, która jest skojarzona z klasą lub wystąpieniem klasy.A field is a variable that is associated with a class or with an instance of a class.

Pole zadeklarowane z static modyfikatorem definiuje pole statyczne.A field declared with the static modifier defines a static field. Pole statyczne identyfikuje dokładnie jedną lokalizację magazynu.A static field identifies exactly one storage location. Niezależnie od tego, ile wystąpień klasy zostało utworzonych, istnieje tylko jedna kopia pola statycznego.No matter how many instances of a class are created, there is only ever one copy of a static field.

Pole zadeklarowane bez static modyfikatora definiuje pole wystąpienia.A field declared without the static modifier defines an instance field. Każde wystąpienie klasy zawiera oddzielną kopię wszystkich pól wystąpienia tej klasy.Every instance of a class contains a separate copy of all the instance fields of that class.

W poniższym przykładzie każde wystąpienie Color klasy ma oddzielną kopię r g pól,, i b wystąpienia, ale istnieje tylko jedna kopia Black pól,, White Red , Green i Blue pola statyczne:In the following example, each instance of the Color class has a separate copy of the r, g, and b instance fields, but there is only one copy of the Black, White, Red, Green, and Blue static fields:

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);
    private byte r, g, b;

    public Color(byte r, byte g, byte b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }
}

Jak pokazano w poprzednim przykładzie pola tylko do odczytu mogą być zadeklarowane za pomocą readonly modyfikatora.As shown in the previous example, read-only fields may be declared with a readonly modifier. Przypisanie do readonly pola może wystąpić tylko jako część deklaracji pola lub konstruktora w tej samej klasie.Assignment to a readonly field can only occur as part of the field's declaration or in a constructor in the same class.

MetodyMethods

*Metoda _ jest składową implementującą obliczenia lub akcję, które mogą być wykonywane przez obiekt lub klasę.A *method _ is a member that implements a computation or action that can be performed by an object or class. Metody statyczne są dostępne za pomocą klasy.Static methods are accessed through the class. _ Metody wystąpień* są dostępne za pomocą wystąpień klasy._ Instance methods* are accessed through instances of the class.

Metody mają (prawdopodobnie pustą) listę *parametrów _, które reprezentują wartości lub odwołania do zmiennych, które są przenoszone do metody i _ Typ zwracany *, który określa typ wartości obliczanej i zwracanej przez metodę.Methods have a (possibly empty) list of parameters _, which represent values or variable references passed to the method, and a _return type**, which specifies the type of the value computed and returned by the method. Zwracany typ metody to, void Jeśli nie zwraca wartości.A method's return type is void if it does not return a value.

Podobnie jak typy, metody mogą także mieć zestaw parametrów typu, dla których argumenty typu muszą być określone, gdy wywoływana jest metoda.Like types, methods may also have a set of type parameters, for which type arguments must be specified when the method is called. W przeciwieństwie do typów, argumenty typu często można wywnioskować na podstawie argumentów wywołania metody i nie muszą być jawnie określone.Unlike types, the type arguments can often be inferred from the arguments of a method call and need not be explicitly given.

Sygnatura metody musi być unikatowa w klasie, w której metoda jest zadeklarowana.The signature of a method must be unique in the class in which the method is declared. Podpis metody składa się z nazwy metody, liczby parametrów typu oraz liczby, modyfikatorów i typów jego parametrów.The signature of a method consists of the name of the method, the number of type parameters and the number, modifiers, and types of its parameters. Sygnatura metody nie zawiera typu zwracanego.The signature of a method does not include the return type.

ParametryParameters

Parametry służą do przekazywania wartości lub odwołań do zmiennych do metod.Parameters are used to pass values or variable references to methods. Parametry metody pobierają rzeczywiste wartości z argumentów , które są określone podczas wywoływania metody.The parameters of a method get their actual values from the arguments that are specified when the method is invoked. Istnieją cztery rodzaje parametrów: parametry wartości, parametry odwołania, parametry wyjściowe i tablice parametrów.There are four kinds of parameters: value parameters, reference parameters, output parameters, and parameter arrays.

Parametr value jest używany do przekazywania parametru wejściowego.A value parameter is used for input parameter passing. Parametr value odnosi się do zmiennej lokalnej, która pobiera jej wartość początkową z argumentu, który został przesłany dla parametru.A value parameter corresponds to a local variable that gets its initial value from the argument that was passed for the parameter. Modyfikacje parametru value nie wpływają na argument, który został przesłany dla parametru.Modifications to a value parameter do not affect the argument that was passed for the parameter.

Parametry wartości mogą być opcjonalne, określając wartość domyślną, aby można było pominąć odpowiednie argumenty.Value parameters can be optional, by specifying a default value so that corresponding arguments can be omitted.

Parametr Reference służy do przekazywania parametrów wejściowych i wyjściowych.A reference parameter is used for both input and output parameter passing. Argument przesłany dla parametru odwołania musi być zmienną i podczas wykonywania metody parametr Reference reprezentuje tę samą lokalizację magazynu co zmienna argumentu.The argument passed for a reference parameter must be a variable, and during execution of the method, the reference parameter represents the same storage location as the argument variable. Parametr odwołania jest zadeklarowany z ref modyfikatorem.A reference parameter is declared with the ref modifier. W poniższym przykładzie pokazano sposób użycia ref parametrów.The following example shows the use of ref parameters.

using System;

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

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

Parametr wyjściowy jest używany do przekazywania parametrów wyjściowych.An output parameter is used for output parameter passing. Parametr wyjściowy jest podobny do parametru odwołania, z tą różnicą, że początkowa wartość argumentu dostarczonego przez wywołującego jest nieważna.An output parameter is similar to a reference parameter except that the initial value of the caller-provided argument is unimportant. Parametr wyjściowy jest zadeklarowany z out modyfikatorem.An output parameter is declared with the out modifier. W poniższym przykładzie pokazano sposób użycia out parametrów.The following example shows the use of out parameters.

using System;

class Test
{
    static void Divide(int x, int y, out int result, out int remainder) {
        result = x / y;
        remainder = x % y;
    }

    static void Main() {
        int res, rem;
        Divide(10, 3, out res, out rem);
        Console.WriteLine("{0} {1}", res, rem);    // Outputs "3 1"
    }
}

Tablica parametrów umożliwia przekazanie zmiennej liczbie argumentów do metody.A parameter array permits a variable number of arguments to be passed to a method. Tablica parametrów jest zadeklarowana z params modyfikatorem.A parameter array is declared with the params modifier. Tylko ostatni parametr metody może być tablicą parametrów, a typ tablicy parametrów musi być typem tablicy jednowymiarowej.Only the last parameter of a method can be a parameter array, and the type of a parameter array must be a single-dimensional array type. WriteMetody i WriteLine System.Console klasy są dobrymi przykładami użycia tablicy parametrów.The Write and WriteLine methods of the System.Console class are good examples of parameter array usage. Są one deklarowane w następujący sposób.They are declared as follows.

public class Console
{
    public static void Write(string fmt, params object[] args) {...}
    public static void WriteLine(string fmt, params object[] args) {...}
    ...
}

W metodzie, która używa tablicy parametrów, tablica parametrów zachowuje się dokładnie tak jak zwykły parametr typu tablicy.Within a method that uses a parameter array, the parameter array behaves exactly like a regular parameter of an array type. Jednak w wywołaniu metody z tablicą parametrów możliwe jest przekazanie jednego argumentu typu tablicy parametrów lub dowolnej liczby argumentów typu elementu tablicy parametrów w parametrze.However, in an invocation of a method with a parameter array, it is possible to pass either a single argument of the parameter array type or any number of arguments of the element type of the parameter array. W tym drugim przypadku wystąpienie tablicy jest automatycznie tworzone i inicjowane z podanym argumentami.In the latter case, an array instance is automatically created and initialized with the given arguments. Ten przykładThis example

Console.WriteLine("x={0} y={1} z={2}", x, y, z);

jest równoznaczny z zapisem poniżej.is equivalent to writing the following.

string s = "x={0} y={1} z={2}";
object[] args = new object[3];
args[0] = x;
args[1] = y;
args[2] = z;
Console.WriteLine(s, args);

Treść metody i zmienne lokalneMethod body and local variables

Treść metody Określa instrukcje do wykonania, gdy metoda jest wywoływana.A method's body specifies the statements to execute when the method is invoked.

Treść metody może deklarować zmienne, które są specyficzne dla wywołania metody.A method body can declare variables that are specific to the invocation of the method. Takie zmienne są nazywane zmiennymi lokalnymi.Such variables are called local variables. Deklaracja zmiennej lokalnej określa nazwę typu, nazwę zmiennej i prawdopodobnie wartość początkową.A local variable declaration specifies a type name, a variable name, and possibly an initial value. Poniższy przykład deklaruje zmienną lokalną i z początkową wartością zero i zmienną lokalną j bez wartości początkowej.The following example declares a local variable i with an initial value of zero and a local variable j with no initial value.

using System;

class Squares
{
    static void Main() {
        int i = 0;
        int j;
        while (i < 10) {
            j = i * i;
            Console.WriteLine("{0} x {0} = {1}", i, j);
            i = i + 1;
        }
    }
}

Język C# wymaga, aby zmienna lokalna była przypisana ostatecznie przed uzyskaniem jej wartości.C# requires a local variable to be definitely assigned before its value can be obtained. Na przykład jeśli deklaracja poprzedniej nie i zawierała wartości początkowej, kompilator zgłosi błąd dla kolejnych zastosowań, i ponieważ i nie zostanie on ostatecznie przypisany w tych punktach w programie.For example, if the declaration of the previous i did not include an initial value, the compiler would report an error for the subsequent usages of i because i would not be definitely assigned at those points in the program.

Metoda może użyć return instrukcji do zwrócenia kontroli do obiektu wywołującego.A method can use return statements to return control to its caller. W wyniku zwrócenia metody void return instrukcje nie mogą określać wyrażenia.In a method returning void, return statements cannot specify an expression. W metodzie zwracającej void nie, return instrukcje muszą zawierać wyrażenie, które oblicza wartość zwracaną.In a method returning non-void, return statements must include an expression that computes the return value.

Metody static i instanceStatic and instance methods

Metoda zadeklarowana za pomocą static modyfikatora jest metodą statyczną.A method declared with a static modifier is a static method. Metoda statyczna nie działa w konkretnym wystąpieniu i może bezpośrednio uzyskiwać dostęp do statycznych elementów członkowskich.A static method does not operate on a specific instance and can only directly access static members.

Metoda zadeklarowana bez static modyfikatora jest metodą wystąpienia.A method declared without a static modifier is an instance method. Metoda wystąpienia działa w konkretnym wystąpieniu i może uzyskiwać dostęp do elementów członkowskich static i instance.An instance method operates on a specific instance and can access both static and instance members. Wystąpienie, na którym wywołano metodę wystąpienia, można jawnie uzyskać do niego dostęp this .The instance on which an instance method was invoked can be explicitly accessed as this. Wystąpił błąd podczas odwoływania się do this w metodzie statycznej.It is an error to refer to this in a static method.

Następująca Entity Klasa zawiera elementy członkowskie statyczne i wystąpienia.The following Entity class has both static and instance members.

class Entity
{
    static int nextSerialNo;
    int serialNo;

    public Entity() {
        serialNo = nextSerialNo++;
    }

    public int GetSerialNo() {
        return serialNo;
    }

    public static int GetNextSerialNo() {
        return nextSerialNo;
    }

    public static void SetNextSerialNo(int value) {
        nextSerialNo = value;
    }
}

Każde Entity wystąpienie zawiera numer seryjny (i najprawdopodobniej inne informacje, które nie są wyświetlane w tym miejscu).Each Entity instance contains a serial number (and presumably some other information that is not shown here). EntityKonstruktor (który przypomina metodę wystąpienia) Inicjuje nowe wystąpienie przy użyciu następnego dostępnego numeru seryjnego.The Entity constructor (which is like an instance method) initializes the new instance with the next available serial number. Ponieważ Konstruktor jest członkiem wystąpienia, może uzyskać dostęp zarówno do serialNo pola wystąpienia, jak i nextSerialNo pola statycznego.Because the constructor is an instance member, it is permitted to access both the serialNo instance field and the nextSerialNo static field.

GetNextSerialNoMetody i SetNextSerialNo static mogą uzyskać dostęp do nextSerialNo pola statycznego, ale może to być błąd, aby uzyskać bezpośredni dostęp do serialNo pola wystąpienia.The GetNextSerialNo and SetNextSerialNo static methods can access the nextSerialNo static field, but it would be an error for them to directly access the serialNo instance field.

Poniższy przykład pokazuje użycie Entity klasy.The following example shows the use of the Entity class.

using System;

class Test
{
    static void Main() {
        Entity.SetNextSerialNo(1000);
        Entity e1 = new Entity();
        Entity e2 = new Entity();
        Console.WriteLine(e1.GetSerialNo());           // Outputs "1000"
        Console.WriteLine(e2.GetSerialNo());           // Outputs "1001"
        Console.WriteLine(Entity.GetNextSerialNo());   // Outputs "1002"
    }
}

Należy zauważyć, SetNextSerialNo że GetNextSerialNo metody i są wywoływane dla klasy, podczas gdy GetSerialNo metoda wystąpienia jest wywoływana w wystąpieniach klasy.Note that the SetNextSerialNo and GetNextSerialNo static methods are invoked on the class whereas the GetSerialNo instance method is invoked on instances of the class.

Metody wirtualne, przesłonięcia i abstrakcyjneVirtual, override, and abstract methods

Gdy deklaracja metody wystąpienia zawiera virtual modyfikator, metoda jest określana jako Metoda wirtualna* _.When an instance method declaration includes a virtual modifier, the method is said to be a *virtual method _. Gdy virtual modyfikator nie jest obecny, metoda jest określana jako _ niewirtualna Metoda *.When no virtual modifier is present, the method is said to be a _*non-virtual method**.

Gdy wywoływana jest metoda wirtualna, *Typ czasu wykonywania _ wystąpienia, dla którego odbywa się wywołanie określa rzeczywistą implementację metody do wywołania.When a virtual method is invoked, the *run-time type _ of the instance for which that invocation takes place determines the actual method implementation to invoke. W wywołaniu metody niewirtualnej wartość _ typu czasu kompilacji* wystąpienia jest czynnikiem decydującym.In a nonvirtual method invocation, the _ compile-time type* of the instance is the determining factor.

Metoda wirtualna może zostać przesłonięta w klasie pochodnej.A virtual method can be overridden in a derived class. Gdy deklaracja metody wystąpienia zawiera override modyfikator, metoda zastępuje dziedziczną metodę wirtualną z tą samą sygnaturą.When an instance method declaration includes an override modifier, the method overrides an inherited virtual method with the same signature. Podczas gdy deklaracja metody wirtualnej wprowadza nową metodę, Deklaracja metody przesłonięcia specjalizacji istniejącej dziedziczonej metody wirtualnej, dostarczając nową implementację tej metody.Whereas a virtual method declaration introduces a new method, an override method declaration specializes an existing inherited virtual method by providing a new implementation of that method.

Metoda abstrakcyjna jest metodą wirtualną bez implementacji.An abstract method is a virtual method with no implementation. Metoda abstrakcyjna jest zadeklarowana z abstract modyfikatorem i jest dozwolona tylko w klasie, która również jest zadeklarowana abstract .An abstract method is declared with the abstract modifier and is permitted only in a class that is also declared abstract. Metoda abstrakcyjna musi zostać przesłonięta w każdej nieabstrakcyjnej klasie pochodnej.An abstract method must be overridden in every non-abstract derived class.

Poniższy przykład deklaruje klasę abstrakcyjną, Expression która reprezentuje węzeł drzewa wyrażeń i trzy klasy pochodne, Constant , VariableReference i Operation , które implementują węzły drzewa wyrażeń dla stałych, odwołań do zmiennych i operacji arytmetycznych.The following example declares an abstract class, Expression, which represents an expression tree node, and three derived classes, Constant, VariableReference, and Operation, which implement expression tree nodes for constants, variable references, and arithmetic operations. (Jest to podobne do, ale nie należy mylić z typami drzewa wyrażenia wprowadzonymi w typach drzew wyrażeń).(This is similar to, but not to be confused with the expression tree types introduced in Expression tree types).

using System;
using System.Collections;

public abstract class Expression
{
    public abstract double Evaluate(Hashtable vars);
}

public class Constant: Expression
{
    double value;

    public Constant(double value) {
        this.value = value;
    }

    public override double Evaluate(Hashtable vars) {
        return value;
    }
}

public class VariableReference: Expression
{
    string name;

    public VariableReference(string name) {
        this.name = name;
    }

    public override double Evaluate(Hashtable vars) {
        object value = vars[name];
        if (value == null) {
            throw new Exception("Unknown variable: " + name);
        }
        return Convert.ToDouble(value);
    }
}

public class Operation: Expression
{
    Expression left;
    char op;
    Expression right;

    public Operation(Expression left, char op, Expression right) {
        this.left = left;
        this.op = op;
        this.right = right;
    }

    public override double Evaluate(Hashtable vars) {
        double x = left.Evaluate(vars);
        double y = right.Evaluate(vars);
        switch (op) {
            case '+': return x + y;
            case '-': return x - y;
            case '*': return x * y;
            case '/': return x / y;
        }
        throw new Exception("Unknown operator");
    }
}

Poprzednie cztery klasy mogą służyć do modelowania wyrażeń arytmetycznych.The previous four classes can be used to model arithmetic expressions. Na przykład przy użyciu wystąpień tych klas wyrażenie x + 3 może być reprezentowane w następujący sposób.For example, using instances of these classes, the expression x + 3 can be represented as follows.

Expression e = new Operation(
    new VariableReference("x"),
    '+',
    new Constant(3));

EvaluateMetoda Expression wystąpienia jest wywoływana w celu obliczenia danego wyrażenia i utworzenia double wartości.The Evaluate method of an Expression instance is invoked to evaluate the given expression and produce a double value. Metoda przyjmuje jako argument a Hashtable , który zawiera nazwy zmiennych (jako klucze wpisów) i wartości (jako wartości wpisów).The method takes as an argument a Hashtable that contains variable names (as keys of the entries) and values (as values of the entries). EvaluateMetoda jest wirtualną metodą abstrakcyjną, co oznacza, że nieabstrakcyjne klasy pochodne muszą zastąpić je, aby zapewnić rzeczywistą implementację.The Evaluate method is a virtual abstract method, meaning that non-abstract derived classes must override it to provide an actual implementation.

ConstantImplementacja Evaluate po prostu zwraca przechowywaną stałą.A Constant's implementation of Evaluate simply returns the stored constant. VariableReferenceImplementacja programu wyszukuje nazwę zmiennej w elemencie Hashtable i zwraca wartość wynikową.A VariableReference's implementation looks up the variable name in the hashtable and returns the resulting value. OperationImplementacja najpierw szacuje lewy i prawy operand (cyklicznie wywołując ich Evaluate metody), a następnie wykonuje daną operację arytmetyczną.An Operation's implementation first evaluates the left and right operands (by recursively invoking their Evaluate methods) and then performs the given arithmetic operation.

Poniższy program używa Expression klas do obliczenia wyrażenia x * (y + 2) pod kątem różnych wartości x i y .The following program uses the Expression classes to evaluate the expression x * (y + 2) for different values of x and y.

using System;
using System.Collections;

class Test
{
    static void Main() {
        Expression e = new Operation(
            new VariableReference("x"),
            '*',
            new Operation(
                new VariableReference("y"),
                '+',
                new Constant(2)
            )
        );
        Hashtable vars = new Hashtable();
        vars["x"] = 3;
        vars["y"] = 5;
        Console.WriteLine(e.Evaluate(vars));        // Outputs "21"
        vars["x"] = 1.5;
        vars["y"] = 9;
        Console.WriteLine(e.Evaluate(vars));        // Outputs "16.5"
    }
}

Przeciążanie metodyMethod overloading

Metoda *przeciążanie _ zezwala na wiele metod w tej samej klasie, które mają taką samą nazwę, o ile mają unikatowe podpisy.Method *overloading _ permits multiple methods in the same class to have the same name as long as they have unique signatures. Podczas kompilowania wywołania przeciążonej metody kompilator używa rozdzielczości przeciążeniowej _ * do określenia konkretnej metody do wywołania.When compiling an invocation of an overloaded method, the compiler uses _ overload resolution* to determine the specific method to invoke. Rozpoznanie przeciążenia umożliwia znalezienie jednej metody, która najlepiej pasuje do argumentów lub zgłasza błąd, jeśli nie można znaleźć pojedynczego najlepszego dopasowania.Overload resolution finds the one method that best matches the arguments or reports an error if no single best match can be found. W poniższym przykładzie przedstawiono sposób rozwiązywania przeciążenia.The following example shows overload resolution in effect. Komentarz dla każdego wywołania Main metody pokazuje, która metoda jest faktycznie wywoływana.The comment for each invocation in the Main method shows which method is actually invoked.

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

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

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

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

    static void F<T>(T x) {
        Console.WriteLine("F<T>(T)");
    }

    static void F(double x, double y) {
        Console.WriteLine("F(double, double)");
    }

    static void Main() {
        F();                 // Invokes F()
        F(1);                // Invokes F(int)
        F(1.0);              // Invokes F(double)
        F("abc");            // Invokes F(object)
        F((double)1);        // Invokes F(double)
        F((object)1);        // Invokes F(object)
        F<int>(1);           // Invokes F<T>(T)
        F(1, 1);             // Invokes F(double, double)
    }
}

Jak pokazano w przykładzie, dana metoda może być zawsze wybierana przez jawne rzutowanie argumentów na dokładne typy parametrów i/lub jawne dostarczenie argumentów typu.As shown by the example, a particular method can always be selected by explicitly casting the arguments to the exact parameter types and/or explicitly supplying type arguments.

Inne elementy członkowskie funkcjiOther function members

Elementy członkowskie, które zawierają kod wykonywalny, są określane zbiorczo jako elementy członkowskie klasy.Members that contain executable code are collectively known as the function members of a class. W poprzedniej sekcji opisano metody, które są podstawowym rodzajem elementów członkowskich funkcji.The preceding section describes methods, which are the primary kind of function members. W tej sekcji opisano inne rodzaje składowych funkcji obsługiwane przez język C#: konstruktory, właściwości, indeksatory, zdarzenia, operatory i destruktory.This section describes the other kinds of function members supported by C#: constructors, properties, indexers, events, operators, and destructors.

Poniższy kod przedstawia klasę generyczną o nazwie List<T> , która implementuje rozwijaną listę obiektów.The following code shows a generic class called List<T>, which implements a growable list of objects. Klasa zawiera kilka przykładów typowych rodzajów elementów członkowskich funkcji.The class contains several examples of the most common kinds of function members.

public class List<T> {
    // Constant...
    const int defaultCapacity = 4;

    // Fields...
    T[] items;
    int count;

    // Constructors...
    public List(int capacity = defaultCapacity) {
        items = new T[capacity];
    }

    // Properties...
    public int Count {
        get { return count; }
    }
    public int Capacity {
        get {
            return items.Length;
        }
        set {
            if (value < count) value = count;
            if (value != items.Length) {
                T[] newItems = new T[value];
                Array.Copy(items, 0, newItems, 0, count);
                items = newItems;
            }
        }
    }

    // Indexer...
    public T this[int index] {
        get {
            return items[index];
        }
        set {
            items[index] = value;
            OnChanged();
        }
    }

    // Methods...
    public void Add(T item) {
        if (count == Capacity) Capacity = count * 2;
        items[count] = item;
        count++;
        OnChanged();
    }
    protected virtual void OnChanged() {
        if (Changed != null) Changed(this, EventArgs.Empty);
    }
    public override bool Equals(object other) {
        return Equals(this, other as List<T>);
    }
    static bool Equals(List<T> a, List<T> b) {
        if (a == null) return b == null;
        if (b == null || a.count != b.count) return false;
        for (int i = 0; i < a.count; i++) {
            if (!object.Equals(a.items[i], b.items[i])) {
                return false;
            }
        }
        return true;
    }

    // Event...
    public event EventHandler Changed;

    // Operators...
    public static bool operator ==(List<T> a, List<T> b) {
        return Equals(a, b);
    }
    public static bool operator !=(List<T> a, List<T> b) {
        return !Equals(a, b);
    }
}

KonstruktoryConstructors

C# obsługuje zarówno wystąpienie, jak i konstruktory statyczne.C# supports both instance and static constructors. Konstruktor wystąpienia* _ jest członkiem, który implementuje akcje wymagane do zainicjowania wystąpienia klasy.An *instance constructor _ is a member that implements the actions required to initialize an instance of a class. _ Static konstruktora* jest członkiem, który implementuje akcje wymagane do zainicjowania samej klasy podczas pierwszego ładowania.A _ static constructor* is a member that implements the actions required to initialize a class itself when it is first loaded.

Konstruktor jest zadeklarowany jak metoda bez zwracanego typu i o takiej samej nazwie jak zawierająca klasy.A constructor is declared like a method with no return type and the same name as the containing class. Jeśli deklaracja konstruktora zawiera static modyfikator, deklaruje Konstruktor statyczny.If a constructor declaration includes a static modifier, it declares a static constructor. W przeciwnym razie deklaruje Konstruktor wystąpienia.Otherwise, it declares an instance constructor.

Konstruktory wystąpień mogą być przeciążone.Instance constructors can be overloaded. Na przykład List<T> Klasa deklaruje dwa konstruktory wystąpień, jeden bez parametrów i jeden, który pobiera int parametr.For example, the List<T> class declares two instance constructors, one with no parameters and one that takes an int parameter. Konstruktory wystąpień są wywoływane przy użyciu new operatora.Instance constructors are invoked using the new operator. Poniższe instrukcje przydzielą dwa List<string> wystąpienia przy użyciu każdego konstruktora List klasy.The following statements allocate two List<string> instances using each of the constructors of the List class.

List<string> list1 = new List<string>();
List<string> list2 = new List<string>(10);

W przeciwieństwie do innych elementów członkowskich, konstruktory wystąpień nie są dziedziczone, a Klasa nie ma konstruktorów wystąpień innych niż zadeklarowane w klasie.Unlike other members, instance constructors are not inherited, and a class has no instance constructors other than those actually declared in the class. Jeśli nie podano konstruktora wystąpienia dla klasy, zostanie automatycznie podana pusta wartość bez parametrów.If no instance constructor is supplied for a class, then an empty one with no parameters is automatically provided.

WłaściwościProperties

*Właściwości _ są naturalnym rozszerzeniem pól.*Properties _ are a natural extension of fields. Oba są nazwanymi członkami ze skojarzonymi typami, a składnia dostępu do pól i właściwości jest taka sama.Both are named members with associated types, and the syntax for accessing fields and properties is the same. Jednak w przeciwieństwie do pól właściwości nie oznacza lokalizacji magazynu.However, unlike fields, properties do not denote storage locations. Zamiast tego właściwości mają _ metody *dostępu**, które określają instrukcje do wykonania, gdy ich wartości są odczytywane lub zapisywane.Instead, properties have _ accessors* that specify the statements to be executed when their values are read or written.

Właściwość jest zadeklarowana jako pole, z tą różnicą, że deklaracja kończy się get akcesorem i/lub set akcesorem zapisanym między ogranicznikami { i } zamiast kończyć się średnikiem.A property is declared like a field, except that the declaration ends with a get accessor and/or a set accessor written between the delimiters { and } instead of ending in a semicolon. Właściwość, która ma zarówno get akcesor, jak i set akcesora, to właściwość, do odczytu i zapisu , właściwość, która ma tylko get metodę dostępu, jest właściwością tylko do odczytu, a właściwość, która ma tylko set metodę dostępu, ma _ Właściwość tylko do zapisu *.A property that has both a get accessor and a set accessor is a read-write property _, a property that has only a get accessor is a _read-only property*, and a property that has only a set accessor is a _*write-only property**.

getMetoda dostępu odpowiada metodzie bez parametrów z wartością zwracaną typu właściwości.A get accessor corresponds to a parameterless method with a return value of the property type. Poza elementem docelowym przypisania, gdy właściwość jest przywoływana w wyrażeniu, get metoda dostępu do właściwości jest wywoływana w celu obliczenia wartości właściwości.Except as the target of an assignment, when a property is referenced in an expression, the get accessor of the property is invoked to compute the value of the property.

setMetoda dostępu odpowiada metodzie z pojedynczym parametrem o nazwie value i bez zwracanego typu.A set accessor corresponds to a method with a single parameter named value and no return type. Gdy właściwość jest przywoływana jako element docelowy przypisania lub jako operand ++ lub -- , set metoda dostępu jest wywoływana z argumentem, który dostarcza nową wartość.When a property is referenced as the target of an assignment or as the operand of ++ or --, the set accessor is invoked with an argument that provides the new value.

List<T>Klasa deklaruje dwie właściwości Count i Capacity , które są tylko do odczytu i odczytu i zapisu.The List<T> class declares two properties, Count and Capacity, which are read-only and read-write, respectively. Poniżej przedstawiono przykład użycia tych właściwości.The following is an example of use of these properties.

List<string> names = new List<string>();
names.Capacity = 100;            // Invokes set accessor
int i = names.Count;             // Invokes get accessor
int j = names.Capacity;          // Invokes get accessor

Podobnie jak pola i metody, C# obsługuje zarówno właściwości wystąpienia, jak i właściwości statyczne.Similar to fields and methods, C# supports both instance properties and static properties. Właściwości statyczne są zadeklarowane za pomocą static modyfikatora, a właściwości wystąpienia są deklarowane bez użycia.Static properties are declared with the static modifier, and instance properties are declared without it.

Metody dostępu właściwości mogą być wirtualne.The accessor(s) of a property can be virtual. Gdy Deklaracja właściwości zawiera virtual abstract modyfikator, lub override , ma zastosowanie do akcesorów właściwości.When a property declaration includes a virtual, abstract, or override modifier, it applies to the accessor(s) of the property.

Indexers (Indeksatory)Indexers

Indeksator jest członkiem, który umożliwia indeksowanie obiektów w taki sam sposób jak w przypadku tablicy.An indexer is a member that enables objects to be indexed in the same way as an array. Indeksator jest zadeklarowany jak właściwość, z tą różnicą, że po nazwie składowej this następuje lista parametrów zapisywana między ogranicznikami [ i ] .An indexer is declared like a property except that the name of the member is this followed by a parameter list written between the delimiters [ and ]. Parametry są dostępne w metodach dostępu indeksatora.The parameters are available in the accessor(s) of the indexer. Podobnie jak w przypadku właściwości, indeksatory mogą być tylko do odczytu i zapisu, tylko do odczytu i do zapisu, a Akcesory dla indeksatora mogą być wirtualne.Similar to properties, indexers can be read-write, read-only, and write-only, and the accessor(s) of an indexer can be virtual.

ListKlasa deklaruje pojedynczy indeksator do odczytu i zapisu, który pobiera int parametr.The List class declares a single read-write indexer that takes an int parameter. Indeksator umożliwia indeksowanie List wystąpień z int wartościami.The indexer makes it possible to index List instances with int values. Na przykładFor example

List<string> names = new List<string>();
names.Add("Liz");
names.Add("Martha");
names.Add("Beth");
for (int i = 0; i < names.Count; i++) {
    string s = names[i];
    names[i] = s.ToUpper();
}

Indeksatory mogą być przeciążone, co oznacza, że Klasa może deklarować wiele indeksatorów, o ile liczba lub typy ich parametrów różnią się.Indexers can be overloaded, meaning that a class can declare multiple indexers as long as the number or types of their parameters differ.

ZdarzeniaEvents

Zdarzenie jest członkiem, który umożliwia klasy lub obiektowi dostarczanie powiadomień.An event is a member that enables a class or object to provide notifications. Zdarzenie jest zadeklarowane jak pole, z tą różnicą, że deklaracja zawiera event słowo kluczowe i typ musi być typem delegata.An event is declared like a field except that the declaration includes an event keyword and the type must be a delegate type.

W obrębie klasy, która deklaruje element członkowski zdarzenia, zdarzenie zachowuje się podobnie jak pole typu delegata (pod warunkiem, że zdarzenie nie jest abstrakcyjne i nie deklaruje metod dostępu).Within a class that declares an event member, the event behaves just like a field of a delegate type (provided the event is not abstract and does not declare accessors). W polu jest przechowywane odwołanie do delegata, który reprezentuje programy obsługi zdarzeń, które zostały dodane do zdarzenia.The field stores a reference to a delegate that represents the event handlers that have been added to the event. Jeśli nie ma żadnych dojść do zdarzeń, pole jest null .If no event handles are present, the field is null.

List<T>Klasa deklaruje pojedynczy element członkowski zdarzenia o nazwie Changed , który wskazuje, że dodano nowy element do listy.The List<T> class declares a single event member called Changed, which indicates that a new item has been added to the list. ChangedZdarzenie jest zgłaszane przez OnChanged metodę wirtualną, która najpierw sprawdza, czy zdarzenie jest null (oznacza, że nie ma żadnych programów obsługi).The Changed event is raised by the OnChanged virtual method, which first checks whether the event is null (meaning that no handlers are present). Pojęcie związane z wywoływaniem zdarzenia jest dokładnie równoważne do wywołania delegata reprezentowanego przez zdarzenie, co oznacza, że nie istnieją żadne specjalne konstrukcje języka do wywoływania zdarzeń.The notion of raising an event is precisely equivalent to invoking the delegate represented by the event—thus, there are no special language constructs for raising events.

Klienci reagują na zdarzenia za poorednictwem programów obsługi zdarzeń.Clients react to events through event handlers. Procedury obsługi zdarzeń są dołączane przy użyciu += operatora i usuwane przy użyciu -= operatora.Event handlers are attached using the += operator and removed using the -= operator. Poniższy przykład dołącza procedurę obsługi zdarzeń do Changed zdarzenia List<string> .The following example attaches an event handler to the Changed event of a List<string>.

using System;

class Test
{
    static int changeCount;

    static void ListChanged(object sender, EventArgs e) {
        changeCount++;
    }

    static void Main() {
        List<string> names = new List<string>();
        names.Changed += new EventHandler(ListChanged);
        names.Add("Liz");
        names.Add("Martha");
        names.Add("Beth");
        Console.WriteLine(changeCount);        // Outputs "3"
    }
}

W przypadku zaawansowanych scenariuszy, w których wymagana jest kontrola bazowego magazynu zdarzenia, deklaracja zdarzenia może jawnie dostarczyć i akcesorów add remove , które są nieco podobne do set metody dostępu do właściwości.For advanced scenarios where control of the underlying storage of an event is desired, an event declaration can explicitly provide add and remove accessors, which are somewhat similar to the set accessor of a property.

OperatoryOperators

Operator jest członkiem, który definiuje znaczenie zastosowania określonego operatora wyrażenia do wystąpienia klasy.An operator is a member that defines the meaning of applying a particular expression operator to instances of a class. Można zdefiniować trzy rodzaje operatorów: operatory jednoargumentowe, operatory binarne i operatory konwersji.Three kinds of operators can be defined: unary operators, binary operators, and conversion operators. Wszystkie operatory muszą być zadeklarowane jako public i static .All operators must be declared as public and static.

List<T>Klasa deklaruje dwa operatory operator== i i operator!= w ten sposób daje nowe znaczenie dla wyrażeń, które stosują te operatory do List wystąpień.The List<T> class declares two operators, operator== and operator!=, and thus gives new meaning to expressions that apply those operators to List instances. W tym celu operatory definiują równość dwóch List<T> wystąpień w porównaniu z poszczególnymi obiektami zawartymi przy użyciu Equals metod.Specifically, the operators define equality of two List<T> instances as comparing each of the contained objects using their Equals methods. Poniższy przykład używa == operatora do porównywania dwóch List<int> wystąpień.The following example uses the == operator to compare two List<int> instances.

using System;

class Test
{
    static void Main() {
        List<int> a = new List<int>();
        a.Add(1);
        a.Add(2);
        List<int> b = new List<int>();
        b.Add(1);
        b.Add(2);
        Console.WriteLine(a == b);        // Outputs "True"
        b.Add(3);
        Console.WriteLine(a == b);        // Outputs "False"
    }
}

Pierwsze dane Console.WriteLine wyjściowe, True ponieważ dwie listy zawierają tę samą liczbę obiektów z tymi samymi wartościami w tej samej kolejności.The first Console.WriteLine outputs True because the two lists contain the same number of objects with the same values in the same order. List<T>Nie zdefiniowano operator== , pierwsze Console.WriteLine miałoby wynik, False ponieważ a i odwołuje się do b różnych List<int> wystąpień.Had List<T> not defined operator==, the first Console.WriteLine would have output False because a and b reference different List<int> instances.

DestruktoryDestructors

Destruktor jest członkiem, który implementuje akcje wymagane do zadestruktorowania wystąpienia klasy.A destructor is a member that implements the actions required to destruct an instance of a class. Destruktory nie mogą mieć parametrów, nie mogą mieć modyfikatorów dostępności i nie mogą być wywoływane jawnie.Destructors cannot have parameters, they cannot have accessibility modifiers, and they cannot be invoked explicitly. Destruktor dla wystąpienia jest wywoływany automatycznie podczas wyrzucania elementów bezużytecznych.The destructor for an instance is invoked automatically during garbage collection.

Moduł wyrzucania elementów bezużytecznych jest dozwolony w przypadku podejmowania decyzji o zbieraniu obiektów i destruktorów uruchamiania.The garbage collector is allowed wide latitude in deciding when to collect objects and run destructors. W odróżnieniu od czasu wywołania destruktorów nie jest deterministyczna, a destruktory mogą być wykonywane na dowolnym wątku.Specifically, the timing of destructor invocations is not deterministic, and destructors may be executed on any thread. Z tych i innych powodów klasy powinny implementować destruktory tylko wtedy, gdy żadne inne rozwiązania nie są możliwe.For these and other reasons, classes should implement destructors only when no other solutions are feasible.

usingInstrukcja zawiera lepsze podejście do niszczenia obiektów.The using statement provides a better approach to object destruction.

StrukturyStructs

Podobnie jak klasy, struktury są strukturami danych, które mogą zawierać składowe danych i składowe funkcji, ale w przeciwieństwie do klas, struktury są typami wartości i nie wymagają przydziału sterty.Like classes, structs are data structures that can contain data members and function members, but unlike classes, structs are value types and do not require heap allocation. Zmienna typu struktury bezpośrednio przechowuje dane struktury, podczas gdy zmienna typu klasy przechowuje odwołanie do obiektu przydzielanego dynamicznie.A variable of a struct type directly stores the data of the struct, whereas a variable of a class type stores a reference to a dynamically allocated object. Typy struktur nie obsługują dziedziczenia określonego przez użytkownika, a wszystkie typy struktur niejawnie dziedziczą po typie object .Struct types do not support user-specified inheritance, and all struct types implicitly inherit from type object.

Struktury są szczególnie przydatne w przypadku małych struktur danych, które mają semantykę wartości.Structs are particularly useful for small data structures that have value semantics. Liczby zespolone, punkty w układzie współrzędnych lub pary klucz-wartość w słowniku są wszystkimi dobrymi przykładami struktur.Complex numbers, points in a coordinate system, or key-value pairs in a dictionary are all good examples of structs. Użycie struktur zamiast klas dla małych struktur danych może spowodować znaczną różnicę liczby alokacji pamięci wykonywanej przez aplikację.The use of structs rather than classes for small data structures can make a large difference in the number of memory allocations an application performs. Na przykład następujący program tworzy i Inicjuje tablicę z 100 punktów.For example, the following program creates and initializes an array of 100 points. Z Point zaimplementowaną klasą, 101 oddzielnych obiektów są tworzone wystąpienia — jeden dla tablicy i jeden dla elementów 100.With Point implemented as a class, 101 separate objects are instantiated—one for the array and one each for the 100 elements.

class Point
{
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

class Test
{
    static void Main() {
        Point[] points = new Point[100];
        for (int i = 0; i < 100; i++) points[i] = new Point(i, i);
    }
}

Alternatywą jest tworzenie Point struktury.An alternative is to make Point a struct.

struct Point
{
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

Teraz zostanie utworzony tylko jeden obiekt — jeden dla tablicy — i Point wystąpienia są przechowywane w wierszu tablicy.Now, only one object is instantiated—the one for the array—and the Point instances are stored in-line in the array.

Konstruktory struktury są wywoływane z new operatorem, ale nie oznacza to, że pamięć jest przyznana.Struct constructors are invoked with the new operator, but that does not imply that memory is being allocated. Zamiast dynamicznie przydzielać obiektu i zwracać odwołanie do niego, Konstruktor struktury po prostu zwraca wartość struktury (zazwyczaj w tymczasowej lokalizacji na stosie), a następnie ta wartość jest kopiowana w razie potrzeby.Instead of dynamically allocating an object and returning a reference to it, a struct constructor simply returns the struct value itself (typically in a temporary location on the stack), and this value is then copied as necessary.

Klasy, istnieje możliwość, że dwie zmienne odwołują się do tego samego obiektu, a tym samym możliwe dla operacji na jednej zmiennej, aby wpływać na obiekt, do którego odwołuje się inna zmienna.With classes, it is possible for two variables to reference the same object and thus possible for operations on one variable to affect the object referenced by the other variable. W przypadku struktur zmienne każda z nich ma własną kopię danych i nie jest możliwe wykonywanie operacji na nich, aby wpływać na inne.With structs, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other. Na przykład dane wyjściowe generowane przez Poniższy fragment kodu zależą od tego, czy Point jest klasą czy strukturą.For example, the output produced by the following code fragment depends on whether Point is a class or a struct.

Point a = new Point(10, 10);
Point b = a;
a.x = 20;
Console.WriteLine(b.x);

Jeśli Point jest klasą, dane wyjściowe są 20 spowodowane a tym b samym obiektem.If Point is a class, the output is 20 because a and b reference the same object. Jeśli Point jest strukturą, dane wyjściowe wynikają z 10 faktu, że przypisanie a do b tworzy kopię wartości i ta kopia nie ma wpływ na kolejne przypisanie do a.x .If Point is a struct, the output is 10 because the assignment of a to b creates a copy of the value, and this copy is unaffected by the subsequent assignment to a.x.

Poprzedni przykład wyróżnia dwa ograniczenia struktur.The previous example highlights two of the limitations of structs. Najpierw kopiowanie całej struktury jest zwykle mniej wydajne niż kopiowanie odwołania do obiektu, dlatego przypisanie i wartość przekazywanie parametrów mogą być bardziej kosztowne z strukturami niż w przypadku typów referencyjnych.First, copying an entire struct is typically less efficient than copying an object reference, so assignment and value parameter passing can be more expensive with structs than with reference types. Po drugie, z ref wyjątkiem out parametrów i, nie jest możliwe tworzenie odwołań do struktur, które wywołują zasady ich użycia w wielu sytuacjach.Second, except for ref and out parameters, it is not possible to create references to structs, which rules out their usage in a number of situations.

TabliceArrays

*Array _ to struktura danych zawierająca wiele zmiennych, do których uzyskuje się dostęp za pomocą indeksów obliczanych.An *array _ is a data structure that contains a number of variables that are accessed through computed indices. Zmienne zawarte w tablicy, nazywane również elementami tablicy, są wszystkie tego samego typu, a ten typ jest nazywany typem elementu _ tablicy.The variables contained in an array, also called the elements of the array, are all of the same type, and this type is called the _ element type* of the array.

Typy tablic są typami odwołań, a deklaracja zmiennej tablicowej po prostu ustawia miejsce na odwołanie do wystąpienia tablicy.Array types are reference types, and the declaration of an array variable simply sets aside space for a reference to an array instance. Rzeczywiste wystąpienia tablicy są tworzone dynamicznie w czasie wykonywania przy użyciu new operatora.Actual array instances are created dynamically at run-time using the new operator. newOperacja określa Długość nowego wystąpienia tablicy, które jest następnie naprawione dla okresu istnienia wystąpienia.The new operation specifies the length of the new array instance, which is then fixed for the lifetime of the instance. Indeksy elementów z zakresu tablicy od 0 do Length - 1 .The indices of the elements of an array range from 0 to Length - 1. newOperator automatycznie inicjuje elementy tablicy do ich wartości domyślnych, które na przykład są równe zero dla wszystkich typów liczbowych i null dla wszystkich typów odwołań.The new operator automatically initializes the elements of an array to their default value, which, for example, is zero for all numeric types and null for all reference types.

Poniższy przykład tworzy tablicę int elementów, Inicjuje tablicę i drukuje zawartość tablicy.The following example creates an array of int elements, initializes the array, and prints out the contents of the array.

using System;

class Test
{
    static void Main() {
        int[] a = new int[10];
        for (int i = 0; i < a.Length; i++) {
            a[i] = i * i;
        }
        for (int i = 0; i < a.Length; i++) {
            Console.WriteLine("a[{0}] = {1}", i, a[i]);
        }
    }
}

Ten przykład tworzy i działa na *jednowymiarowej tablicy _.This example creates and operates on a *single-dimensional array _. Język C# obsługuje również tablice wielowymiarowe.C# also supports multi-dimensional arrays. Liczba wymiarów typu tablicy, nazywana również _ rangą* typu tablicy, jest taka i liczbą przecinków, które są zapisywane między nawiasami kwadratowymi typu tablicy.The number of dimensions of an array type, also known as the _ rank* of the array type, is one plus the number of commas written between the square brackets of the array type. Poniższy przykład przydziela jednowymiarową, dwuwymiarową i trójwymiarową tablicę.The following example allocates a one-dimensional, a two-dimensional, and a three-dimensional array.

int[] a1 = new int[10];
int[,] a2 = new int[10, 5];
int[,,] a3 = new int[10, 5, 2];

a1Tablica zawiera 10 elementów, a2 tablica zawiera 50 (10 × 5) elementów, a a3 Tablica zawiera 100 (10 × 5 x 2) elementów.The a1 array contains 10 elements, the a2 array contains 50 (10 × 5) elements, and the a3 array contains 100 (10 × 5 × 2) elements.

Typ elementu tablicy może być dowolnego typu, łącznie z typem tablicy.The element type of an array can be any type, including an array type. Tablica z elementami typu tablicy jest czasami nazywana tablicą nieregularną , ponieważ długości tablic elementów nie wszystkie muszą być takie same.An array with elements of an array type is sometimes called a jagged array because the lengths of the element arrays do not all have to be the same. Poniższy przykład alokuje tablicę tablic int :The following example allocates an array of arrays of int:

int[][] a = new int[3][];
a[0] = new int[10];
a[1] = new int[5];
a[2] = new int[20];

Pierwszy wiersz tworzy tablicę z trzema elementami, każdy typ int[] i każdy z początkową wartością null .The first line creates an array with three elements, each of type int[] and each with an initial value of null. Kolejne wiersze inicjują następnie trzy elementy z odwołaniami do poszczególnych wystąpień tablicy o różnej długości.The subsequent lines then initialize the three elements with references to individual array instances of varying lengths.

newOperator zezwala na określenie wartości początkowych elementów tablicy przy użyciu inicjatora tablicy, który jest listą wyrażeń pisanych ogranicznikami { i } .The new operator permits the initial values of the array elements to be specified using an array initializer, which is a list of expressions written between the delimiters { and }. Poniższy przykład przydziela i inicjuje int[] z trzema elementami.The following example allocates and initializes an int[] with three elements.

int[] a = new int[] {1, 2, 3};

Należy zauważyć, że długość tablicy jest wywnioskowana na podstawie liczby wyrażeń między { i } .Note that the length of the array is inferred from the number of expressions between { and }. Deklaracje zmiennej lokalnej i pola mogą być skrócone w taki sposób, aby nie trzeba było przestawiać tego typu tablicy.Local variable and field declarations can be shortened further such that the array type does not have to be restated.

int[] a = {1, 2, 3};

Oba poprzednie przykłady są równoważne z następującymi:Both of the previous examples are equivalent to the following:

int[] t = new int[3];
t[0] = 1;
t[1] = 2;
t[2] = 3;
int[] a = t;

InterfejsyInterfaces

Interfejs definiuje kontrakt, który może być zaimplementowany przez klasy i struktury.An interface defines a contract that can be implemented by classes and structs. Interfejs może zawierać metody, właściwości, zdarzenia i indeksatory.An interface can contain methods, properties, events, and indexers. Interfejs nie dostarcza implementacji elementów członkowskich, które definiuje — tylko określa elementy członkowskie, które muszą być dostarczone przez klasy lub struktury, które implementują interfejs.An interface does not provide implementations of the members it defines—it merely specifies the members that must be supplied by classes or structs that implement the interface.

Interfejsy mogą wykorzystywać wielokrotne dziedziczenie.Interfaces may employ multiple inheritance. W poniższym przykładzie interfejs IComboBox dziedziczy z obu ITextBox i IListBox .In the following example, the interface IComboBox inherits from both ITextBox and IListBox.

interface IControl
{
    void Paint();
}

interface ITextBox: IControl
{
    void SetText(string text);
}

interface IListBox: IControl
{
    void SetItems(string[] items);
}

interface IComboBox: ITextBox, IListBox {}

Klasy i struktury mogą implementować wiele interfejsów.Classes and structs can implement multiple interfaces. W poniższym przykładzie Klasa EditBox implementuje zarówno IControl , jak i IDataBound .In the following example, the class EditBox implements both IControl and IDataBound.

interface IDataBound
{
    void Bind(Binder b);
}

public class EditBox: IControl, IDataBound
{
    public void Paint() {...}
    public void Bind(Binder b) {...}
}

Gdy Klasa lub struktura implementuje określony interfejs, wystąpienia tej klasy lub struktury mogą być niejawnie konwertowane na typ tego interfejsu.When a class or struct implements a particular interface, instances of that class or struct can be implicitly converted to that interface type. Na przykładFor example

EditBox editBox = new EditBox();
IControl control = editBox;
IDataBound dataBound = editBox;

W przypadkach, gdy wystąpienie nie jest statycznie znane do implementacji określonego interfejsu, można użyć rzutowania typu dynamicznego.In cases where an instance is not statically known to implement a particular interface, dynamic type casts can be used. Na przykład następujące instrukcje używają rzutowania typu dynamicznego do uzyskiwania IControl implementacji obiektu i IDataBound interfejsu.For example, the following statements use dynamic type casts to obtain an object's IControl and IDataBound interface implementations. Ponieważ rzeczywisty typ obiektu to EditBox , Rzutowanie powiedzie się.Because the actual type of the object is EditBox, the casts succeed.

object obj = new EditBox();
IControl control = (IControl)obj;
IDataBound dataBound = (IDataBound)obj;

W poprzedniej EditBox klasie Paint Metoda z IControl interfejsu i Bind Metoda z IDataBound interfejsu są implementowane za pomocą public elementów członkowskich.In the previous EditBox class, the Paint method from the IControl interface and the Bind method from the IDataBound interface are implemented using public members. C# obsługuje również jawne implementacje elementu członkowskiego interfejsu, za pomocą którego Klasa lub struktura może uniknąć tworzenia elementów członkowskich public .C# also supports explicit interface member implementations, using which the class or struct can avoid making the members public. Implementacja jawnego elementu członkowskiego interfejsu jest zapisywana przy użyciu w pełni kwalifikowanej nazwy elementu członkowskiego interfejsu.An explicit interface member implementation is written using the fully qualified interface member name. Na przykład EditBox Klasa może zaimplementować IControl.Paint IDataBound.Bind metody i przy użyciu jawnych implementacji elementu członkowskiego interfejsu w następujący sposób.For example, the EditBox class could implement the IControl.Paint and IDataBound.Bind methods using explicit interface member implementations as follows.

public class EditBox: IControl, IDataBound
{
    void IControl.Paint() {...}
    void IDataBound.Bind(Binder b) {...}
}

Dostęp do jawnych elementów członkowskich interfejsu można uzyskać tylko za pośrednictwem typu interfejsu.Explicit interface members can only be accessed via the interface type. Na przykład implementacja IControl.Paint dostarczonych przez poprzednią EditBox klasę może być wywoływana tylko przez pierwsze przekonwertowanie EditBox odwołania do IControl typu interfejsu.For example, the implementation of IControl.Paint provided by the previous EditBox class can only be invoked by first converting the EditBox reference to the IControl interface type.

EditBox editBox = new EditBox();
editBox.Paint();                        // Error, no such method
IControl control = editBox;
control.Paint();                        // Ok

WyliczeniaEnums

Typ wyliczeniowy jest odrębnym typem wartości z zestawem nazwanych stałych.An enum type is a distinct value type with a set of named constants. Poniższy przykład deklaruje i używa typu wyliczeniowego o nazwie Color z trzema stałymi wartościami, Red , Green i Blue .The following example declares and uses an enum type named Color with three constant values, Red, Green, and Blue.

using System;

enum Color
{
    Red,
    Green,
    Blue
}

class Test
{
    static void PrintColor(Color color) {
        switch (color) {
            case Color.Red:
                Console.WriteLine("Red");
                break;
            case Color.Green:
                Console.WriteLine("Green");
                break;
            case Color.Blue:
                Console.WriteLine("Blue");
                break;
            default:
                Console.WriteLine("Unknown color");
                break;
        }
    }

    static void Main() {
        Color c = Color.Red;
        PrintColor(c);
        PrintColor(Color.Blue);
    }
}

Każdy typ wyliczeniowy ma odpowiedni typ całkowity nazywany typem podstawowym typu wyliczeniowego.Each enum type has a corresponding integral type called the underlying type of the enum type. Typ wyliczeniowy, który nie deklaruje jawnie typu podstawowego, ma typ podstawowy int .An enum type that does not explicitly declare an underlying type has an underlying type of int. Format magazynu typu wyliczeniowego i zakres możliwych wartości są określane przez jego typ podstawowy.An enum type's storage format and range of possible values are determined by its underlying type. Zbiór wartości, dla których można zastosować typ wyliczeniowy, nie jest ograniczony przez elementy członkowskie wyliczenia.The set of values that an enum type can take on is not limited by its enum members. W szczególności każda wartość typu podstawowego wyliczenia może być rzutowana na typ wyliczeniowy i jest unikatową prawidłową wartością tego typu wyliczeniowego.In particular, any value of the underlying type of an enum can be cast to the enum type and is a distinct valid value of that enum type.

Poniższy przykład deklaruje typ wyliczeniowy o nazwie Alignment z typem podstawowym sbyte .The following example declares an enum type named Alignment with an underlying type of sbyte.

enum Alignment: sbyte
{
    Left = -1,
    Center = 0,
    Right = 1
}

Jak pokazano w poprzednim przykładzie, Deklaracja elementu członkowskiego wyliczenia może zawierać wyrażenie stałe, które określa wartość elementu członkowskiego.As shown by the previous example, an enum member declaration can include a constant expression that specifies the value of the member. Wartość stała dla każdego elementu członkowskiego wyliczenia musi znajdować się w zakresie bazowego typu wyliczenia.The constant value for each enum member must be in the range of the underlying type of the enum. Jeśli deklaracja elementu członkowskiego wyliczenia nie określa jawnie wartości, element członkowski otrzymuje wartość zero (jeśli jest to pierwszy element członkowski typu enum) lub wartość w postaci jednokrotnie poprzedzającej składową wyliczenia plus jeden.When an enum member declaration does not explicitly specify a value, the member is given the value zero (if it is the first member in the enum type) or the value of the textually preceding enum member plus one.

Wartości wyliczeniowe mogą być konwertowane na wartości całkowite i odwrotnie przy użyciu rzutowania typu.Enum values can be converted to integral values and vice versa using type casts. Na przykładFor example

int i = (int)Color.Blue;        // int i = 2;
Color c = (Color)2;             // Color c = Color.Blue;

Wartość domyślna dowolnego typu wyliczeniowego jest wartością całkowitą zero przekonwertowaną na typ wyliczeniowy.The default value of any enum type is the integral value zero converted to the enum type. W przypadkach, gdy zmienne są automatycznie inicjowane do wartości domyślnej, jest to wartość nadana zmiennym typów wyliczeniowych.In cases where variables are automatically initialized to a default value, this is the value given to variables of enum types. Aby wartość domyślna typu wyliczeniowego była łatwo dostępna, literał 0 niejawnie konwertowany na dowolny typ wyliczeniowy.In order for the default value of an enum type to be easily available, the literal 0 implicitly converts to any enum type. W ten sposób można używać następujących sposobów.Thus, the following is permitted.

Color c = 0;

DelegaciDelegates

Typ delegata reprezentuje odwołania do metod z określoną listą parametrów i zwracanym typem.A delegate type represents references to methods with a particular parameter list and return type. Delegaty umożliwiają traktowanie metod jako jednostek, które mogą być przypisane do zmiennych i przekazane jako parametry.Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Delegaty są podobne do koncepcji wskaźników funkcji, które znajdują się w innych językach, ale w przeciwieństwie do wskaźników funkcji Delegaty są zorientowane obiektowo i są bezpieczne dla typów.Delegates are similar to the concept of function pointers found in some other languages, but unlike function pointers, delegates are object-oriented and type-safe.

Poniższy przykład deklaruje i używa typu delegata o nazwie Function .The following example declares and uses a delegate type named Function.

using System;

delegate double Function(double x);

class Multiplier
{
    double factor;

    public Multiplier(double factor) {
        this.factor = factor;
    }

    public double Multiply(double x) {
        return x * factor;
    }
}

class Test
{
    static double Square(double x) {
        return x * x;
    }

    static double[] Apply(double[] a, Function f) {
        double[] result = new double[a.Length];
        for (int i = 0; i < a.Length; i++) result[i] = f(a[i]);
        return result;
    }

    static void Main() {
        double[] a = {0.0, 0.5, 1.0};
        double[] squares = Apply(a, Square);
        double[] sines = Apply(a, Math.Sin);
        Multiplier m = new Multiplier(2.0);
        double[] doubles =  Apply(a, m.Multiply);
    }
}

Wystąpienie Function typu delegata może odwoływać się do dowolnej metody, która przyjmuje double argument i zwraca double wartość.An instance of the Function delegate type can reference any method that takes a double argument and returns a double value. ApplyMetoda odnosi się Function do elementów a double[] , zwracając double[] wynik.The Apply method applies a given Function to the elements of a double[], returning a double[] with the results. MainMetoda Apply jest używana do zastosowania trzech różnych funkcji do double[] .In the Main method, Apply is used to apply three different functions to a double[].

Delegat może odwoływać się do metody statycznej (takiej jak Square lub Math.Sin w poprzednim przykładzie) lub metody wystąpienia (na przykład m.Multiply w poprzednim przykładzie).A delegate can reference either a static method (such as Square or Math.Sin in the previous example) or an instance method (such as m.Multiply in the previous example). Delegat, który odwołuje się do metody wystąpienia, odwołuje się również do określonego obiektu i gdy metoda wystąpienia jest wywoływana za pomocą delegata, ten obiekt zostaje this w wywołaniu.A delegate that references an instance method also references a particular object, and when the instance method is invoked through the delegate, that object becomes this in the invocation.

Delegatów można także tworzyć za pomocą funkcji anonimowych, które są "metodami wbudowanymi", które są tworzone na bieżąco.Delegates can also be created using anonymous functions, which are "inline methods" that are created on the fly. Funkcje anonimowe mogą zobaczyć zmienne lokalne otaczających metod.Anonymous functions can see the local variables of the surrounding methods. W ten sposób przykład mnożnika można napisać łatwiej, bez użycia Multiplier klasy:Thus, the multiplier example above can be written more easily without using a Multiplier class:

double[] doubles =  Apply(a, (double x) => x * 2.0);

Interesująca i przydatna właściwość delegata polega na tym, że nie wie ani nie posługuje się klasą metody, do której się odwołuje; wszystkie te kwestie polegają na tym, że metoda przywoływana ma te same parametry i zwracany typ jako delegat.An interesting and useful property of a delegate is that it does not know or care about the class of the method it references; all that matters is that the referenced method has the same parameters and return type as the delegate.

AtrybutyAttributes

Typy, elementy członkowskie i inne jednostki w programie C# obsługują Modyfikatory kontrolujące pewne aspekty ich zachowania.Types, members, and other entities in a C# program support modifiers that control certain aspects of their behavior. Na przykład dostępność metody jest kontrolowana za pomocą public protected internal modyfikatorów,, i private .For example, the accessibility of a method is controlled using the public, protected, internal, and private modifiers. Język C# służy do uogólniania tej funkcji w taki sposób, że typy informacji deklaratywnych zdefiniowanych przez użytkownika mogą być dołączane do jednostek programu i pobierane w czasie wykonywania.C# generalizes this capability such that user-defined types of declarative information can be attached to program entities and retrieved at run-time. Programy określają te dodatkowe informacje deklaracyjne przez definiowanie i używanie atrybutów.Programs specify this additional declarative information by defining and using attributes.

Poniższy przykład deklaruje HelpAttribute atrybut, który może być umieszczony w jednostkach programu, aby udostępnić linki do powiązanej dokumentacji.The following example declares a HelpAttribute attribute that can be placed on program entities to provide links to their associated documentation.

using System;

public class HelpAttribute: Attribute
{
    string url;
    string topic;

    public HelpAttribute(string url) {
        this.url = url;
    }

    public string Url {
        get { return url; }
    }

    public string Topic {
        get { return topic; }
        set { topic = value; }
    }
}

Wszystkie klasy atrybutów pochodzą z System.Attribute klasy bazowej dostarczonej przez .NET Framework.All attribute classes derive from the System.Attribute base class provided by the .NET Framework. Atrybuty mogą być stosowane, dając ich nazwę, wraz z dowolnymi argumentami, wewnątrz nawiasów kwadratowych tuż przed skojarzoną deklaracją.Attributes can be applied by giving their name, along with any arguments, inside square brackets just before the associated declaration. Jeśli nazwa atrybutu Attribute zostanie zakończona, ta część nazwy może zostać pominięta, gdy występuje odwołanie do atrybutu.If an attribute's name ends in Attribute, that part of the name can be omitted when the attribute is referenced. Na przykład HelpAttribute atrybut może być używany w następujący sposób.For example, the HelpAttribute attribute can be used as follows.

[Help("http://msdn.microsoft.com/.../MyClass.htm")]
public class Widget
{
    [Help("http://msdn.microsoft.com/.../MyClass.htm", Topic = "Display")]
    public void Display(string text) {}
}

Ten przykład dołącza HelpAttribute do Widget klasy i drugi HelpAttribute do Display metody w klasie.This example attaches a HelpAttribute to the Widget class and another HelpAttribute to the Display method in the class. Publiczne konstruktory klasy atrybutów kontrolują informacje, które muszą być dostarczone, gdy atrybut jest dołączony do jednostki programu.The public constructors of an attribute class control the information that must be provided when the attribute is attached to a program entity. Dodatkowe informacje można uzyskać, odwołując się do właściwości publicznego odczytu i zapisu klasy atrybutów (takich jak odwołanie do Topic Właściwości wcześniej).Additional information can be provided by referencing public read-write properties of the attribute class (such as the reference to the Topic property previously).

Poniższy przykład pokazuje, jak informacje o atrybutach danej jednostki programu mogą być pobierane w czasie wykonywania przy użyciu odbicia.The following example shows how attribute information for a given program entity can be retrieved at run-time using reflection.

using System;
using System.Reflection;

class Test
{
    static void ShowHelp(MemberInfo member) {
        HelpAttribute a = Attribute.GetCustomAttribute(member,
            typeof(HelpAttribute)) as HelpAttribute;
        if (a == null) {
            Console.WriteLine("No help for {0}", member);
        }
        else {
            Console.WriteLine("Help for {0}:", member);
            Console.WriteLine("  Url={0}, Topic={1}", a.Url, a.Topic);
        }
    }

    static void Main() {
        ShowHelp(typeof(Widget));
        ShowHelp(typeof(Widget).GetMethod("Display"));
    }
}

Gdy określony atrybut jest żądany przez odbicie, Konstruktor klasy atrybutu jest wywoływany z informacjami podanymi w źródle programu i zwracane jest wystąpienie atrybutu wynikowego.When a particular attribute is requested through reflection, the constructor for the attribute class is invoked with the information provided in the program source, and the resulting attribute instance is returned. Jeśli dodatkowe informacje zostały przekazane za pomocą właściwości, te właściwości są ustawiane na podane wartości przed zwróceniem wystąpienia atrybutu.If additional information was provided through properties, those properties are set to the given values before the attribute instance is returned.