Parametry a modifikátory metody
Ve výchozím nastavení se argumenty v jazyce C# předávají funkcím podle hodnoty. To znamená, že se metodě předá kopie proměnné. Pro typy hodnot (struct
) se do metody předá kopie hodnoty . U typů odkazu (class
) se metodě předá kopie odkazu . Modifikátory parametrů umožňují předávat argumenty odkazem.
Vzhledem k tomu, že struktura je typ hodnoty , metoda přijímá a pracuje s kopií argumentu při předání struktury podle hodnoty metodě. Metoda nemá přístup k původní struktuře ve volající metodě, a proto ji nemůže žádným způsobem změnit. Metoda může změnit pouze kopii.
Instance třídy je odkazový typ , nikoli typ hodnoty. Pokud je typ odkazu předán hodnotou metodě, metoda obdrží kopii odkazu na instanci. Obě proměnné odkazují na stejný objekt. Parametr je kopie odkazu. Volaná metoda nemůže změnit přiřazení instance ve volající metodě. Volaná metoda však může použít kopii odkazu pro přístup k členům instance. Pokud volána metoda změní člen instance, volající metoda také uvidí tyto změny, protože odkazuje na stejnou instanci.
Předání podle hodnoty a předání referencí
Všechny příklady v této části používají následující dva typy record
k ilustraci rozdílů mezi typy class
a typy struct
:
public record struct Point(int X, int Y);
// This doesn't use a primary constructor because the properties implemented for `record` types are
// readonly in record class types. That would prevent the mutations necessary for this example.
public record class Point3D
{
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
}
Výstup následujícího příkladu znázorňuje rozdíl mezi předáním typu struktury podle hodnoty a předáním typu třídy podle hodnoty. Obě metody Mutate
mění hodnoty vlastností argumentu. Pokud je parametr struct
typem, tyto změny se provádějí v kopii dat argumentu. Pokud je parametr typu class
, tyto změny se provádějí v instanci odkazované argumentem:
public class PassTypesByValue
{
public static void Mutate(Point pt)
{
Console.WriteLine($"\tEnter {nameof(Mutate)}:\t\t{pt}");
pt.X = 19;
pt.Y = 23;
Console.WriteLine($"\tExit {nameof(Mutate)}:\t\t{pt}");
}
public static void Mutate(Point3D pt)
{
Console.WriteLine($"\tEnter {nameof(Mutate)}:\t\t{pt}");
pt.X = 19;
pt.Y = 23;
pt.Z = 42;
Console.WriteLine($"\tExit {nameof(Mutate)}:\t\t{pt}");
}
public static void TestPassTypesByValue()
{
Console.WriteLine("===== Value Types =====");
var ptStruct = new Point { X = 1, Y = 2 };
Console.WriteLine($"After initialization:\t\t{ptStruct}");
Mutate(ptStruct);
Console.WriteLine($"After called {nameof(Mutate)}:\t\t{ptStruct}");
Console.WriteLine("===== Reference Types =====");
var ptClass = new Point3D { X = 1, Y = 2, Z = 3 };
Console.WriteLine($"After initialization:\t\t{ptClass}");
Mutate(ptClass);
Console.WriteLine($"After called {nameof(Mutate)}:\t\t{ptClass}");
// Output:
// ===== Value Types =====
// After initialization: Point { X = 1, Y = 2 }
// Enter Mutate: Point { X = 1, Y = 2 }
// Exit Mutate: Point { X = 19, Y = 23 }
// After called Mutate: Point { X = 1, Y = 2 }
// ===== Reference Types =====
// After initialization: Point3D { X = 1, Y = 2, Z = 3 }
// Enter Mutate: Point3D { X = 1, Y = 2, Z = 3 }
// Exit Mutate: Point3D { X = 19, Y = 23, Z = 42 }
// After called Mutate: Point3D { X = 19, Y = 23, Z = 42 }
}
}
Modifikátor ref
je jedním ze způsobů, jak předat argumenty odkazem metodám. Následující kód se řídí předchozím příkladem, ale předává parametry odkazem. Změny typu struct
jsou viditelné v metodě volající, když je struktura předána odkazem. Když je typ odkazu předán odkazem, nedochází k žádné sémantické změně.
public class PassTypesByReference
{
public static void Mutate(ref Point pt)
{
Console.WriteLine($"\tEnter {nameof(Mutate)}:\t\t{pt}");
pt.X = 19;
pt.Y = 23;
Console.WriteLine($"\tExit {nameof(Mutate)}:\t\t{pt}");
}
public static void Mutate(ref Point3D pt)
{
Console.WriteLine($"\tEnter {nameof(Mutate)}:\t\t{pt}");
pt.X = 19;
pt.Y = 23;
pt.Z = 42;
Console.WriteLine($"\tExit {nameof(Mutate)}:\t\t{pt}");
}
public static void TestPassTypesByReference()
{
Console.WriteLine("===== Value Types =====");
var pStruct = new Point { X = 1, Y = 2 };
Console.WriteLine($"After initialization:\t\t{pStruct}");
Mutate(ref pStruct);
Console.WriteLine($"After called {nameof(Mutate)}:\t\t{pStruct}");
Console.WriteLine("===== Reference Types =====");
var pClass = new Point3D { X = 1, Y = 2, Z = 3 };
Console.WriteLine($"After initialization:\t\t{pClass}");
Mutate(ref pClass);
Console.WriteLine($"After called {nameof(Mutate)}:\t\t{pClass}");
// Output:
// ===== Value Types =====
// After initialization: Point { X = 1, Y = 2 }
// Enter Mutate: Point { X = 1, Y = 2 }
// Exit Mutate: Point { X = 19, Y = 23 }
// After called Mutate: Point { X = 19, Y = 23 }
// ===== Reference Types =====
// After initialization: Point3D { X = 1, Y = 2, Z = 3 }
// Enter Mutate: Point3D { X = 1, Y = 2, Z = 3 }
// Exit Mutate: Point3D { X = 19, Y = 23, Z = 42 }
// After called Mutate: Point3D { X = 19, Y = 23, Z = 42 }
}
}
Předchozí příklady upravily vlastnosti parametru. Metoda může také změnit přiřazení parametru k nové hodnotě. Přiřazení se chová odlišně pro typy struktur a typy tříd při předávání podle hodnoty nebo podle odkazu. Následující příklad ukazuje, jak se typy struktur a typy tříd chovají při opětovném přiřazení parametrů předaných hodnotou:
public class PassByValueReassignment
{
public static void Reassign(Point pt)
{
Console.WriteLine($"\tEnter {nameof(Reassign)}:\t\t{pt}");
pt = new Point { X = 13, Y = 29 };
Console.WriteLine($"\tExit {nameof(Reassign)}:\t\t{pt}");
}
public static void Reassign(Point3D pt)
{
Console.WriteLine($"\tEnter {nameof(Reassign)}:\t\t{pt}");
pt = new Point3D { X = 13, Y = 29, Z = -42 };
Console.WriteLine($"\tExit {nameof(Reassign)}:\t\t{pt}");
}
public static void TestPassByValueReassignment()
{
Console.WriteLine("===== Value Types =====");
var ptStruct = new Point { X = 1, Y = 2 };
Console.WriteLine($"After initialization:\t\t{ptStruct}");
Reassign(ptStruct);
Console.WriteLine($"After called {nameof(Reassign)}:\t\t{ptStruct}");
Console.WriteLine("===== Reference Types =====");
var ptClass = new Point3D { X = 1, Y = 2, Z = 3 };
Console.WriteLine($"After initialization:\t\t{ptClass}");
Reassign(ptClass);
Console.WriteLine($"After called {nameof(Reassign)}:\t\t{ptClass}");
// Output:
// ===== Value Types =====
// After initialization: Point { X = 1, Y = 2 }
// Enter Reassign: Point { X = 1, Y = 2 }
// Exit Reassign: Point { X = 13, Y = 29 }
// After called Reassign: Point { X = 1, Y = 2 }
// ===== Reference Types =====
// After initialization: Point3D { X = 1, Y = 2, Z = 3 }
// Enter Reassign: Point3D { X = 1, Y = 2, Z = 3 }
// Exit Reassign: Point3D { X = 13, Y = 29, Z = -42 }
// After called Reassign: Point3D { X = 1, Y = 2, Z = 3 }
}
}
Předchozí ukázka ukazuje, že když přiřadíte parametru novou hodnotu, tato změna není viditelná z volající metody, bez ohledu na to, zda je typ hodnotový nebo odkazový. Následující příklad ukazuje chování při opětovném přiřazení parametru, který byl předán odkazem:
public class PassByReferenceReassignment
{
public static void Reassign(ref Point pt)
{
Console.WriteLine($"\tEnter {nameof(Reassign)}:\t\t{pt}");
pt = new Point { X = 13, Y = 29 };
Console.WriteLine($"\tExit {nameof(Reassign)}:\t\t{pt}");
}
public static void Reassign(ref Point3D pt)
{
Console.WriteLine($"\tEnter {nameof(Reassign)}:\t\t{pt}");
pt = new Point3D { X = 13, Y = 29, Z = -42 };
Console.WriteLine($"\tExit {nameof(Reassign)}:\t\t{pt}");
}
public static void TestPassByReferenceReassignment()
{
Console.WriteLine("===== Value Types =====");
var ptStruct = new Point { X = 1, Y = 2 };
Console.WriteLine($"After initialization:\t\t{ptStruct}");
Reassign(ref ptStruct);
Console.WriteLine($"After called {nameof(Reassign)}:\t\t{ptStruct}");
Console.WriteLine("===== Reference Types =====");
var ptClass = new Point3D { X = 1, Y = 2, Z = 3 };
Console.WriteLine($"After initialization:\t\t{ptClass}");
Reassign(ref ptClass);
Console.WriteLine($"After called {nameof(Reassign)}:\t\t{ptClass}");
// Output:
// ===== Value Types =====
// After initialization: Point { X = 1, Y = 2 }
// Enter Reassign: Point { X = 1, Y = 2 }
// Exit Reassign: Point { X = 13, Y = 29 }
// After called Reassign: Point { X = 13, Y = 29 }
// ===== Reference Types =====
// After initialization: Point3D { X = 1, Y = 2, Z = 3 }
// Enter Reassign: Point3D { X = 1, Y = 2, Z = 3 }
// Exit Reassign: Point3D { X = 13, Y = 29, Z = -42 }
// After called Reassign: Point3D { X = 13, Y = 29, Z = -42 }
}
}
Předchozí příklad ukazuje, jak se v kontextu volání zobrazí změna přiřazení hodnoty parametru předaného odkazem.
Bezpečný kontext odkazů a hodnot
Metody mohou ukládat hodnoty parametrů v polích. Když jsou parametry předány podle hodnoty, to je obvykle bezpečné. Hodnoty se zkopírují a při uložení do pole jsou dostupné odkazové typy. Předání parametrů odkazem vyžaduje, aby kompilátor definoval, kdy je bezpečné přiřadit odkaz na novou proměnnou. Pro každý výraz kompilátor definuje bezpečný kontext , který ohraničuje přístup k výrazu nebo proměnné. Kompilátor používá dva obory: bezpečný kontext a kontext ref-safe.
- Bezpečný kontext definuje obor, kde se dá bezpečně přistupovat k libovolnému výrazu.
- Kontext ref-safe definuje obor, kde lze bezpečně přistupovat k libovolnému výrazu nebo ho upravit.
Neformálně si tyto obory můžete představit jako mechanismus, který zajistí, že váš kód nikdy nebude přistupovat k odkazu nebo ho nebude modifikovat. Odkaz je platný, pokud odkazuje na platný objekt nebo strukturu. Bezpečný kontext definuje, kdy lze proměnnou přiřadit nebo znovu přiřadit. Kontext ref-safe definuje, kdy lze proměnnou přiřadit odkaz nebo znovu přiřadit odkaz. Přiřazení přiřadí proměnnou nové hodnotě; Přiřazení odkazu přiřadí proměnnou, která odkazuje na jiné umístění úložiště.
Parametry odkazu
Pro deklaraci parametru použijete jeden z následujících modifikátorů, který předá argumenty odkazem místo hodnoty:
-
ref
: Argument musí být inicializován před voláním metody. Metoda může parametru přiřadit novou hodnotu, ale není k tomu nutná. -
out
: Volající metoda není nutná k inicializaci argumentu před voláním metody. Metoda musí přiřadit hodnotu parametru. -
ref readonly
: Argument musí být inicializován před voláním metody. Metoda nemůže k parametru přiřadit novou hodnotu. -
in
: Argument musí být inicializován před voláním metody. Metoda nemůže k parametru přiřadit novou hodnotu. Kompilátor může vytvořit dočasnou proměnnou pro uložení kopie argumentu nain
parametry.
Parametr předaný odkazem je referenční proměnná. Nemá vlastní hodnotu. Místo toho odkazuje na jinou proměnnou, která se nazývá její referenční. Referenční proměnné mohou být ref přiřazeny, což změní jejich předmět.
Členové třídy nemohou mít podpisy, které se liší pouze pomocí ref
, ref readonly
, in
nebo out
. K chybě kompilátoru dochází v případě, že jediný rozdíl mezi dvěma členy typu je, že jeden z nich má ref
parametr a druhý má out
parametr , ref readonly
nebo in
parametr. Metody však mohou být přetíženy, pokud jedna metoda má ref
, ref readonly
, in
, nebo out
parametr a druhý má parametr, který je předán hodnotou, jak je znázorněno v následujícím příkladu. V jiných situacích, které vyžadují porovnávání podpisů, jako je skrytí nebo přepsání, in
ref
, ref readonly
a out
jsou součástí podpisu a vzájemně se neshodují.
Pokud má parametr jeden z předchozích modifikátorů, může mít odpovídající argument kompatibilní modifikátor:
- Argument parametru
ref
ref
musí obsahovat modifikátor. - Argument parametru
out
out
musí obsahovat modifikátor. - Argument parametru
in
může volitelně obsahovatin
modifikátor.ref
Pokud je modifikátor použit v argumentu místo toho, kompilátor vydá upozornění. - Argument parametru
ref readonly
by měl obsahovat buďin
ref
modifikátory, ale ne obojí. Pokud není zahrnut ani jeden modifikátor, kompilátor vydá upozornění.
Když použijete tyto modifikátory, popisují způsob použití argumentu:
-
ref
znamená, že metoda může číst nebo zapisovat hodnotu argumentu. -
out
znamená, že metoda nastaví hodnotu argumentu. -
ref readonly
znamená, že metoda čte, ale nemůže zapsat hodnotu argumentu. Argument by měl být předán odkazem. -
in
znamená, že metoda čte, ale nemůže zapsat hodnotu argumentu. Argument bude předán odkazem nebo dočasnou proměnnou.
V následujících typech metod nemůžete použít předchozí modifikátory parametrů:
- Asynchronní metody, které definujete pomocí modifikátoru async
- Metody iterátoru , které zahrnují výnosové vrácení nebo
yield break
příkaz.
Metody rozšíření mají také omezení použití těchto klíčových slov argumentu:
- Klíčové
out
slovo nelze použít u prvního argumentu metody rozšíření. - Klíčové
ref
slovo nelze použít u prvního argumentu metody rozšíření, pokud argument nenístruct
, nebo obecný typ není omezen na strukturu. - Klíčová
ref readonly
slova ain
klíčová slova nelze použít, pokud není prvním argumentemstruct
. - Klíčová
ref readonly
slova ain
klíčová slova nelze použít u žádného obecného typu, i když je omezena na strukturu.
Vlastnosti nejsou proměnné. Jsou to metody. Vlastnosti nemohou být argumenty parametrů ref
.
ref
modifikátor parametrů
Pokud chcete použít ref
parametr, musí definice metody i volající metoda explicitně použít ref
klíčové slovo, jak je znázorněno v následujícím příkladu. (Kromě toho, že volající metoda může vynechat ref
při volání COM.)
void Method(ref int refArgument)
{
refArgument = refArgument + 44;
}
int number = 1;
Method(ref number);
Console.WriteLine(number);
// Output: 45
Před předáním argumentu parametru ref
musí být inicializován.
out
modifikátor parametrů
Pokud chcete použít out
parametr, musí definice metody i volající metoda explicitně použít out
klíčové slovo. Příklad:
int initializeInMethod;
OutArgExample(out initializeInMethod);
Console.WriteLine(initializeInMethod); // value is now 44
void OutArgExample(out int number)
{
number = 44;
}
Proměnné předané jako out
argumenty nemusí být inicializovány před předáním volání metody. Volaná metoda je však nutná k přiřazení hodnoty před vrácením metody.
Dekonstrukční metody deklarují své parametry pomocí modifikátoru out
pro vrácení více hodnot. Jiné metody mohou vrátit řazené kolekce členů hodnot pro více vrácených hodnot.
Před předáním proměnné jako argumentu můžete deklarovat proměnnou v samostatném out
příkazu. Můžete také deklarovat out
proměnnou v seznamu argumentů volání metody, nikoli v samostatné deklaraci proměnné.
out
Deklarace proměnných vytvářejí kompaktnější, čitelný kód a také vám brání neúmyslně přiřazovat hodnotu proměnné před voláním metody. Následující příklad definuje proměnnou number
ve volání Int32.TryParse metoda.
string numberAsString = "1640";
if (Int32.TryParse(numberAsString, out int number))
Console.WriteLine($"Converted '{numberAsString}' to {number}");
else
Console.WriteLine($"Unable to convert '{numberAsString}'");
// The example displays the following output:
// Converted '1640' to 1640
Můžete také deklarovat implicitně zatypovanou místní proměnnou.
ref readonly
modifikátor
ref readonly
Modifikátor musí být obsažen v deklaraci metody. Modifikátor v lokalitě volání je volitelný.
in
Lze použít buď modifikátor, nebo ref
modifikátor.
ref readonly
Modifikátor není platný na webu volání. Který modifikátor, který použijete na webu volání, může pomoct popsat charakteristiky argumentu. Můžete použít ref
pouze v případě, že je argument proměnnou a je zapisovatelný. Argument lze použít in
pouze v případech, kdy je argument proměnnou. Může být zapisovatelný nebo jen pro čtení. Pokud argument není proměnnou, nemůžete přidat ani modifikátor, ale jedná se o výraz. Následující příklady ukazují tyto podmínky. Následující metoda používá ref readonly
modifikátor k označení, že velká struktura by měla být předána odkazem z důvodů výkonu:
public static void ForceByRef(ref readonly OptionStruct thing)
{
// elided
}
Metodu můžete volat pomocí nebo ref
modifikátoruin
. Pokud modifikátor vynecháte, kompilátor vydá upozornění. Pokud je argument výrazem, nikoli proměnnou, nemůžete přidat in
ani ref
modifikátory, takže byste měli potlačit upozornění:
ForceByRef(in options);
ForceByRef(ref options);
ForceByRef(options); // Warning! variable should be passed with `ref` or `in`
ForceByRef(new OptionStruct()); // Warning, but an expression, so no variable to reference
Pokud je proměnná proměnná proměnná readonly
, musíte použít in
modifikátor. Kompilátor vydá chybu, pokud místo toho použijete ref
modifikátor.
ref readonly
Modifikátor označuje, že metoda očekává, že argument bude proměnnou, nikoli výraz, který není proměnnou. Příklady výrazů, které nejsou proměnnými, jsou konstanty, návratové hodnoty metody a vlastnosti. Pokud argument není proměnná, kompilátor vydá upozornění.
in
modifikátor parametrů
in
Modifikátor je vyžadován v deklaraci metody, ale nepotřebné v lokalitě volání.
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;
}
in
Modifikátor umožňuje kompilátoru vytvořit dočasnou proměnnou argumentu a předat do argumentu jen pro čtení odkaz. Kompilátor vždy vytvoří dočasnou proměnnou, pokud je nutné argument převést, pokud existuje implicitní převod z typu argumentu nebo pokud je argument hodnotou, která není proměnnou. Například pokud je argument literálovou hodnotou nebo hodnota vrácená z přístupového objektu vlastnosti. Pokud vaše rozhraní API vyžaduje předání argumentu odkazem, zvolte ref readonly
místo modifikátoru in
modifikátor.
Metody definované pomocí in
parametrů potenciálně získávají optimalizaci výkonu. Některé struct
argumenty typu můžou být velké a když se metody volají v těsné smyčce nebo kritické cesty kódu, náklady na kopírování těchto struktur jsou podstatné. Metody deklarují in
parametry, které určují, že argumenty lze bezpečně předat odkazem, protože volaná metoda neupravuje stav tohoto argumentu. Předání těchto argumentů odkazem zabrání (potenciálně) nákladné kopii. Modifikátor explicitně přidáte in
na web volání, abyste zajistili, že argument bude předán odkazem, nikoli hodnotou. Explicitní použití in
má následující dva efekty:
- Zadání
in
v lokalitě volání vynutí kompilátor vybrat metodu definovanou s odpovídajícímin
parametrem. V opačném případě, pokud se dvě metody liší pouze v přítomnostiin
, podle přetížení hodnoty je lepší shoda. - Zadáním deklarujete
in
svůj záměr předat argument odkazem. Argument použitý sin
musí představovat umístění, na které lze přímo odkazovat. Platí stejná obecná pravidla aout
ref
argumenty: Nemůžete použít konstanty, běžné vlastnosti ani jiné výrazy, které vytvářejí hodnoty. Jinak vynecháníin
v lokalitě volání informuje kompilátor, že je v pořádku vytvořit dočasnou proměnnou, která bude předávat odkazem jen pro čtení do metody. Kompilátor vytvoří dočasnou proměnnou pro překonání několika omezení pomocíin
argumentů:- Dočasná proměnná umožňuje konstanty v době kompilace jako
in
parametry. - Dočasná proměnná umožňuje pro parametry vlastnosti nebo jiné výrazy
in
. - Dočasná proměnná umožňuje argumenty, ve kterých je implicitní převod typu argumentu na typ parametru.
- Dočasná proměnná umožňuje konstanty v době kompilace jako
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 ilustruje 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`
Předpokládejme, že byla k dispozici jiná metoda používající argumenty podle hodnoty. 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ým voláním metody, kde je argument předán odkazem, je poslední volání.
Poznámka:
Předchozí kód se používá int
jako typ argumentu pro jednoduchost. Vzhledem k tomu int
, že není větší než odkaz ve většině moderních počítačů, neexistuje žádný přínos předání jediného int
odkazu jako odkazu jen pro čtení.
params
modifikátor
Za klíčovým slovem v deklaraci metody nejsou povoleny params
žádné další parametry a v deklaraci metody je povoleno pouze jedno params
klíčové slovo.
Deklarovaný typ parametru params
musí být typ kolekce. Rozpoznané typy kolekcí jsou:
- Jednorozměrný typ
T[]
pole , v takovém případě typ prvku jeT
. - Typ rozsahu:
System.Span<T>
System.ReadOnlySpan<T>
Zde je typT
prvku .
- Typ s přístupnou metodou create s odpovídajícím typem elementu. Metoda create je identifikována pomocí stejného atributu, který se používá pro výrazy kolekce.
- Struktura System.Collections.Generic.IEnumerable<T>
- Typ má konstruktor, který lze vyvolat bez argumentů a konstruktor je alespoň tak přístupný jako deklarující člen.
-
Typ má instanci (nikoli rozšiřující) metodu
Add
, kde:- Metodu lze vyvolat pomocí argumentu s jednou hodnotou.
- Pokud je metoda obecná, argumenty typu lze odvodit z argumentu.
- Metoda je alespoň tak přístupná jako deklarující člen. Typ elementu je typ iteracetypu.
- Typ rozhraní:
Před jazykem C# 13 musí být parametr jednorozměrným polem.
Při volání metody s parametrem params
můžete předat:
- Čárkami oddělený seznam argumentů typu prvků pole.
- Kolekce argumentů zadaného typu.
- Žádné argumenty. Pokud neodešlete žádné argumenty, délka
params
seznamu je nula.
Následující příklad ukazuje různé způsoby, jak lze argumenty odeslat do parametru params
.
public static void ParamsModifierExample(params int[] list)
{
for (int i = 0; i < list.Length; i++)
{
System.Console.Write(list[i] + " ");
}
System.Console.WriteLine();
}
public static void ParamsModifierObjectExample(params object[] list)
{
for (int i = 0; i < list.Length; i++)
{
System.Console.Write(list[i] + " ");
}
System.Console.WriteLine();
}
public static void TryParamsCalls()
{
// You can send a comma-separated list of arguments of the
// specified type.
ParamsModifierExample(1, 2, 3, 4);
ParamsModifierObjectExample(1, 'a', "test");
// A params parameter accepts zero or more arguments.
// The following calling statement displays only a blank line.
ParamsModifierObjectExample();
// An array argument can be passed, as long as the array
// type matches the parameter type of the method being called.
int[] myIntArray = { 5, 6, 7, 8, 9 };
ParamsModifierExample(myIntArray);
object[] myObjArray = { 2, 'b', "test", "again" };
ParamsModifierObjectExample(myObjArray);
// The following call causes a compiler error because the object
// array cannot be converted into an integer array.
//ParamsModifierExample(myObjArray);
// The following call does not cause an error, but the entire
// integer array becomes the first element of the params array.
ParamsModifierObjectExample(myIntArray);
}
/*
Output:
1 2 3 4
1 a test
5 6 7 8 9
2 b test again
System.Int32[]
*/
Řešení přetížení může způsobit nejednoznačnost, pokud je argument parametru params
typem kolekce. Typ kolekce argumentu musí být konvertibilní na typ kolekce parametru. Pokud různé přetížení poskytují lepší převody pro tento parametr, může být tato metoda lepší. Pokud je však argument parametru params
buď diskrétní prvky, nebo chybí, jsou všechna přetížení s různými params
typy parametrů stejná pro tento parametr.
Další informace najdete v části Seznam argumentů ve Specifikaci jazyka C#. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#.