Deklarace příkazů

Příkaz deklarace deklaruje novou proměnnou a volitelně ji inicializuje. Všechny proměnné mají deklarovaný typ. Další informace o typech najdete v článku o systému typů .NET. Deklarace obvykle obsahuje typ a název proměnné. Může také obsahovat inicializaci: = operátor následovaný výrazem. Typ může být nahrazen znakem var. Deklarace nebo výraz může obsahovat ref modifikátor, který deklaruje, že nová proměnná odkazuje na existující umístění úložiště.

Implicitně zadávané místní proměnné

Proměnné, které jsou deklarovány v oboru metody, můžou mít implicitní typ var. Implicitně napsaná místní proměnná je silně zadáváná, jako kdybyste typ deklarovali sami, ale typ určuje kompilátor. Následující dvě deklarace a ab jsou funkčně ekvivalentní:

var a = 10; // Implicitly typed.
int b = 10; // Explicitly typed.

Důležité

Při var použití s povolenými typy odkazů s možnou hodnotou null vždy znamená typ odkazu s možnou hodnotou null, i když typ výrazu není null. Analýza stavu null kompilátoru chrání před dereferencováním potenciální null hodnoty. Pokud proměnná nikdy není přiřazena výrazu, který může být null, kompilátor nevygeneruje žádná upozornění. Pokud proměnnou přiřadíte výrazu, který může mít hodnotu null, musíte před dereferencováním otestovat, jestli není null, abyste se vyhnuli upozorněním.

Běžné použití klíčového var slova je s konstruktorem vyvolání výrazů. Použití var příkazu umožňuje neopakovat název typu v deklaraci proměnné a instanci objektu, jak ukazuje následující příklad:

var xs = new List<int>();

Počínaje jazykem C# 9.0 můžete jako alternativu new použít cílový výraz :

List<int> xs = new();
List<int>? ys = new();

Při porovnávání vzorů var se klíčové slovo používá ve vzoruvar.

Následující příklad ukazuje dva výrazy dotazu. V prvním výrazu je použití parametru var povolené, ale nevyžaduje se, protože typ výsledku dotazu lze explicitně uvést jako IEnumerable<string>. Ve druhém výrazu však umožňuje, var aby výsledkem byla kolekce anonymních typů a název tohoto typu není přístupný s výjimkou samotného kompilátoru. Použití nástroje var eliminuje požadavek na vytvoření nové třídy pro výsledek. V příkladu foreach 2 musí být implicitně zadána také proměnná item iterace.

// Example #1: var is optional when
// the select clause specifies a string
string[] words = { "apple", "strawberry", "grape", "peach", "banana" };
var wordQuery = from word in words
                where word[0] == 'g'
                select word;

// Because each element in the sequence is a string,
// not an anonymous type, var is optional here also.
foreach (string s in wordQuery)
{
    Console.WriteLine(s);
}

// Example #2: var is required because
// the select clause specifies an anonymous type
var custQuery = from cust in customers
                where cust.City == "Phoenix"
                select new { cust.Name, cust.Phone };

// var must be used because each item
// in the sequence is an anonymous type
foreach (var item in custQuery)
{
    Console.WriteLine("Name={0}, Phone={1}", item.Name, item.Phone);
}

Referenční místní hodnoty

Před typ proměnné přidáte ref klíčové slovo, které deklaruje ref místní. Místní ref je proměnná, která odkazuje na jiné úložiště. Předpokládejme, že GetContactInformation je metoda deklarována jako návrat odkazu:

public ref Person GetContactInformation(string fname, string lname)

Porovnejme tato dvě přiřazení:

Person p = contacts.GetContactInformation("Brandie", "Best");
ref Person p2 = ref contacts.GetContactInformation("Brandie", "Best");

Proměnná p obsahuje kopii návratové hodnoty z GetContactInformation. Jedná se o samostatné umístění úložiště od návratu ref z GetContactInformation. Pokud změníte libovolnou vlastnost objektu p, změníte kopii objektu Person.

Proměnná p2odkazuje na umístění úložiště pro ref návrat z GetContactInformation. Je to stejné úložiště jako ref vrácení z GetContactInformation. Pokud změníte libovolnou vlastnost objektu p2, změníte tuto jednu instanci objektu Person.

K hodnotě můžete přistupovat odkazem stejným způsobem. V některých případech se při přístupu k hodnotě pomocí odkazu zvýší výkon tím, že se vyhnete potenciálně nákladné operaci kopírování. Následující příkaz například ukazuje, jak lze definovat místní hodnotu odkazu, která se používá k odkazování na hodnotu.

ref VeryLargeStruct reflocal = ref veryLargeStruct;

