StrukturenStructs
Strukturen ähneln Klassen darin, dass Sie Datenstrukturen darstellen, die Datenmember und Funktionsmember enthalten können.Structs are similar to classes in that they represent data structures that can contain data members and function members. Im Unterschied zu Klassen sind Strukturen jedoch Werttypen und erfordern keine Heap Zuordnung.However, unlike classes, structs are value types and do not require heap allocation. Eine Variable eines Struktur Typs enthält direkt die Daten der Struktur, während eine Variable eines Klassen Typs einen Verweis auf die Daten enthält, wobei es sich um ein Objekt handelt, das als Objekt bezeichnet wird.A variable of a struct type directly contains the data of the struct, whereas a variable of a class type contains a reference to the data, the latter known as an object.
Strukturen sind besonders nützlich für kleine Datenstrukturen, die über Wertsemantik verfügen.Structs are particularly useful for small data structures that have value semantics. Komplexe Zahlen, Punkte in einem Koordinatensystem oder Schlüssel-Wert-Paare im Wörterbuch sind gute Beispiele für Strukturen.Complex numbers, points in a coordinate system, or key-value pairs in a dictionary are all good examples of structs. Der Schlüssel für diese Datenstrukturen besteht darin, dass Sie nur wenige Datenmember haben, dass Sie keine Vererbung oder referenzielle Identität benötigen, und dass Sie mithilfe der Wert Semantik, bei der die Zuweisung den Wert anstelle des Verweises kopiert, bequem implementiert werden können.Key to these data structures is that they have few data members, that they do not require use of inheritance or referential identity, and that they can be conveniently implemented using value semantics where assignment copies the value instead of the reference.
Wie in einfache Typenbeschrieben, sind die einfachen Typen, die von c# bereitgestellt werden, z int
. b double
., und bool
, tatsächlich alle Strukturtypen.As described in Simple types, the simple types provided by C#, such as int
, double
, and bool
, are in fact all struct types. Ebenso wie diese vordefinierten Typen Strukturen sind, ist es auch möglich, Strukturen und Operator Überladung zu verwenden, um neue "primitive" Typen in der Programmiersprache c# zu implementieren.Just as these predefined types are structs, it is also possible to use structs and operator overloading to implement new "primitive" types in the C# language. Am Ende dieses Kapitels (Struktur Beispiele) werden zwei Beispiele für solche Typen angegeben.Two examples of such types are given at the end of this chapter (Struct examples).
Struct declarations (Strukturdeklarationen)Struct declarations
Eine struct_declaration ist eine type_declaration (Typdeklarationen), die eine neue Struktur deklariert:A struct_declaration is a type_declaration (Type declarations) that declares a new struct:
struct_declaration
: attributes? struct_modifier* 'partial'? 'struct' identifier type_parameter_list?
struct_interfaces? type_parameter_constraints_clause* struct_body ';'?
;
Ein struct_declaration besteht aus einem optionalen Satz von Attributen (Attributen), gefolgt von einer optionalen Gruppe von struct_modifier s (Strukturmodifizierern), gefolgt von einem partial
optionalen-Modifizierer, gefolgt vom-Schlüsselwort struct
und einem Bezeichner , der die Struktur benennt, gefolgt von einer optionalen type_parameter_list Specification (Typparameter), gefolgt von einer optionalen struct_interfaces Spezifikation (partieller Modifizierer), gefolgt von einer optionalen type_parameter_constraints_clause s-Spezifikation (Typparameter Einschränkungen), gefolgt von einer struct_body (Struktur Text), optional gefolgt von einem SemikolonA struct_declaration consists of an optional set of attributes (Attributes), followed by an optional set of struct_modifier s (Struct modifiers), followed by an optional partial
modifier, followed by the keyword struct
and an identifier that names the struct, followed by an optional type_parameter_list specification (Type parameters), followed by an optional struct_interfaces specification (Partial modifier) ), followed by an optional type_parameter_constraints_clause s specification (Type parameter constraints), followed by a struct_body (Struct body), optionally followed by a semicolon.
StrukturmodifiziererStruct modifiers
Eine struct_declaration kann optional eine Sequenz von strukturmodifizierermodifizierer einschließen:A struct_declaration may optionally include a sequence of struct modifiers:
struct_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
| struct_modifier_unsafe
;
Es ist ein Kompilierzeitfehler, damit derselbe Modifizierer mehrmals in einer Struktur Deklaration angezeigt wird.It is a compile-time error for the same modifier to appear multiple times in a struct declaration.
Die Modifizierer einer Struktur Deklaration haben dieselbe Bedeutung wie die einer Klassen Deklaration (Klassen Deklarationen).The modifiers of a struct declaration have the same meaning as those of a class declaration (Class declarations).
Partieller ModifiziererPartial modifier
Der- partial
Modifizierer gibt an, dass dieser struct_declaration eine partielle Typdeklaration ist.The partial
modifier indicates that this struct_declaration is a partial type declaration. Mehrere partielle Struktur Deklarationen mit demselben Namen innerhalb eines einschließenden Namespace oder einer Typdeklaration kombinieren eine Struktur Deklaration, die den in partiellen Typenangegebenen Regeln folgt.Multiple partial struct declarations with the same name within an enclosing namespace or type declaration combine to form one struct declaration, following the rules specified in Partial types.
Struktur SchnittstellenStruct interfaces
Eine Struktur Deklaration kann eine struct_interfaces Spezifikation enthalten. in diesem Fall wird die Struktur so bezeichnet, dass die angegebenen Schnittstellentypen direkt implementiert werden.A struct declaration may include a struct_interfaces specification, in which case the struct is said to directly implement the given interface types.
struct_interfaces
: ':' interface_type_list
;
Schnittstellen Implementierungen werden in Schnittstellen Implementierungenausführlicher erläutert.Interface implementations are discussed further in Interface implementations.
Struktur TextStruct body
Der struct_body einer Struktur definiert die Member der Struktur.The struct_body of a struct defines the members of the struct.
struct_body
: '{' struct_member_declaration* '}'
;
Struct members (Strukturmember)Struct members
Die Member einer Struktur bestehen aus den Membern, die von den struct_member_declaration en eingeführt wurden, und den Membern, die vom-Typ geerbt wurden System.ValueType
.The members of a struct consist of the members introduced by its struct_member_declaration s and the members inherited from the type System.ValueType
.
struct_member_declaration
: constant_declaration
| field_declaration
| method_declaration
| property_declaration
| event_declaration
| indexer_declaration
| operator_declaration
| constructor_declaration
| static_constructor_declaration
| type_declaration
| struct_member_declaration_unsafe
;
Mit Ausnahme der Unterschiede in den Klassen-und Struktur unterschiedengelten die Beschreibungen von Klassenmembern, die in Klassenmembern durch Async-Funktionen bereitgestellt werden, auch für Strukturmember.Except for the differences noted in Class and struct differences, the descriptions of class members provided in Class members through Async functions apply to struct members as well.
Class and struct differences (Klassen- und Strukturdifferenzen)Class and struct differences
Strukturen unterscheiden sich in mehreren wichtigen Punkten von Klassen:Structs differ from classes in several important ways:
- Strukturen sind Werttypen (Wert Semantik).Structs are value types (Value semantics).
- Alle Strukturtypen erben implizit von der-Klasse
System.ValueType
(Vererbung).All struct types implicitly inherit from the classSystem.ValueType
(Inheritance). - Durch die Zuweisung zu einer Variablen eines Struktur Typs wird eine Kopie des zugewiesenen Werts (Zuweisung) erstellt.Assignment to a variable of a struct type creates a copy of the value being assigned (Assignment).
- Der Standardwert einer Struktur ist der Wert, der erzeugt wird, indem alle Werttyp Felder auf ihren Standardwert und alle Verweistyp Felder auf
null
(Standardwerte) festgelegt werden.The default value of a struct is the value produced by setting all value type fields to their default value and all reference type fields tonull
(Default values). - Boxing-und Unboxing-Vorgänge werden verwendet, um zwischen einem Strukturtyp und
object
(Boxing und Unboxing) zu konvertieren.Boxing and unboxing operations are used to convert between a struct type andobject
(Boxing and unboxing). - Die Bedeutung von
this
unterscheidet sich für Strukturen (dieser Zugriff).The meaning ofthis
is different for structs (This access). - Instanzfelddeklarationen für eine Struktur dürfen keine Variableninitialisierer (Feldinitialisierer) enthalten.Instance field declarations for a struct are not permitted to include variable initializers (Field initializers).
- Eine Struktur darf keinen Parameter losen Instanzenkonstruktor (Konstruktoren) deklarieren.A struct is not permitted to declare a parameterless instance constructor (Constructors).
- Es ist nicht zulässig, einen destrukturtor (destrukturtoren) zu deklarieren.A struct is not permitted to declare a destructor (Destructors).
Wert SemantikValue semantics
Strukturen sind Werttypen (Werttypen) und werden als Wert Semantik bezeichnet.Structs are value types (Value types) and are said to have value semantics. Klassen hingegen sind Verweis Typen (Verweis Typen) und werden als Verweis Semantik bezeichnet.Classes, on the other hand, are reference types (Reference types) and are said to have reference semantics.
Eine Variable eines Struktur Typs enthält direkt die Daten der Struktur, während eine Variable eines Klassen Typs einen Verweis auf die Daten enthält, wobei es sich um ein Objekt handelt, das als Objekt bezeichnet wird.A variable of a struct type directly contains the data of the struct, whereas a variable of a class type contains a reference to the data, the latter known as an object. Wenn eine Struktur B
ein Instanzfeld vom Typ enthält A
und A
ein Strukturtyp ist, ist dies ein Kompilierzeitfehler für A
, von dem abhängig ist, B
oder ein von konstruierter Typ B
.When a struct B
contains an instance field of type A
and A
is a struct type, it is a compile-time error for A
to depend on B
or a type constructed from B
. Eine Struktur X
* hängt direkt von _ einer Struktur ab, Y
Wenn X
ein Instanzfeld vom Typ enthält Y
.A struct X
*directly depends on _ a struct Y
if X
contains an instance field of type Y
. Bei dieser Definition ist der gesamte Satz von Strukturen, von denen eine Struktur abhängt, das transitiv Schließen der _ direkt abhängig von * Relationship.Given this definition, the complete set of structs upon which a struct depends is the transitive closure of the _ directly depends on* relationship. Beispiel:For example
struct Node
{
int data;
Node next; // error, Node directly depends on itself
}
ist ein Fehler, da Node
ein Instanzfeld seines eigenen Typs enthält.is an error because Node
contains an instance field of its own type. Ein weiteres BeispielAnother example
struct A { B b; }
struct B { C c; }
struct C { A a; }
ist ein Fehler, da jeder der Typen A
, B
und voneinander C
abhängig ist.is an error because each of the types A
, B
, and C
depend on each other.
Mit-Klassen können zwei Variablen auf das gleiche Objekt verweisen, und so können Vorgänge in einer Variablen das Objekt beeinflussen, auf das von der anderen Variablen verwiesen wird.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. Bei Strukturen verfügen die Variablen jeweils über eine eigene Kopie der Daten (außer im Fall von ref
-und- out
Parameter Variablen), und es ist nicht möglich, dass sich Vorgänge auf einem anderen befinden.With structs, the variables each have their own copy of the data (except in the case of ref
and out
parameter variables), and it is not possible for operations on one to affect the other. Da Strukturen keine Verweis Typen sind, ist es außerdem nicht möglich, dass die Werte eines Struktur Typs sind null
.Furthermore, because structs are not reference types, it is not possible for values of a struct type to be null
.
Bei Angabe der DeklarationGiven the declaration
struct Point
{
public int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
das Code Fragmentthe code fragment
Point a = new Point(10, 10);
Point b = a;
a.x = 100;
System.Console.WriteLine(b.x);
Gibt den Wert aus 10
.outputs the value 10
. Die Zuweisung von a
zum Erstellen b
einer Kopie des Werts und ist folglich b
von der Zuweisung zu nicht betroffen a.x
.The assignment of a
to b
creates a copy of the value, and b
is thus unaffected by the assignment to a.x
. Hätte Point
stattdessen als Klasse deklariert werden, würde die Ausgabe lauten, 100
weil a
und auf b
dasselbe Objekt verweisen würden.Had Point
instead been declared as a class, the output would be 100
because a
and b
would reference the same object.
VererbungInheritance
Alle Strukturtypen erben implizit von der-Klasse System.ValueType
, die wiederum von der-Klasse erbt object
.All struct types implicitly inherit from the class System.ValueType
, which, in turn, inherits from class object
. Eine Struktur Deklaration kann eine Liste der implementierten Schnittstellen angeben, aber es ist nicht möglich, dass eine Struktur Deklaration eine Basisklasse angibt.A struct declaration may specify a list of implemented interfaces, but it is not possible for a struct declaration to specify a base class.
Strukturtypen sind niemals abstrakt und sind immer implizit versiegelt.Struct types are never abstract and are always implicitly sealed. Die abstract
sealed
Modifizierer und sind daher in einer Struktur Deklaration nicht zulässig.The abstract
and sealed
modifiers are therefore not permitted in a struct declaration.
Da die Vererbung für Strukturen nicht unterstützt wird, kann der deklarierte Zugriff auf einen Strukturmember nicht protected
oder sein protected internal
.Since inheritance isn't supported for structs, the declared accessibility of a struct member cannot be protected
or protected internal
.
Funktionsmember in einer Struktur können nicht abstract
oder sein virtual
, und der- override
Modifizierer darf nur Methoden überschreiben, die von geerbt wurden System.ValueType
.Function members in a struct cannot be abstract
or virtual
, and the override
modifier is allowed only to override methods inherited from System.ValueType
.
ZuweisungAssignment
Durch die Zuweisung zu einer Variablen eines Struktur Typs wird eine Kopie des zugewiesenen Werts erstellt.Assignment to a variable of a struct type creates a copy of the value being assigned. Dies unterscheidet sich von der Zuweisung zu einer Variablen eines Klassen Typs, die den Verweis, aber nicht das durch den Verweis identifizierte Objekt kopiert.This differs from assignment to a variable of a class type, which copies the reference but not the object identified by the reference.
Ähnlich wie bei einer Zuweisung wird eine Kopie der Struktur erstellt, wenn eine Struktur als Wert Parameter übergeben oder als Ergebnis eines Funktionsmembers zurückgegeben wird.Similar to an assignment, when a struct is passed as a value parameter or returned as the result of a function member, a copy of the struct is created. Eine Struktur kann mithilfe eines-oder-Parameters als Verweis an einen Funktionsmember übergeben werden ref
out
.A struct may be passed by reference to a function member using a ref
or out
parameter.
Wenn eine Eigenschaft oder ein Indexer einer Struktur das Ziel einer Zuweisung ist, muss der Instanzausdruck, der der Eigenschaft oder dem Indexer-Zugriff zugeordnet ist, als Variable klassifiziert werden.When a property or indexer of a struct is the target of an assignment, the instance expression associated with the property or indexer access must be classified as a variable. Wenn der Instanzausdruck als Wert klassifiziert wird, tritt ein Kompilierzeitfehler auf.If the instance expression is classified as a value, a compile-time error occurs. Dies wird in " einfache Zuweisung" ausführlicher beschrieben.This is described in further detail in Simple assignment.
StandardwerteDefault values
Wie in Standardwertebeschrieben, werden bei der Erstellung automatisch verschiedene Arten von Variablen auf ihren Standardwert initialisiert.As described in Default values, several kinds of variables are automatically initialized to their default value when they are created. Für Variablen von Klassentypen und anderen Verweis Typen ist dieser Standardwert null
.For variables of class types and other reference types, this default value is null
. Da Strukturen jedoch Werttypen sind, die nicht sein dürfen null
, ist der Standardwert einer Struktur der Wert, der erzeugt wird, indem alle Werttyp Felder auf ihren Standardwert und alle Verweistyp Felder auf festgelegt werden null
.However, since structs are value types that cannot be null
, the default value of a struct is the value produced by setting all value type fields to their default value and all reference type fields to null
.
Point
Im Beispiel wird auf die oben deklarierte Struktur verwiesen.Referring to the Point
struct declared above, the example
Point[] a = new Point[100];
Initialisiert jede Point
im-Array mit dem Wert, der erstellt wird, indem die x
Felder und auf NULL festgelegt werden y
.initializes each Point
in the array to the value produced by setting the x
and y
fields to zero.
Der Standardwert einer Struktur entspricht dem Wert, der vom Standardkonstruktor der Struktur zurückgegeben wird (Standardkonstruktoren).The default value of a struct corresponds to the value returned by the default constructor of the struct (Default constructors). Anders als bei einer Klasse ist es nicht zulässig, einen Parameter losen Instanzkonstruktor zu deklarieren.Unlike a class, a struct is not permitted to declare a parameterless instance constructor. Stattdessen verfügt jede Struktur implizit über einen Parameter losen Instanzenkonstruktor, der immer den Wert zurückgibt, der sich aus dem Festlegen aller Werttyp Felder auf ihren Standardwert und alle Verweistyp Felder auf ergibt null
.Instead, every struct implicitly has a parameterless instance constructor which always returns the value that results from setting all value type fields to their default value and all reference type fields to null
.
Strukturen sollten so entworfen werden, dass der standardmäßige Initialisierungs Zustand einen gültigen Status aufweist.Structs should be designed to consider the default initialization state a valid state. Im BeispielIn the example
using System;
struct KeyValuePair
{
string key;
string value;
public KeyValuePair(string key, string value) {
if (key == null || value == null) throw new ArgumentException();
this.key = key;
this.value = value;
}
}
der benutzerdefinierte Instanzkonstruktor schützt nur bei NULL-Werten, wenn er explizit aufgerufen wird.the user-defined instance constructor protects against null values only where it is explicitly called. In Fällen, in denen eine KeyValuePair
Variable der Standardwert Initialisierung unterliegt, sind die key
value
Felder und NULL, und die Struktur muss darauf vorbereitet sein, diesen Zustand zu verarbeiten.In cases where a KeyValuePair
variable is subject to default value initialization, the key
and value
fields will be null, and the struct must be prepared to handle this state.
Boxing und UnboxingBoxing and unboxing
Ein Wert eines Klassen Typs kann in den Typ object
oder in einen Schnittstellentyp konvertiert werden, der von der-Klasse implementiert wird, indem der Verweis zum Zeitpunkt der Kompilierung als anderer Typ behandelt wird.A value of a class type can be converted to type object
or to an interface type that is implemented by the class simply by treating the reference as another type at compile-time. Ebenso kann ein Wert vom Typ object
oder ein Wert eines Schnittstellen Typs zurück in einen Klassentyp konvertiert werden, ohne den Verweis zu ändern (in diesem Fall ist jedoch eine Lauf Zeittyp Überprüfung erforderlich).Likewise, a value of type object
or a value of an interface type can be converted back to a class type without changing the reference (but of course a run-time type check is required in this case).
Da Strukturen keine Verweis Typen sind, werden diese Vorgänge für Strukturtypen unterschiedlich implementiert.Since structs are not reference types, these operations are implemented differently for struct types. Wenn ein Wert eines Struktur Typs in object
den Typ oder in einen Schnittstellentyp konvertiert wird, der von der Struktur implementiert wird, wird ein Boxing-Vorgang durchgeführt.When a value of a struct type is converted to type object
or to an interface type that is implemented by the struct, a boxing operation takes place. Wenn ein Wert des Typs object
oder ein Wert eines Schnittstellen Typs zurück in einen Strukturtyp konvertiert wird, findet auch ein Unboxing-Vorgang statt.Likewise, when a value of type object
or a value of an interface type is converted back to a struct type, an unboxing operation takes place. Ein wichtiger Unterschied von denselben Vorgängen für Klassentypen besteht darin, dass Boxing und Unboxing den Struktur Wert entweder in die oder aus der geachtelten Instanz kopieren.A key difference from the same operations on class types is that boxing and unboxing copies the struct value either into or out of the boxed instance. Folglich werden Änderungen an der Unboxing-Struktur, die an der Unboxing-Struktur vorgenommen werden, nicht in der Struktur der Struktur spiegele widergespiegelt.Thus, following a boxing or unboxing operation, changes made to the unboxed struct are not reflected in the boxed struct.
Wenn ein Strukturtyp eine von geerbte virtuelle Methode überschreibt (z. b., System.Object
Equals
GetHashCode
oder ToString
), bewirkt der Aufruf der virtuellen Methode über eine Instanz des Struktur Typs nicht, dass Boxing erfolgt.When a struct type overrides a virtual method inherited from System.Object
(such as Equals
, GetHashCode
, or ToString
), invocation of the virtual method through an instance of the struct type does not cause boxing to occur. Dies gilt auch, wenn die Struktur als Typparameter verwendet wird und der Aufruf durch eine Instanz des Typparameter Typs erfolgt.This is true even when the struct is used as a type parameter and the invocation occurs through an instance of the type parameter type. Beispiel:For example:
using System;
struct Counter
{
int value;
public override string ToString() {
value++;
return value.ToString();
}
}
class Program
{
static void Test<T>() where T: new() {
T x = new T();
Console.WriteLine(x.ToString());
Console.WriteLine(x.ToString());
Console.WriteLine(x.ToString());
}
static void Main() {
Test<Counter>();
}
}
Die Ausgabe des Programms lautet wie folgt:The output of the program is:
1
2
3
Obwohl es für ToString
den Fall, dass es nicht möglich ist, Nebeneffekte hat, zeigt das Beispiel, dass kein Boxing für die drei Aufrufe von erfolgt ist x.ToString()
.Although it is bad style for ToString
to have side effects, the example demonstrates that no boxing occurred for the three invocations of x.ToString()
.
Auf ähnliche Weise tritt beim Zugriff auf ein Element in einem eingeschränkten Typparameter nie implizit ein Boxing auf.Similarly, boxing never implicitly occurs when accessing a member on a constrained type parameter. Angenommen, eine Schnittstelle ICounter
enthält eine Methode, Increment
die zum Ändern eines Werts verwendet werden kann.For example, suppose an interface ICounter
contains a method Increment
which can be used to modify a value. Wenn ICounter
als Einschränkung verwendet wird, wird die Implementierung der- Increment
Methode mit einem Verweis auf die Variable aufgerufen, die Increment
für aufgerufen wurde, nie eine geachtelte Kopie.If ICounter
is used as a constraint, the implementation of the Increment
method is called with a reference to the variable that Increment
was called on, never a boxed copy.
using System;
interface ICounter
{
void Increment();
}
struct Counter: ICounter
{
int value;
public override string ToString() {
return value.ToString();
}
void ICounter.Increment() {
value++;
}
}
class Program
{
static void Test<T>() where T: ICounter, new() {
T x = new T();
Console.WriteLine(x);
x.Increment(); // Modify x
Console.WriteLine(x);
((ICounter)x).Increment(); // Modify boxed copy of x
Console.WriteLine(x);
}
static void Main() {
Test<Counter>();
}
}
Der erste-Befehl, Increment
der den Wert in der Variablen ändert x
.The first call to Increment
modifies the value in the variable x
. Dies entspricht nicht dem zweiten-Befehl, der Increment
den Wert in einer geachtelten Kopie von ändert x
.This is not equivalent to the second call to Increment
, which modifies the value in a boxed copy of x
. Folglich lautet die Ausgabe des Programms wie folgt:Thus, the output of the program is:
0
1
1
Weitere Informationen zu Boxing und Unboxing finden Sie unter Boxing und Unboxing.For further details on boxing and unboxing, see Boxing and unboxing.
Bedeutung diesesMeaning of this
Innerhalb eines Instanzkonstruktors oder Instanzfunktionsmembers einer Klasse this
wird als Wert klassifiziert.Within an instance constructor or instance function member of a class, this
is classified as a value. Folglich this
kann verwendet werden, um auf die-Instanz zu verweisen, für die der Funktionsmember aufgerufen wurde. es ist nicht möglich, this
in einem Funktionsmember einer Klasse zuzuweisen.Thus, while this
can be used to refer to the instance for which the function member was invoked, it is not possible to assign to this
in a function member of a class.
Innerhalb eines Instanzkonstruktors einer Struktur this
entspricht einem out
Parameter vom Strukturtyp, und innerhalb eines Instanzfunktionsmembers einer Struktur this
entspricht einem ref
Parameter des Struktur Typs.Within an instance constructor of a struct, this
corresponds to an out
parameter of the struct type, and within an instance function member of a struct, this
corresponds to a ref
parameter of the struct type. In beiden Fällen this
wird als Variable klassifiziert, und es ist möglich, die gesamte Struktur, für die der Funktionsmember aufgerufen wurde, zu ändern, indem Sie this
oder als- ref
oder- out
Parameter übergeben.In both cases, this
is classified as a variable, and it is possible to modify the entire struct for which the function member was invoked by assigning to this
or by passing this as a ref
or out
parameter.
FeldinitialisiererField initializers
Wie in Standardwertebeschrieben, besteht der Standardwert einer Struktur aus dem Wert, der sich aus dem Festlegen aller Werttyp Felder auf ihren Standardwert und alle Verweistyp Felder auf ergibt null
.As described in Default values, the default value of a struct consists of the value that results from setting all value type fields to their default value and all reference type fields to null
. Aus diesem Grund lässt eine Struktur nicht zu, dass Instanzfelddeklarationen Variableninitialisierer einschließen.For this reason, a struct does not permit instance field declarations to include variable initializers. Diese Einschränkung gilt nur für Instanzfelder.This restriction applies only to instance fields. Statische Felder einer Struktur dürfen Variableninitialisierer einschließen.Static fields of a struct are permitted to include variable initializers.
Das BeispielThe example
struct Point
{
public int x = 1; // Error, initializer not permitted
public int y = 1; // Error, initializer not permitted
}
ist fehlerhaft, da die Instanzen Feld Deklarationen Variableninitialisierer enthalten.is in error because the instance field declarations include variable initializers.
KonstruktorenConstructors
Anders als bei einer Klasse ist es nicht zulässig, einen Parameter losen Instanzkonstruktor zu deklarieren.Unlike a class, a struct is not permitted to declare a parameterless instance constructor. Stattdessen verfügt jede Struktur implizit über einen Parameter losen Instanzenkonstruktor, der immer den Wert zurückgibt, der sich aus dem Festlegen aller Werttyp Felder auf ihren Standardwert und alle Verweistyp Felder auf NULL (Standardkonstruktoren) ergibt.Instead, every struct implicitly has a parameterless instance constructor which always returns the value that results from setting all value type fields to their default value and all reference type fields to null (Default constructors). Eine Struktur kann Instanzkonstruktoren mit Parametern deklarieren.A struct can declare instance constructors having parameters. Beispiel:For example
struct Point
{
int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Bei der obigen Deklaration werden die AnweisungenGiven the above declaration, the statements
Point p1 = new Point();
Point p2 = new Point(0, 0);
Erstellen Sie einen Point
mit x
und y
Initialisiert mit 0 (null).both create a Point
with x
and y
initialized to zero.
Ein Strukturinstanzkonstruktor darf keinen Konstruktorinitialisierer des Formulars einschließen base(...)
.A struct instance constructor is not permitted to include a constructor initializer of the form base(...)
.
Wenn der Strukturinstanzkonstruktor keinen Konstruktorinitialisierer angibt, this
entspricht die Variable einem out
Parameter des Strukturtyps. ähnlich wie bei einem out
Parameter this
muss an jedem Speicherort, an dem der Konstruktor zurückgegeben wird, definitiv zugewiesen werden (definitive Zuweisung).If the struct instance constructor doesn't specify a constructor initializer, the this
variable corresponds to an out
parameter of the struct type, and similar to an out
parameter, this
must be definitely assigned (Definite assignment) at every location where the constructor returns. Wenn der Strukturinstanzkonstruktor einen Konstruktorinitialisierer angibt, this
entspricht die Variable einem ref
Parameter des Strukturtyps und ähnelt einem ref
Parameter this
als definitiv beim Eintrag dem Konstruktortext zugewiesen.If the struct instance constructor specifies a constructor initializer, the this
variable corresponds to a ref
parameter of the struct type, and similar to a ref
parameter, this
is considered definitely assigned on entry to the constructor body. Beachten Sie die folgende instanzkonstruktorimplementierung:Consider the instance constructor implementation below:
struct Point
{
int x, y;
public int X {
set { x = value; }
}
public int Y {
set { y = value; }
}
public Point(int x, int y) {
X = x; // error, this is not yet definitely assigned
Y = y; // error, this is not yet definitely assigned
}
}
Es kann keine Instanzmember-Funktion (einschließlich der Set-Accessoren für die Eigenschaften X
und Y
) aufgerufen werden, bis alle Felder der Struktur, die erstellt wird, definitiv zugewiesen wurden.No instance member function (including the set accessors for the properties X
and Y
) can be called until all fields of the struct being constructed have been definitely assigned. Die einzige Ausnahme betrifft automatisch implementierte Eigenschaften (automatisch implementierte Eigenschaften).The only exception involves automatically implemented properties (Automatically implemented properties). Die konkreten Zuweisungs Regeln (einfache Zuweisungs Ausdrücke) geben explizit die Zuweisung zu einer Auto-Eigenschaft eines Struktur Typs innerhalb eines Instanzkonstruktors dieses Struktur Typs aus: eine solche Zuweisung wird als eindeutige Zuweisung des verborgenen dahinter liegenden Felds der Auto-Eigenschaft betrachtet.The definite assignment rules (Simple assignment expressions) specifically exempt assignment to an auto-property of a struct type within an instance constructor of that struct type: such an assignment is considered a definite assignment of the hidden backing field of the auto-property. Daher ist Folgendes zulässig:Thus, the following is allowed:
struct Point
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y) {
X = x; // allowed, definitely assigns backing field
Y = y; // allowed, definitely assigns backing field
}
DestruktorenDestructors
Es ist nicht zulässig, einen Dekonstruktor zu deklarieren.A struct is not permitted to declare a destructor.
Statische KonstruktorenStatic constructors
Statische Konstruktoren für Strukturen folgen den meisten der gleichen Regeln wie für-Klassen.Static constructors for structs follow most of the same rules as for classes. Die Ausführung eines statischen Konstruktors für einen Strukturtyp wird durch das erste der folgenden Ereignisse ausgelöst, die innerhalb einer Anwendungsdomäne auftreten:The execution of a static constructor for a struct type is triggered by the first of the following events to occur within an application domain:
- Es wird auf einen statischen Member des Struktur Typs verwiesen.A static member of the struct type is referenced.
- Ein explizit deklarierter Konstruktor des Struktur Typs wird aufgerufen.An explicitly declared constructor of the struct type is called.
Das Erstellen von Standardwerten (Standardwerte) von Strukturtypen löst nicht den statischen Konstruktor aus.The creation of default values (Default values) of struct types does not trigger the static constructor. (Ein Beispiel hierfür ist der Anfangswert von Elementen in einem Array.)(An example of this is the initial value of elements in an array.)
Struct examples (Strukturbeispiele)Struct examples
Im folgenden werden zwei wichtige Beispiele für die Verwendung von struct
Typen zum Erstellen von Typen veranschaulicht, die ähnlich wie die vordefinierten Typen der Sprache verwendet werden können, jedoch mit einer geänderten Semantik.The following shows two significant examples of using struct
types to create types that can be used similarly to the predefined types of the language, but with modified semantics.
Daten Bank IntegertypDatabase integer type
Die DBInt
folgende Struktur implementiert einen ganzzahligen Typ, der den gesamten Satz von Werten des int
Typs darstellen kann, zuzüglich eines zusätzlichen Zustands, der einen unbekannten Wert angibt.The DBInt
struct below implements an integer type that can represent the complete set of values of the int
type, plus an additional state that indicates an unknown value. Ein Typ mit diesen Merkmalen wird häufig in Datenbanken verwendet.A type with these characteristics is commonly used in databases.
using System;
public struct DBInt
{
// The Null member represents an unknown DBInt value.
public static readonly DBInt Null = new DBInt();
// When the defined field is true, this DBInt represents a known value
// which is stored in the value field. When the defined field is false,
// this DBInt represents an unknown value, and the value field is 0.
int value;
bool defined;
// Private instance constructor. Creates a DBInt with a known value.
DBInt(int value) {
this.value = value;
this.defined = true;
}
// The IsNull property is true if this DBInt represents an unknown value.
public bool IsNull { get { return !defined; } }
// The Value property is the known value of this DBInt, or 0 if this
// DBInt represents an unknown value.
public int Value { get { return value; } }
// Implicit conversion from int to DBInt.
public static implicit operator DBInt(int x) {
return new DBInt(x);
}
// Explicit conversion from DBInt to int. Throws an exception if the
// given DBInt represents an unknown value.
public static explicit operator int(DBInt x) {
if (!x.defined) throw new InvalidOperationException();
return x.value;
}
public static DBInt operator +(DBInt x) {
return x;
}
public static DBInt operator -(DBInt x) {
return x.defined ? -x.value : Null;
}
public static DBInt operator +(DBInt x, DBInt y) {
return x.defined && y.defined? x.value + y.value: Null;
}
public static DBInt operator -(DBInt x, DBInt y) {
return x.defined && y.defined? x.value - y.value: Null;
}
public static DBInt operator *(DBInt x, DBInt y) {
return x.defined && y.defined? x.value * y.value: Null;
}
public static DBInt operator /(DBInt x, DBInt y) {
return x.defined && y.defined? x.value / y.value: Null;
}
public static DBInt operator %(DBInt x, DBInt y) {
return x.defined && y.defined? x.value % y.value: Null;
}
public static DBBool operator ==(DBInt x, DBInt y) {
return x.defined && y.defined? x.value == y.value: DBBool.Null;
}
public static DBBool operator !=(DBInt x, DBInt y) {
return x.defined && y.defined? x.value != y.value: DBBool.Null;
}
public static DBBool operator >(DBInt x, DBInt y) {
return x.defined && y.defined? x.value > y.value: DBBool.Null;
}
public static DBBool operator <(DBInt x, DBInt y) {
return x.defined && y.defined? x.value < y.value: DBBool.Null;
}
public static DBBool operator >=(DBInt x, DBInt y) {
return x.defined && y.defined? x.value >= y.value: DBBool.Null;
}
public static DBBool operator <=(DBInt x, DBInt y) {
return x.defined && y.defined? x.value <= y.value: DBBool.Null;
}
public override bool Equals(object obj) {
if (!(obj is DBInt)) return false;
DBInt x = (DBInt)obj;
return value == x.value && defined == x.defined;
}
public override int GetHashCode() {
return value;
}
public override string ToString() {
return defined? value.ToString(): "DBInt.Null";
}
}
Boolescher DateitypDatabase boolean type
Die DBBool
folgende Struktur implementiert einen logischen Typ mit drei Werten.The DBBool
struct below implements a three-valued logical type. Mögliche Werte dieses Typs sind DBBool.True
, DBBool.False
und DBBool.Null
, bei denen der Null
Member einen unbekannten Wert angibt.The possible values of this type are DBBool.True
, DBBool.False
, and DBBool.Null
, where the Null
member indicates an unknown value. Solche logischen Typen mit drei Werten werden häufig in Datenbanken verwendet.Such three-valued logical types are commonly used in databases.
using System;
public struct DBBool
{
// The three possible DBBool values.
public static readonly DBBool Null = new DBBool(0);
public static readonly DBBool False = new DBBool(-1);
public static readonly DBBool True = new DBBool(1);
// Private field that stores -1, 0, 1 for False, Null, True.
sbyte value;
// Private instance constructor. The value parameter must be -1, 0, or 1.
DBBool(int value) {
this.value = (sbyte)value;
}
// Properties to examine the value of a DBBool. Return true if this
// DBBool has the given value, false otherwise.
public bool IsNull { get { return value == 0; } }
public bool IsFalse { get { return value < 0; } }
public bool IsTrue { get { return value > 0; } }
// Implicit conversion from bool to DBBool. Maps true to DBBool.True and
// false to DBBool.False.
public static implicit operator DBBool(bool x) {
return x? True: False;
}
// Explicit conversion from DBBool to bool. Throws an exception if the
// given DBBool is Null, otherwise returns true or false.
public static explicit operator bool(DBBool x) {
if (x.value == 0) throw new InvalidOperationException();
return x.value > 0;
}
// Equality operator. Returns Null if either operand is Null, otherwise
// returns True or False.
public static DBBool operator ==(DBBool x, DBBool y) {
if (x.value == 0 || y.value == 0) return Null;
return x.value == y.value? True: False;
}
// Inequality operator. Returns Null if either operand is Null, otherwise
// returns True or False.
public static DBBool operator !=(DBBool x, DBBool y) {
if (x.value == 0 || y.value == 0) return Null;
return x.value != y.value? True: False;
}
// Logical negation operator. Returns True if the operand is False, Null
// if the operand is Null, or False if the operand is True.
public static DBBool operator !(DBBool x) {
return new DBBool(-x.value);
}
// Logical AND operator. Returns False if either operand is False,
// otherwise Null if either operand is Null, otherwise True.
public static DBBool operator &(DBBool x, DBBool y) {
return new DBBool(x.value < y.value? x.value: y.value);
}
// Logical OR operator. Returns True if either operand is True, otherwise
// Null if either operand is Null, otherwise False.
public static DBBool operator |(DBBool x, DBBool y) {
return new DBBool(x.value > y.value? x.value: y.value);
}
// Definitely true operator. Returns true if the operand is True, false
// otherwise.
public static bool operator true(DBBool x) {
return x.value > 0;
}
// Definitely false operator. Returns true if the operand is False, false
// otherwise.
public static bool operator false(DBBool x) {
return x.value < 0;
}
public override bool Equals(object obj) {
if (!(obj is DBBool)) return false;
return value == ((DBBool)obj).value;
}
public override int GetHashCode() {
return value;
}
public override string ToString() {
if (value > 0) return "DBBool.True";
if (value < 0) return "DBBool.False";
return "DBBool.Null";
}
}