16 Struktur
16.1 Obecné
Struktury jsou podobné třídám, které představují datové struktury, které mohou obsahovat datové členy a členy funkce. Na rozdíl od tříd jsou však struktury typy hodnot a nevyžadují přidělení haldy. Proměnná struct
typu přímo obsahuje data struct
, zatímco proměnná typu třídy obsahuje odkaz na data, druhá známá jako objekt.
Poznámka: Struktury jsou zvláště užitečné pro malé datové struktury, které mají sémantiku hodnot. Komplexní čísla, body v souřadnicovém systému nebo páry klíč-hodnota ve slovníku jsou dobrými příklady struktur. Klíčem k těmto datovým strukturám je, že mají málo datových členů, že nevyžadují použití dědičnosti nebo sémantiky odkazu, spíše je možné je pohodlně implementovat pomocí sémantiky hodnot, kde přiřazení zkopíruje hodnotu místo odkazu. koncová poznámka
Jak je popsáno v §8.3.5, jednoduché typy poskytované jazykem C#, například int
, double
a bool
, jsou ve skutečnosti všechny typy struktur.
16.2 Deklarace struktury
16.2.1 Obecné
Struct_declaration je type_declaration (§14.7), která deklaruje novou strukturu:
struct_declaration
: attributes? struct_modifier* 'ref'? 'partial'? 'struct'
identifier type_parameter_list? struct_interfaces?
type_parameter_constraints_clause* struct_body ';'?
;
Struct_declaration se skládá z volitelné sady atributů (§22), za kterou následuje volitelná sada struct_modifiers (§16.2.2), za kterou následuje volitelný ref
modifikátor (§16.2.3), za kterým následuje volitelný částečný modifikátor (§15.2.7), za kterým následuje klíčové slovo struct
a identifikátor, který pojmenuje strukturu, po ní následuje volitelná specifikace type_parameter_list (§15.2.3)), po níž následuje volitelná specifikace struct_interfaces (§16.2.5), za kterou následuje volitelná specifikace type_parameter_constraints-klauzule (§15.2.5), za kterou následuje struct_body (§16.2.6), případně následuje středník.
Prohlášení o struktuře nesmí poskytnout type_parameter_constraints_clauses , pokud rovněž nezadá type_parameter_list.
Deklarace struktury, která poskytuje type_parameter_list je obecná deklarace struktury. Kromě toho každá struktura vnořená uvnitř obecné deklarace třídy nebo obecná deklarace struktury je sama o sobě obecnou deklaraci struktury, protože argumenty typu pro obsahující typ musí být zadány k vytvoření konstruovaného typu (§8.4).
Deklarace struktury, která obsahuje ref
klíčové slovo, nesmí mít struct_interfaces část.
16.2.2 Modifikátory struktury
Volitelně může struct_declaration obsahovat posloupnost struct_modifiers:
struct_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
| 'readonly'
| unsafe_modifier // unsafe code support
;
unsafe_modifier (§23.2) je k dispozici pouze v nebezpečném kódu (§23).
Jedná se o chybu v době kompilace, aby se stejný modifikátor zobrazoval vícekrát v deklaraci struktury.
readonly
Kromě toho mají modifikátory deklarace struktury stejný význam jako modifikátory deklarace třídy (§15.2.2).
readonly
Modifikátor označuje, že struct_declaration deklaruje typ, jehož instance jsou neměnné.
Struktura jen pro čtení má následující omezení:
- Každé z jeho polí instance je rovněž deklarováno
readonly
. - Žádné vlastnosti jeho instance nesmí mít set_accessor_declaration (§15.7.3).
- Neuplatní žádné zvláštní události (§15.8.2).
Když je instance struktury jen pro čtení předána metodě, jeho this
je považován za vstupní argument/parametr, který zakáže přístup k zápisu do všech polí instance (s výjimkou konstruktorů).
16.2.3 Modifikátor ref
ref
Modifikátor označuje, že struct_declaration deklaruje typ, jehož instance jsou přiděleny v zásobníku provádění. Tyto typy se nazývají typy ref struktury . ref
Modifikátor deklaruje, že instance mohou obsahovat pole typu ref-like, a nesmí být zkopírovány z jeho bezpečného kontextu (§16.4.12). Pravidla pro určení bezpečného kontextu ref struktury jsou popsána v §16.4.12.
Jedná se o chybu v době kompilace, pokud se typ struktury ref používá v některém z následujících kontextů:
- Jako typ prvku pole.
- Jako deklarovaný typ pole třídy nebo struktury, která nemá
ref
modifikátor. - Být krabicový do
System.ValueType
neboSystem.Object
. - Jako argument typu.
- Jako typ elementu řazené kolekce členů.
- Asynchronní metoda.
- Iterátor.
- Neexistuje žádný převod z
ref struct
typu na typobject
nebo typSystem.ValueType
. - Typ
ref struct
nesmí být deklarován k implementaci žádného rozhraní. - Metoda instance deklarovaná v
object
nebo vSystem.ValueType
, ale není přepsána vref struct
typu, nesmí být volána s příjemcem tohotoref struct
typu. - Metoda
ref struct
instance typu se nezachytí převodem skupiny metod na typ delegáta. - Struktura ref se nezachytí výrazem lambda ani místní funkcí.
Poznámka: Nesmí
ref struct
deklarovatasync
metody instance ani v rámci metody instance použítyield return
aniyield break
příkaz, protože implicitníthis
parametr nelze použít v těchto kontextech. koncová poznámka
Tato omezení zajišťují, že proměnná typu ref struct
neodkazuje na paměť zásobníku, která již není platná, nebo na proměnné, které již nejsou platné.
16.2.4 Částečný modifikátor
partial
Modifikátor označuje, že tento struct_declaration je částečná deklarace typu. Více částečných deklarací struktury se stejným názvem v rámci uzavřené deklarace oboru názvů nebo typu je kombinováno tak, aby vytvořilo jednu deklaraci struktury podle pravidel uvedených v §15.2.7.
16.2.5 Rozhraní struktur
Deklarace struktury může obsahovat specifikaci struct_interfaces , v takovém případě se struktura říká, aby přímo implementoval dané typy rozhraní. Pro konstruovaný typ struktury, včetně vnořeného typu deklarovaného v rámci obecné deklarace typu (§15.3.9.7), je každý typ implementovaného rozhraní získán nahrazením každého type_parameter v daném rozhraní, odpovídající type_argument konstruovaného typu.
struct_interfaces
: ':' interface_type_list
;
Zpracování rozhraní na více částech částečné deklarace struktury (§15.2.7) je dále popsáno v §15.2.4.3.
Implementace rozhraní jsou popsány dále v §18.6.
16.2.6 Tělo struktury
Struct_body struktury definuje členy struktury.
struct_body
: '{' struct_member_declaration* '}'
;
16.3 Členy struktury
Členy struktury se skládají z členů zavedených jeho struct_member_declarationa členy zděděné z typu 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
| fixed_size_buffer_declaration // unsafe code support
;
fixed_size_buffer_declaration (§23.8.2) je k dispozici pouze v nebezpečném kódu (§23).
Poznámka: Všechny druhy class_member_declarations s výjimkou finalizer_declaration jsou také struct_member_declarations. koncová poznámka
S výjimkou rozdílů uvedených v §16.4 se popisy členů třídy uvedené v §15.3 až §15.12 vztahují i na členy struktury.
16.4 Rozdíly ve třídě a struktuře
16.4.1 Obecné
Struktury se liší od tříd několika důležitými způsoby:
- Struktury jsou hodnotové typy (§16.4.2).
- Všechny typy struktur implicitně dědí z třídy
System.ValueType
(§16.4.3). - Přiřazení proměnné typu struktury vytvoří kopii přiřazené hodnoty (§16.4.4).
- Výchozí hodnota struktury je hodnota vytvořená nastavením všech polí na výchozí hodnotu (§16.4.5).
- Boxing and unboxing operations are used to convert between a struct type and certain reference types (§16.4.6).
this
Význam se liší v rámci členů struktury (§16.4.7).- Deklarace polí instance pro strukturu nesmí obsahovat inicializátory proměnných (§16.4.8).
- Struktura není povolena k deklaraci konstruktoru instance bez parametrů (§16.4.9).
- Struktura není povolena k deklaraci finalizátoru.
16.4.2 Sémantika hodnot
Struktury jsou hodnotové typy (§8.3) a říká se, že mají sémantiku hodnot. Třídy jsou na druhou stranu referenčními typy (§8.2) a mají sémantiku odkazu.
Proměnná typu struktury přímo obsahuje data struktury, zatímco proměnná typu třídy obsahuje odkaz na objekt, který obsahuje data. Pokud struktura B
obsahuje pole instance typu A
a A
je typ struktury, jedná se o chybu A
v době kompilace, která závisí na B
typu nebo typu vytvořeném z B
. A struct X
přímo závisí na struktuřeY
, pokud X
obsahuje pole instance typu Y
. Vzhledem k této definici je kompletní sada struktur, na kterých závisí struktura, tranzitivní uzavření přímo závisí na relaci.
Příklad:
struct Node { int data; Node next; // error, Node directly depends on itself }
je chyba, protože
Node
obsahuje pole instance vlastního typu. Další příkladstruct A { B b; } struct B { C c; } struct C { A a; }
je chyba, protože každý typ
A
,B
aC
závisí na sobě.end example
U tříd je možné, aby dvě proměnné odkazovaly na stejný objekt, a proto operace s jednou proměnnou ovlivnit objekt odkazovaný druhou proměnnou. U struktur mají proměnné vlastní kopii dat (s výjimkou parametrů podle odkazu) a není možné, aby operace s jednou z nich ovlivnily druhý. Kromě toho, pokud není explicitně nullable (§8.3.12), není možné, aby hodnoty typu struktury byly null
.
Poznámka: Pokud struktura obsahuje pole typu odkazu, lze obsah odkazovaného objektu změnit jinými operacemi. Hodnota samotného pole, tj. objektu, na který odkazuje, však nelze změnit prostřednictvím mutaci jiné hodnoty struktury. koncová poznámka
Příklad: S ohledem na následující:
struct Point { public int x, y; public Point(int x, int y) { this.x = x; this.y = y; } } class A { static void Main() { Point a = new Point(10, 10); Point b = a; a.x = 100; Console.WriteLine(b.x); } }
výstup je
10
. Přiřazenía
kb
vytvoření kopie hodnoty, ab
proto není ovlivněno přiřazením .a.x
MístoPoint
toho byl deklarován jako třída, výstup by byl100
protoa
, že byb
odkazoval na stejný objekt.end example
16.4.3 Dědičnost
Všechny typy struktur implicitně dědí z třídy System.ValueType
, která následně dědí z třídy object
. Deklarace struktury může určit seznam implementovaných rozhraní, ale není možné, aby deklarace struktury určila základní třídu.
Typy struktur nejsou nikdy abstraktní a vždy jsou implicitně zapečetěné. Modifikátory abstract
a sealed
modifikátory nejsou proto povoleny v deklaraci struktury.
Vzhledem k tomu, že dědičnost není podporována pro struktury, deklarovaná přístupnost člena struktury nemůže být protected
, private protected
nebo protected internal
.
Členy funkce ve struktuře nemohou být abstraktní nebo virtuální a override
modifikátor je povolen pouze k přepsání metod zděděných z System.ValueType
.
16.4.4 Přiřazení
Přiřazení proměnné typu struktury vytvoří kopii přiřazené hodnoty. Liší se od přiřazení k proměnné typu třídy, která kopíruje odkaz, ale nikoli objekt identifikovaný odkazem.
Podobně jako přiřazení se při předání struktury jako parametr hodnoty nebo vrácení v důsledku člena funkce vytvoří kopie struktury. Struktura může být předána odkazem na člen funkce pomocí parametru by-reference.
Je-li vlastnost nebo indexer struktury cílem přiřazení, výraz instance přidružený k vlastnosti nebo indexeru musí být klasifikován jako proměnná. Pokud je výraz instance klasifikován jako hodnota, dojde k chybě v době kompilace. Toto je podrobněji popsáno v §12.21.2.
16.4.5 Výchozí hodnoty
Jak je popsáno v §9.3, při vytváření se automaticky inicializuje několik druhů proměnných na jejich výchozí hodnotu. U proměnných typů tříd a jiných referenčních typů je null
tato výchozí hodnota . Vzhledem k tomu, že struktury jsou typy hodnot, které nemohou být null
, výchozí hodnota struktury je hodnota vytvořená nastavením všech polí typu hodnoty na výchozí hodnotu a všechna pole odkazového typu na null
.
Příklad: Odkazování na
Point
strukturu deklarovanou výše, příkladPoint[] a = new Point[100];
inicializuje každou
Point
z polí na hodnotu vytvořenou nastavenímx
ay
pole na nulu.end example
Výchozí hodnota struktury odpovídá hodnotě vrácené výchozím konstruktorem struktury (§8.3.3). Na rozdíl od třídy není struktura povolena k deklaraci konstruktoru instance bez parametrů. Místo toho má každá struktura implicitně konstruktor instance bez parametrů, který vždy vrátí hodnotu, která je výsledkem nastavení všech polí na výchozí hodnoty.
Poznámka: Struktury by měly být navrženy tak, aby zvážily výchozí inicializační stav platného stavu. V příkladu
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; } }
konstruktor instance definovaný uživatelem chrání před
null
hodnotami pouze tam, kde je explicitně volána. V případech, kdy je proměnnáKeyValuePair
předmětem výchozí inicializace hodnoty,key
budounull
pole avalue
pole a struktura by měla být připravena pro zpracování tohoto stavu.koncová poznámka
16.4.6 Boxing a unboxing
Hodnotu typu třídy lze převést na typ object
nebo na typ rozhraní implementovaný třídou jednoduše tak, že v době kompilace považuje odkaz za jiný typ. Podobně je možné hodnotu typu nebo object
hodnoty typu rozhraní převést zpět na typ třídy beze změny odkazu (v tomto případě se ale vyžaduje kontrola typu běhu).
Vzhledem k tomu, že struktury nejsou odkazové typy, jsou tyto operace implementovány odlišně pro typy struktur. Pokud je hodnota typu struktury převedena na určité odkazové typy (jak je definováno v §10.2.9), provede se operace boxování. Podobně platí, že pokud je hodnota určitých referenčních typů (definovaná v §10.3.7) převedena zpět na typ struktury, provede se operace rozbalení. Klíčovým rozdílem od stejných operací u typů tříd je, že boxování a rozbalování kopíruje hodnotu struktury do nebo z boxované instance.
Poznámka: Po operaci boxingu nebo rozbalení se změny provedené v unboxed
struct
se tedy neprojeví v rámečkustruct
. koncová poznámka
Další podrobnosti o balení a odsílání naleznete v článcích §10.2.9 a §10.3.7.
16.4.7 Význam tohoto
Význam this
struktury se liší od významu this
třídy, jak je popsáno v §12.8.14. Pokud typ struktury přepíše virtuální metodu zděděnou z System.ValueType
(například GetHashCode
Equals
, nebo ToString
), vyvolání virtuální metody prostřednictvím instance typu struktury nezpůsobí výskyt boxu. To platí i v případě, že se struktura používá jako parametr typu a vyvolání probíhá prostřednictvím instance typu parametru.
Příklad:
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>(); }
Výstupem programu je:
1 2 3
I když je špatný styl,
ToString
aby měl vedlejší účinky, příklad ukazuje, že žádné boxování nebylo pro tři vyvoláníx.ToString()
.end example
Podobně při přístupu k členu u parametru omezeného typu při implementaci člena v rámci typu hodnoty nikdy implicitně nedojde. Předpokládejme například, že rozhraní ICounter
obsahuje metodu Increment
, kterou lze použít k úpravě hodnoty. Pokud ICounter
se používá jako omezení, implementace Increment
metody je volána s odkazem na proměnnou, která Increment
byla volána, nikdy boxed kopie.
Příklad:
interface ICounter { void Increment(); } struct Counter : ICounter { int value; public override string ToString() => 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>(); }
První volání
Increment
modifikuje hodnotu v proměnnéx
. Toto není ekvivalentem druhého voláníIncrement
, který upraví hodnotu v krabicové kopiix
. Výstupem programu je tedy:0 1 1
end example
16.4.8 Inicializátory polí
Jak je popsáno v §16.4.5, výchozí hodnota struktury se skládá z hodnoty, která je výsledkem nastavení všech polí typu hodnoty na výchozí hodnotu a všech polí odkazového typu na null
. Z tohoto důvodu struktura nepovoluje deklarace polí instance, aby zahrnovaly inicializátory proměnných. Toto omezení platí jenom pro pole instancí. Statická pole struktury mohou obsahovat inicializátory proměnných.
Příklad: Následující:
struct Point { public int x = 1; // Error, initializer not permitted public int y = 1; // Error, initializer not permitted }
je chybná, protože deklarace polí instance zahrnují inicializátory proměnných.
end example
16.4.9 Konstruktory
Na rozdíl od třídy není struktura povolena k deklaraci konstruktoru instance bez parametrů. Místo toho má každá struktura implicitně konstruktor instance bez parametrů, který vždy vrátí hodnotu, která je výsledkem nastavení všech polí typu hodnoty na výchozí hodnotu a všechna pole odkazového typu na null
(§8.3.3). Struktura může deklarovat konstruktory instance s parametry.
Příklad: S ohledem na následující:
struct Point { int x, y; public Point(int x, int y) { this.x = x; this.y = y; } } class A { static void Main() { Point p1 = new Point(); Point p2 = new Point(0, 0); } }
příkazy vytvoří hodnotu with
Point
x
ay
initialized to zero.end example
Konstruktor instance struktury nesmí obsahovat inicializátor konstruktoru formuláře base(
argument_list)
, kde argument_list je nepovinný.
Parametr this
konstruktoru instance struktury odpovídá výstupnímu parametru typu struktury. V každém místě, kde se konstruktor vrátí, this
musí být rozhodně přiřazen (§9.4). Podobně nelze číst (ani implicitně) v těle konstruktoru před tím, než bude jednoznačně přiřazen.
Pokud konstruktor instance struktury určuje inicializátor konstruktoru, tento inicializátor je považován za určité přiřazení k tomu, které nastane před tělem konstruktoru. Proto samotné tělo nemá žádné inicializační požadavky.
Příklad: Zvažte implementaci konstruktoru instance níže:
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 } }
Nelze volat žádný člen funkce instance (včetně přístupových objektů sady pro vlastnosti
X
aY
) dokud nebudou jednoznačně přiřazena všechna pole struktury, která je vytvořena. Mějte však na paměti, že pokudPoint
by byla třída místo struktury, konstruktor instance implementace by byla povolena. Existuje jedna výjimka, která zahrnuje automaticky implementované vlastnosti (§15.7.4). Určitá pravidla přiřazení (§12.21.2) výslovně vyloučila přiřazení k automatické vlastnosti typu struktury v rámci konstruktoru instance tohoto typu struktury: takové přiřazení je považováno za určité přiřazení skrytého záložního pole automatické vlastnosti. Proto je povoleno následující: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 } }
end example]
16.4.10 Statické konstruktory
Statické konstruktory pro struktury se řídí většinou stejných pravidel jako u tříd. Spuštění statického konstruktoru pro typ struktury je aktivováno první z následujících událostí v rámci domény aplikace:
- Na statický člen typu struktury se odkazuje.
- Explicitně deklarovaný konstruktor typu struktury je volána.
Poznámka: Vytvoření výchozích hodnot (§16.4.5) typů struktury neaktivuje statický konstruktor. (Příkladem je počáteční hodnota prvků v poli.) koncová poznámka
16.4.11 Automaticky implementované vlastnosti
Automaticky implementované vlastnosti (§15.7.4) používají skrytá backingová pole, která jsou přístupná pouze pro přístupové objekty vlastností.
Poznámka: Toto omezení přístupu znamená, že konstruktory v strukturách obsahujících automaticky implementované vlastnosti často potřebují explicitní inicializátor konstruktoru, kde by jinak nepotřebují jeden, aby splňovaly požadavek všech polí, která jsou jednoznačně přiřazena před vyvoláním jakéhokoli člena funkce nebo vrátí konstruktor. koncová poznámka
16.4.12 Bezpečné omezení kontextu
16.4.12.1 Obecné
V době kompilace je každý výraz přidružený k kontextu, kde tato instance a všechna její pole mohou být bezpečně přístupná, jeho bezpečný kontext. Bezpečný kontext je kontext, který ohraničuje výraz, který je bezpečný, aby hodnota utekla.
Libovolný výraz, jehož typ kompilace není ref strukturou, má bezpečný kontext kontextu volajícího kontextu.
Výraz default
pro libovolný typ má bezpečný kontext kontextu volajícího.
Pro jakýkoli jiný než výchozí výraz, jehož typ kompilace je ref struktura má bezpečný kontext definovaný v následujících částech.
Záznamy bezpečného kontextu, do kterých je možné zkopírovat kontextovou hodnotu. Při přiřazení z výrazu E1
s bezpečným kontextem S1
k výrazu E2
s bezpečným kontextem S2
se jedná o chybu, pokud S2
je širší kontext než S1
.
Existují tři různé hodnoty bezpečného kontextu, stejné jako hodnoty kontextu ref-safe-context definované pro referenční proměnné (§9.7.2): blok deklarace, člen funkce a kontext volajícího. Bezpečný kontext výrazu omezuje jeho použití následujícím způsobem:
- V případě návratového prohlášení
return e1
musí být bezpečný kontexte1
volajícího. - Pro přiřazení
e1 = e2
bezpečného kontextue2
musí být alespoň tak široký kontext, jako je bezpečný kontexte1
.
Pro vyvolání metody, pokud existuje ref
typ nebo out
argument ref struct
(včetně příjemce, pokud typ není readonly
), s bezpečným kontextem S1
, pak žádný argument (včetně příjemce) nemusí mít užší bezpečný kontext než S1
.
16.4.12.2 Kontext bezpečného parametru
Parametr typu ref struktury, včetně this
parametru metody instance, má bezpečný kontext kontextu volajícího kontextu.
16.4.12.3 Kontext bezpečné místní proměnné
Místní proměnná typu ref struktury má bezpečný kontext následujícím způsobem:
- Pokud je proměnná iterační proměnnou
foreach
smyčky, je bezpečný kontext proměnné stejný jako bezpečný kontext výrazuforeach
smyčky. - V opačném případě, pokud deklarace proměnné má inicializátor, pak je bezpečný kontext proměnné stejný jako bezpečný kontext tohoto inicializátoru.
- V opačném případě je proměnná neinicializována v okamžiku deklarace a má bezpečný kontext kontextu volajícího.
16.4.12.4 Kontext bezpečného pole
Odkaz na pole e.F
, kde typ F
je typ ref struktury, má bezpečný kontext, který je stejný jako bezpečný kontext e
.
16.4.12.5 Operátory
Použití uživatelem definovaného operátoru se považuje za metodu vyvolání (§16.4.12.6).
Pro operátor, který poskytuje hodnotu, například e1 + e2
nebo c ? e1 : e2
, bezpečný kontext výsledku je nejužší kontext mezi bezpečnými kontexty operandů operátoru. V důsledku toho je pro unární operátor, který poskytuje hodnotu, například +e
bezpečný kontext výsledku je bezpečný kontext operandu.
Poznámka: První operand podmíněného operátoru je
bool
, takže jeho bezpečný kontext je kontext volajícího. Z toho vyplývá, že výsledný bezpečný kontext je nejužším bezpečným kontextem druhého a třetího operandu. koncová poznámka
16.4.12.6 Metoda a vyvolání vlastnosti
Hodnota, která je výsledkem vyvolání e1.M(e2, ...)
metody nebo vyvolání e.P
vlastnosti, má bezpečný kontext nejmenších z následujících kontextů:
- kontext volajícího.
- Bezpečný kontext všech výrazů argumentů (včetně příjemce).
Vyvolání vlastnosti (nebo get
set
) se považuje za metodu vyvolání základní metody výše uvedenými pravidly.
16.4.12.7 stackalloc
Výsledkem výrazu stackalloc je bezpečný kontext člena funkce.
16.4.12.8 Vyvolání konstruktoru
Výraz new
, který vyvolá konstruktor, dodržuje stejná pravidla jako volání metody, která je považována za vrácení typu vytvořeného.
Kromě bezpečného kontextu je nejmenší z bezpečných kontextů všech argumentů a operandů všech výrazů inicializátoru objektů, rekurzivně, pokud je k dispozici nějaký inicializátor.
Poznámka: Tato pravidla spoléhají na
Span<T>
to, že nemají konstruktor tohoto formuláře:public Span<T>(ref T p)
Takový konstruktor vytváří instance
Span<T>
používané jako pole nerozlišující odref
pole. Bezpečnostní pravidla popsaná v tomto dokumentu závisí naref
polích, která nejsou platným konstruktorem v jazyce C# nebo .NET. koncová poznámka
ECMA C# draft specification