Klíčové ref slovo se používá před deklaraci místní proměnné i před hodnotou v druhém příkladu. Nezahrnutí obou ref klíčových slov do deklarace proměnné a přiřazení v obou příkladech má za následek chybu kompilátoru CS8172: "Nelze inicializovat proměnnou podle odkazu s hodnotou."

ref VeryLargeStruct reflocal = ref veryLargeStruct; // initialization
refLocal = ref anotherVeryLargeStruct; // reassigned, refLocal refers to different storage.

Místní proměnné odkazu musí být stále inicializovány, když jsou deklarovány.

Následující příklad definuje třídu, která ukládá pole celočíselných NumberStore hodnot. Metoda FindNumber vrátí odkazem první číslo, které je větší než nebo rovno číslu předaným jako argument. Pokud žádné číslo není větší nebo rovno argumentu, vrátí metoda číslo v indexu 0.

using System;

class NumberStore
{
    int[] numbers = { 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023 };

    public ref int FindNumber(int target)
    {
        for (int ctr = 0; ctr < numbers.Length; ctr++)
        {
            if (numbers[ctr] >= target)
                return ref numbers[ctr];
        }
        return ref numbers[0];
    }

    public override string ToString() => string.Join(" ", numbers);
}

Následující příklad volá metodu NumberStore.FindNumber pro načtení první hodnoty, která je větší než nebo rovna 16. Volající pak zdvojnásobí hodnotu vrácenou metodou. Výstup z příkladu ukazuje změnu, která se odráží v hodnotě prvků NumberStore pole instance.

var store = new NumberStore();
Console.WriteLine($"Original sequence: {store.ToString()}");
int number = 16;
ref var value = ref store.FindNumber(number);
value *= 2;
Console.WriteLine($"New sequence:      {store.ToString()}");
// The example displays the following output:
//       Original sequence: 1 3 7 15 31 63 127 255 511 1023
//       New sequence:      1 3 7 15 62 63 127 255 511 1023

Bez podpory návratových hodnot odkazu se taková operace provede vrácením indexu elementu pole spolu s jeho hodnotou. Volající pak může použít tento index k úpravě hodnoty v samostatném volání metody. Volající však může také upravit index pro přístup a případně upravit jiné hodnoty pole.

Následující příklad ukazuje, jak je možné metodu FindNumber přepsat tak, aby používala místní přiřazení odkazu:

using System;

class NumberStore
{
    int[] numbers = { 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023 };

    public ref int FindNumber(int target)
    {
        ref int returnVal = ref numbers[0];
        var ctr = numbers.Length - 1;
        while ((ctr >= 0) && (numbers[ctr] >= target))
        {
            returnVal = ref numbers[ctr];
            ctr--;
        }
        return ref returnVal;
    }

    public override string ToString() => string.Join(" ", numbers);
}

Tato druhá verze je efektivnější s delšími sekvencemi ve scénářích, kdy je hledané číslo blíže ke konci pole, protože pole je iterated od konce směrem k začátku, což způsobuje méně položek ke zkoumání.

Kompilátor vynucuje pravidla oboru u ref proměnných: ref místní hodnoty, ref parametry a ref pole v ref struct typech. Pravidla zajišťují, že odkaz nepřežije objekt, na který odkazuje. Viz část věnovaná pravidlu vymezení rozsahu v článku věnovaném parametrům metody.

odkaz a jen pro čtení

Modifikátor readonly lze použít u ref místních proměnných a ref polí. Modifikátor readonly ovlivní výraz napravo. Projděte si následující ukázkové deklarace:

ref readonly int aConstant; // aConstant can't be value-reassigned.
readonly ref int Storage; // Storage can't be ref-reassigned.
readonly ref readonly int CantChange; // CantChange can't be value-reassigned or ref-reassigned.
  • změna přiřazení hodnoty znamená, že hodnota proměnné je znovu přiřazena.
  • Přiřazení odkazu znamená, že proměnná nyní odkazuje na jiný objekt.

Deklarace readonly ref a readonly ref readonly jsou platné pouze pro ref pole v objektu ref struct.

referenční informace s vymezeným oborem

Kontextové klíčové slovo scoped omezuje životnost hodnoty. Modifikátor scoped omezuje životnost ref-safe-to-escape nebo safe-to-escape na aktuální metodu. Přidání modifikátoru scoped v podstatě tvrdí, že váš kód neprodlouží životnost proměnné.

Můžete použít scoped pro parametr nebo místní proměnnou. Modifikátor scoped může být použit pro parametry a místní hodnoty, pokud je typem ref struct. V opačném scoped případě lze modifikátor použít pouze u místních proměnných, které jsou typy odkazů. To zahrnuje místní proměnné deklarované pomocí modifikátoru ref a parametry deklarované pomocí inmodifikátorů , ref nebo out .

Modifikátor scoped je implicitně přidán do this metod deklarovaných v structparametrech , out parametry a ref parametry, pokud je typem ref struct.

Viz také