Sdílet prostřednictvím


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, doublea 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.

readonlyKromě 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 nebo System.Object.
  • Jako argument typu.
  • Jako typ elementu řazené kolekce členů.
  • Asynchronní metoda.
  • Iterátor.
  • Neexistuje žádný převod z ref struct typu na typ object nebo typ System.ValueType.
  • Typ ref struct nesmí být deklarován k implementaci žádného rozhraní.
  • Metoda instance deklarovaná v object nebo v System.ValueType , ale není přepsána v ref struct typu, nesmí být volána s příjemcem tohoto ref 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 deklarovat async metody instance ani v rámci metody instance použít yield return ani yield 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§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 Xpří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říklad

struct A { B b; }
struct B { C c; }
struct C { A a; }

je chyba, protože každý typ A, Ba C 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 k b vytvoření kopie hodnoty, a b proto není ovlivněno přiřazením .a.x Místo Point toho byl deklarován jako třída, výstup by byl 100 proto a , že by b 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 protectednebo 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 nulltato 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říklad

Point[] a = new Point[100];

inicializuje každou Point z polí na hodnotu vytvořenou nastavením x a y 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 budou nullpole a value 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čku struct. 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 GetHashCodeEquals, 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é kopii x. 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 a y 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 a Y) dokud nebudou jednoznačně přiřazena všechna pole struktury, která je vytvořena. Mějte však na paměti, že pokud Point 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 S1k výrazu E2 s bezpečným kontextem S2se 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 e1musí být bezpečný kontext e1 volajícího.
  • Pro přiřazení e1 = e2 bezpečného kontextu e2 musí být alespoň tak široký kontext, jako je bezpečný kontext e1.

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ýrazu foreach 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 +ebezpeč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í od ref pole. Bezpečnostní pravidla popsaná v tomto dokumentu závisí na ref polích, která nejsou platným konstruktorem v jazyce C# nebo .NET. koncová poznámka