Typy struktur (Referenční dokumentace jazyka C#)

Typ struktury (nebo typ struktury) je hodnotový typ, který dokáže zapouzdřit data a související funkce. Klíčové slovo struct použijete k definování typu struktury:

public struct Coords
{
    public Coords(double x, double y)
    {
        X = x;
        Y = y;
    }

    public double X { get; }
    public double Y { get; }

    public override string ToString() => $"({X}, {Y})";
}

Typy struktur mají sémantiku hodnot. To znamená, že proměnná typu struktury obsahuje instanci typu . Ve výchozím nastavení se hodnoty proměnných zkopírují při přiřazení, předá se argument metodě a vrátí se výsledek metody. V případě proměnné typu struktury se zkopíruje instance typu . Další informace najdete v tématu Typy hodnot.

Typy struktur se obvykle používají k návrhu malých datových typů, které poskytují jen malé nebo žádné chování. Například .NET používá typy struktur k reprezentaci čísla (celé číslo i reálné),logické hodnoty , znaku Unicodea časové instance. Pokud jste se zaměřili na chování typu, zvažte definování třídy. Typy tříd mají referenční sémantiku. To znamená, že proměnná typu třídy obsahuje odkaz na instanci typu, nikoli na samotnou instanci.

Vzhledem k tomu, že typy struktur mají sémantiku hodnot, doporučujeme definovat neměnné typy struktur.

readonly Struct

Počínaje jazykem C# 7.2 můžete pomocí modifikátoru deklarovat, že typ readonly struktury je neměnný. Všechny datové členy readonly struktury musí být jen pro čtení následujícím způsobem:

To zaručuje, že žádný člen readonly struktury nemění stav struktury. V jazyce C# 8,0 a novějším to znamená, že další členy instance s výjimkou konstruktorů jsou implicitně readonly .

Poznámka

V rámci readonly struktury může být datový člen proměnlivého typu odkazu stále v jeho vlastním stavu. Například nelze nahradit List<T> instanci, ale do ní můžete přidat nové prvky.

Následující kód definuje readonly strukturu se sadou vlastností pouze pro inicializaci, která je k dispozici v C# 9,0 a novější:

public readonly struct Coords
{
    public Coords(double x, double y)
    {
        X = x;
        Y = y;
    }

    public double X { get; init; }
    public double Y { get; init; }

    public override string ToString() => $"({X}, {Y})";
}

readonly členy instance

Počínaje jazykem C# 8,0 můžete také použít readonly Modifikátor k deklaraci, že člen instance neupravuje stav struktury. Pokud nemůžete deklarovat typ celé struktury jako readonly , použijte readonly Modifikátor k označení členů instance, které nemění stav struktury.

V rámci readonly člena instance nelze přiřadit pole instance struktury. readonlyČlen však může volat readonly nečlen. V takovém případě kompilátor vytvoří kopii instance struktury a zavolá do readonly této kopie nečlen. V důsledku toho se původní instance struktury nezmění.

Obvykle použijete readonly modifikátor pro následující typy členů instance:

  • způsobů

    public readonly double Sum()
    {
        return X + Y;
    }
    

    Můžete také použít readonly Modifikátor na metody, které přepisují metody deklarované v System.Object :

    public readonly override string ToString() => $"({X}, {Y})";
    
  • vlastnosti a indexery:

    private int counter;
    public int Counter
    {
        readonly get => counter;
        set => counter = value;
    }
    

    Pokud potřebujete použít readonly modifikátor u přístupových objektů vlastnosti nebo indexeru, použijte ji v deklaraci vlastnosti nebo indexeru.

    Poznámka

    Kompilátor deklaruje get přistupující objekt pro automaticky implementovanou vlastnost jako readonly , bez ohledu na přítomnost readonly modifikátoru v deklaraci vlastnosti.

    V C# 9.0 a novějších verzích můžete modifikátor použít na vlastnost nebo readonly indexer s init přístupem:

    public readonly double X { get; init; }
    

Modifikátor nelze použít readonly u statických členů typu struktury.

Kompilátor může modifikátor využít readonly k optimalizaci výkonu. Další informace najdete v tématu Psaní bezpečného a efektivního kódu jazyka C#.

Omezení návrhu typu struktury

Při návrhu typu struktury máte stejné možnosti jako u typu třídy s následujícími výjimkami:

  • Konstruktor bez parametrů nelze deklarovat. Každý typ struktury již poskytuje implicitní konstruktor bez parametrů, který vytváří výchozí hodnotu typu.

  • V deklaraci nelze inicializovat pole instance nebo vlastnost. Můžete však inicializovat statické nebo konstantní pole nebo statickou vlastnost v jeho deklaraci.

  • Konstruktor typu struktury musí inicializovat všechna pole instance typu.

  • Typ struktury nemůže dědit z jiného typu třídy nebo struktury a nemůže být základem třídy. Typ struktury však může implementovat rozhraní.

  • Finalizační metodu nelze deklarovat v rámci typu struktury.

Vytvoření instance typu struktury

V jazyce C# musíte před použitím inicializovat deklarovanou proměnnou. Protože proměnná typu struktury nemůže být (pokud se jedná o proměnnou typu s možnou hodnotou null), musíte vytvořit instanci null odpovídajícího typu. Můžete to udělat několika způsoby.

Obvykle vytváříte instanci typu struktury voláním vhodného konstruktoru s new operátorem . Každý typ struktury má alespoň jeden konstruktor. To je implicitní konstruktor bez parametrů, který vytváří výchozí hodnotu typu. Výchozí hodnotu typu můžete vytvořit také pomocí výchozího výrazu hodnoty .

Pokud jsou všechna pole instance typu struktury dostupná, můžete také vytvořit instanci bez new operátoru. V takovém případě je nutné inicializovat všechna pole instance před prvním použitím instance. Následující příklad ukazuje, jak to provést:

public static class StructWithoutNew
{
    public struct Coords
    {
        public double x;
        public double y;
    }

    public static void Main()
    {
        Coords p;
        p.x = 3;
        p.y = 4;
        Console.WriteLine($"({p.x}, {p.y})");  // output: (3, 4)
    }
}

V případě předdefinovaných hodnotových typůpoužijte odpovídající literály k určení hodnoty typu.

Předávání proměnných typu struktury podle odkazu

Pokud předáte proměnnou typu struktury do metody jako argument nebo vrátíte hodnotu typu struktury z metody, je zkopírována celá instance typu struktury. To může mít vliv na výkon vašeho kódu ve scénářích s vysokým výkonem, které zahrnují typy velkých struktur. Kopírování hodnot se můžete vyhnout předáním proměnné typu struktury odkazem. Použijte ref out in modifikátory parametrů metody, nebo, aby označovaly, že argument musí být předán odkazem. Pomocí funkce ref Return můžete vrátit výsledek metody odkazem. Další informace najdete v tématu Zápis bezpečného a efektivního kódu v jazyce C#.

ref nemají

Počínaje jazykem C# 7,2 můžete použít ref Modifikátor v deklaraci typu struktury. Instance ref typu struktury jsou přiděleny v zásobníku a nemohou uniknout do spravované haldy. Aby bylo zajištěno, že kompilátor omezuje využití ref typů struktury následujícím způsobem:

  • refStruktura nemůže být typem elementu pole.
  • refStruktura nemůže být deklarovaného typu pro pole třídy nebo bez ref struktury.
  • refStruktura nemůže implementovat rozhraní.
  • Struktura ref nemůže být zablokovaná na nebo System.ValueType System.Object .
  • Struktura ref nemůže být argument typu.
  • Proměnnou ref struktury nelze zachytit výrazem lambda nebo místní funkcí.
  • V ref metodě nelze použít proměnnou async struktury. Proměnné struktury však můžete použít v synchronních metodách, například v těch, které vrací ref Task nebo Task<TResult> .
  • Proměnnou ref struktury nelze použít v iterátorech.

Typ struktury se obvykle definuje, když potřebujete typ, který obsahuje také ref datové členy ref typů struktur:

public ref struct CustomRef
{
    public bool IsValid;
    public Span<int> Inputs;
    public Span<int> Outputs;
}

Chcete-li deklarovat struktury jako , zkombinujte modifikátory a v deklaraci typu (modifikátor musí být před ref readonly readonly ref readonly ref modifikátorem ):

public readonly ref struct ConversionRequest
{
    public ConversionRequest(double rate, ReadOnlySpan<double> values)
    {
        Rate = rate;
        Values = values;
    }

    public double Rate { get; }
    public ReadOnlySpan<double> Values { get; }
}

V .NET jsou příklady struktury a ref System.Span<T> System.ReadOnlySpan<T> .

Omezení struct

Klíčové slovo v omezení použijete také k určení, že parametr typu je hodnotový typ, který struct nemůže mít hodnotu null. struct Typy struktury i výčtu splňují struct omezení.

Převody

U libovolného typu ref struktury (s výjimkou typů struktur) existují převody typu boxing a unboxing na typy a System.ValueType System.Object . Mezi typem struktury a libovolným rozhraním, které implementuje, existují také převody typu boxing a unboxing.

specifikace jazyka C#

Další informace najdete v části Structs specifikace jazyka C#.

Další informace o funkcích zavedených v jazyce C# 7.2 a novějších najdete v následujících poznámkách k návrhu funkcí:

Viz také