in – modifikátor parametrů (Referenční příručka jazyka C#)

Klíčové in slovo způsobí, že argumenty budou předány odkazem, ale zajistí, že argument nebude změněn. Z formálního parametru se dělá alias pro argument, který musí být proměnnou. Jinými slovy, jakákoli operace s parametrem se provádí na argumentu . Je to jako klíčová slova ref nebo out s tím rozdílem, že argumenty nelze upravit in v zavolána metodou. Zatímco argumenty mohou být změněny, argumenty musí být upraveny v názvem metody a tyto úpravy ref out jsou pozorovatelné ve volajícím kontextu.

int readonlyArgument = 44;
InArgExample(readonlyArgument);
Console.WriteLine(readonlyArgument);     // value is still 44

void InArgExample(in int number)
{
    // Uncomment the following line to see error CS8331
    //number = 19;
}

Předchozí příklad ukazuje, že modifikátor je obvykle v lokalitě volání in nepotřebný. Vyžaduje se pouze v deklaraci metody.

Poznámka

Klíčové slovo lze také použít s parametrem obecného typu k určení, že parametr typu je kontravariantní, jako součást příkazu nebo jako součást klauzule v in foreach dotazu join LINQ. Další informace o použití klíčového slova v těchto kontextech najdete v tématu v tématu , které in poskytuje odkazy na všechna tato použití.

Proměnné předané in jako argumenty musí být inicializovány před tím, než jsou předány ve volání metody. Volána metoda však nemusí přiřadit hodnotu nebo upravit argument.

inModifikátor parametrů je k dispozici v jazyce C# 7.2 a novějším. Předchozí verze generují chybu kompilátoru (Funkce odkazy jen pro čtení CS8107 není v jazyce C# 7.0 k dispozici. Použijte prosím jazyk verze 7.2 nebo novější.) Informace o konfiguraci verze jazyka kompilátoru najdete v tématu Výběr verze jazyka C#.

Přestože jsou modifikátory parametrů , a považovány za součást podpisu, členy deklarované v jednom typu se nemohou lišit v podpisu in výhradně pomocí , a out ref in ref out . Proto metody nelze přetížit, pokud jediný rozdíl spočívá v tom, že jedna metoda přebírá argument nebo a ref in druhá přebírá out argument. Následující kód se například nezkompiluje:

class CS0663_Example
{
    // Compiler error CS0663: "Cannot define overloaded
    // methods that differ only on in, ref and out".
    public void SampleMethod(in int i) { }
    public void SampleMethod(ref int i) { }
}

Přetížení na základě přítomnosti in je povoleno:

class InOverloads
{
    public void SampleMethod(in int i) { }
    public void SampleMethod(int i) { }
}

Pravidla řešení přetížení

Vysvětlením motivace pro argumenty můžete porozumět pravidlům řešení přetížení pro metody s argumenty podle hodnoty in in a argumentů. Definování metod pomocí in parametrů je potenciální optimalizací výkonu. Některé argumenty typu mohou být velké a při volání metod v úzkách nebo kritických cestách kódu jsou náklady na kopírování těchto struktur struct kritické. Metody deklarují parametry, které určují, že argumenty mohou být bezpečně předány odkazem, protože v volána metoda neupravuje in stav tohoto argumentu. Předáním těchto argumentů odkazem se vyhnete (potenciálně) nákladné kopii.

Zadání in argumentů v lokalitě volání je obvykle volitelné. Neexistuje žádný sémantický rozdíl mezi předáváním argumentů hodnotou a jejich předáním odkazem pomocí in modifikátoru . Modifikátor v lokalitě volání je volitelný, protože není nutné indikovat, že hodnota argumentu může in být změněna. Modifikátor explicitně přidáte do lokality volání, abyste zajistili, že argument bude předán in odkazem, nikoli hodnotou. Explicitní použití in má následující dva účinky:

Nejprve určení v lokalitě volání vynutí kompilátor vybrat metodu definovanou in pomocí odpovídajícího in parametru. V opačném případě, pokud se dvě metody liší pouze za přítomnosti , je lepší shodou přetížení in hodnotou .

Za druhé, zadání in deklaruje váš záměr předat argument odkazem. Argument použitý s in musí představovat umístění, na které lze přímo odkazovat. Platí stejná obecná pravidla pro argumenty a : Nelze použít konstanty, obyčejné vlastnosti ani jiné out ref výrazy, které vytvářejí hodnoty. V opačném případě vynechání v lokalitě volání informuje kompilátor, že mu umožníte vytvořit dočasnou proměnnou, která se předá do metody odkazem jen in pro čtení. Kompilátor vytvoří dočasnou proměnnou, která překoná několik omezení in s argumenty:

  • Dočasná proměnná umožňuje konstanty v době kompilace jako in parametry.
  • Dočasná proměnná umožňuje pro parametry vlastnosti nebo jiné in výrazy.
  • Dočasná proměnná umožňuje argumenty, u kterých existuje implicitní převod z typu argumentu na typ parametru.

Ve všech předchozích instancích kompilátor vytvoří dočasnou proměnnou, která ukládá hodnotu konstanty, vlastnosti nebo jiného výrazu.

Následující kód znázorňuje tato pravidla:

static void Method(in int argument)
{
    // implementation removed
}

Method(5); // OK, temporary variable created.
Method(5L); // CS1503: no implicit conversion from long to int
short s = 0;
Method(s); // OK, temporary int created with the value 0
Method(in s); // CS1503: cannot convert from in short to in int
int i = 42;
Method(i); // passed by readonly reference
Method(in i); // passed by readonly reference, explicitly using `in`

Teď předpokládejme, že je k dispozici jiná metoda využívající argumenty hodnot. Výsledky se změní, jak je znázorněno v následujícím kódu:

static void Method(int argument)
{
    // implementation removed
}

static void Method(in int argument)
{
    // implementation removed
}

Method(5); // Calls overload passed by value
Method(5L); // CS1503: no implicit conversion from long to int
short s = 0;
Method(s); // Calls overload passed by value.
Method(in s); // CS1503: cannot convert from in short to in int
int i = 42;
Method(i); // Calls overload passed by value
Method(in i); // passed by readonly reference, explicitly using `in`

Jediné volání metody, kde je argument předán odkazem, je poslední volání.

Poznámka

Předchozí kód pro zjednodušení int používá jako typ argumentu . Vzhledem k tomu, že ve většině moderních počítačů není větší než odkaz, není předání jediného odkazu jako odkazu int int jen pro čtení přínosné.

Omezení in parametrů

Klíčová slova , a nelze použít in ref pro následující typy out metod:

  • Asynchronní metody, které definujete pomocí modifikátoru async.
  • Metody iterátoru, které zahrnují yield return nebo yield break příkaz.
  • První argument rozšiřující metody nemůže mít in modifikátor, pokud tento argument není struktura.
  • První argument rozšiřující metody, kde je tento argument obecný typ (i v případě, že je tento typ omezen na struktury).

Další informace o modifikátoru a o tom, jak se liší od a najdete v článku in ref o psaní out bezpečného efektivního kódu.

Specifikace jazyka C#

Další informace najdete v tématu Specifikace jazyka C#. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#.