Sdílet prostřednictvím


parametry ref readonly

Poznámka

Tento článek je specifikace funkce. Specifikace slouží jako návrhový dokument pro funkci. Zahrnuje navrhované změny specifikace spolu s informacemi potřebnými při návrhu a vývoji funkce. Tyto články se publikují, dokud nebudou navrhované změny specifikace finalizovány a začleněny do aktuální specifikace ECMA.

Mezi specifikací funkce a dokončenou implementací může docházet k nějakým nesrovnalostem. Tyto rozdíly jsou zachyceny v příslušných poznámkách ze schůzky návrhu jazyka (LDM) .

Další informace o procesu přijetí specifikací funkcí do jazyka C# najdete v článku o specifikacích .

Problém šampiona: https://github.com/dotnet/csharplang/issues/6010

Shrnutí

Povolte modifikátor místa deklarace parametrů ref readonly a změňte pravidla volání takto:

Poznámky k volání parametr ref parametr ref readonly parametr in parametr out
ref Povoleno povolené upozornění Chyba
in Chyba povolené Povoleno Chyba
out Chyba Chyba Chyba Povoleno
Žádná poznámka Chyba upozornění Povoleno Chyba

(Všimněte si, že existuje jedna změna stávajících pravidel: parametr in s anotací místa volání ref generuje upozornění místo chyby.)

Změňte pravidla hodnot argumentu následujícím způsobem:

Druh hodnoty parametr ref parametr ref readonly parametr in parametr out
rvalue Chyba upozornění Povoleno Chyba
lvalue Povoleno povolené Povoleno Povoleno

Pokud hodnota lvalue znamená proměnnou (tj. hodnotu s umístěním; nemusí být zapisovatelná/přiřaditelná) a hodnota rvalue znamená jakýkoli druh hodnoty.

Motivace

C# 7.2 zavedl in parametry jako způsob předávání odkazů jen pro čtení. in parametr umožňuje hodnoty lvalue i rvalue a lze jej použít bez jakékoli poznámky při volání. Rozhraní API, která zaznamenávají nebo vracejí odkazy ze svých parametrů, by však ráda zakázala hodnoty rvalue a také prosadila nějaké označení na místě volání, že je zachycen odkaz. ref readonly parametry jsou ideální v takových případech, protože varují, pokud se používají s r-hodnotami nebo bez jakékoli poznámky v místě volání.

Kromě toho existují rozhraní API, která potřebují pouze odkazy pro čtení, ale používají tyto odkazy.

  • ref parametry, protože byly zavedeny dříve, než byly in dostupné a změna na in by znamenala zásadní změnu zdrojového i binárního kódu, například QueryInterfacenebo
  • cs-CZ: in parametry pro přijímání referenčních odkazů pouze pro čtení, i když předávání r-hodnot do nich ve skutečnosti není logické, například ReadOnlySpan<T>..ctor(in T value), nebo
  • ref parametry k zakázání rvalues, i když nemodifikují předanou referenci, například Unsafe.IsNullRef.

Tato rozhraní API by mohla migrovat na parametry ref readonly, aniž by přerušila fungování pro uživatele. Podrobnosti o binární kompatibilitě najdete v navrhovaném kódování metadat . Konkrétně změna

  • refref readonly by znamenala pouze binární nekompatibilitu pro virtuální metody.
  • refin by také byla binární zlomová změna virtuálních metod, ale ne zdrojová zlomová změna, protože pravidla se změní, aby varovala pouze na ref argumenty předané parametrům in.
  • inref readonly by nebyla změna narušující kompatibilitu (ale žádné poznámky na místě volání ani rvalue by nevedly k upozornění).
    • Všimněte si, že by to byla změna vedoucí k chybě kompatibility pro uživatele používající starší verze kompilátoru (protože interpretují parametry ref readonly jako parametry ref, což neumožňuje použití in nebo žádné anotace na volajícím místě) a pro nové verze kompilátoru s LangVersion <= 11 (pro zachování konzistence se staršími verzemi kompilátoru bude vydána chyba, že parametry ref readonly nejsou podporovány, pokud nebudou předány odpovídající argumenty s modifikátorem ref).

V opačném směru se mění

  • ref readonlyref by mohlo dojít ke změně narušující zdrojový kód (pokud byla použita pouze anotace volání ref a jako argumenty byly používány jen odkazy vyhrazené pro čtení) a binární změna narušující kompatibilitu pro virtuální metody,
  • ref readonlyin by nebyla zásadní změna (ale anotace místa volání ref by vedla k upozornění).

Všimněte si, že výše uvedená pravidla platí pro podpisy metod, ale ne pro podpisy delegátů. Změna ref na in v podpisu delegáta může být například změna způsobující chybu zdroje (pokud uživatel přiřazuje metodu s parametrem ref danému typu delegáta, stane se po změně rozhraní API chybou).

Podrobný návrh

Obecně platí, že pravidla pro parametry ref readonly jsou stejná jako pro parametry in v jejich návrhus výjimkou případů, kdy se explicitně změnily v tomto návrhu.

Deklarace parametrů

Nejsou potřeba žádné změny gramatiky. Modifikátor ref readonly bude pro parametry povolen. Kromě normálních metod budou ref readonly povoleny pro parametry indexeru (například in, ale na rozdíl od ref), ale nepovolené pro parametry operátoru (například ref, ale na rozdíl od in).

Výchozí hodnoty parametrů budou povoleny pro parametry ref readonly s upozorněním, protože jsou ekvivalentní předávání hodnot rvalue. To umožňuje autorům rozhraní API změnit parametry in s výchozími hodnotami na ref readonly parametry bez zavedení změny způsobující chybu zdroje.

Kontroly typu hodnoty

Všimněte si, že i když je modifikátor argumentu ref povolený pro parametry ref readonly, nic se nezmění, pokud jde o kontroly typu hodnoty, tj.

  • ref lze použít pouze s přiřaditelnými hodnotami;
  • pro předávání odkazů jen pro čtení, jeden musí místo toho použít modifikátor argumentu in;
  • pro předávání hodnot rvalue nemusíte použít žádný modifikátor (což vede k upozornění na parametry ref readonly, jak je popsáno v souhrnu tohoto návrhu).

Rozlišení přetížení

Rozlišení přetížení umožní kombinovat ref/ref readonly/inbez volání poznámek a modifikátory parametrů, které jsou označeny tabulkou v souhrnu tohoto návrhu, tj. všechny povolené a varování případy budou během řešení přetížení považovány za možné kandidáty. Konkrétně se jedná o změnu stávajícího chování, kdy metody s parametrem in budou odpovídat voláním s odpovídajícím argumentem označeným jako ref— tato změna bude řízena verzí jazyka.

Upozornění pro předání argumentu bez modifikátoru volání do parametru ref readonly se však potlačí, pokud parametr je

  • příjemce při vyvolání metody rozšíření,
  • používá se implicitně jako součást inicializátoru vlastní kolekce nebo zpracování interpolovaných řetězců.

Přetížení podle hodnoty budou upřednostňována před přetížením ref readonly v případě, že není přítomen žádný modifikátor argumentu (in parametry mají stejné chování).

Převody metod

Podobně pro účely anonymní funkce [§10.7] a skupiny metod [§10.8] převody jsou tyto modifikátory považovány za kompatibilní (ale jakákoli povolená konverze mezi různými modifikátory vede k upozornění):

  • ref readonly parametr cílové metody může odpovídat parametru in nebo ref delegáta,
  • in parametr cílové metody může odpovídat ref readonly nebo, pokud to dovoluje verze jazyka, ref parametru delegáta.
  • Poznámka: ref parametr cílové metody není povoleno shodovat in ani ref readonly parametr delegáta.

Například:

DIn dIn = (ref int p) => { }; // error: cannot match `ref` to `in`
DRef dRef = (in int p) => { }; // warning: mismatch between `in` and `ref`
DRR dRR = (ref int p) => { }; // error: cannot match `ref` to `ref readonly`
dRR = (in int p) => { }; // warning: mismatch between `in` and `ref readonly`
dIn = (ref readonly int p) => { }; // warning: mismatch between `ref readonly` and `in`
dRef = (ref readonly int p) => { }; // warning: mismatch between `ref readonly` and `ref`
delegate void DIn(in int p);
delegate void DRef(ref int p);
delegate void DRR(ref readonly int p);

Všimněte si, že nedošlo ke změně v chování při převodech ukazatelů funkce . Připomeňme si, že implicitní konverze ukazatelů na funkce jsou zakázány, pokud dojde k neshodě mezi modifikátory typu reference, a explicitní přetypy jsou vždy povoleny bez upozornění.

Porovnávání podpisů

Členy deklarované v jednom typu se nemohou lišit pouze v podpisu ref/out/in/ref readonly. Pro jiné účely porovnávání podpisů (např. skrytí nebo přepsání) lze ref readonly zaměnit s modifikátorem in, ale výsledkem je upozornění na místě deklarace [§7.6]. To neplatí při porovnávání deklarace partial s implementací a při porovnávání signatury zachytávače s zachycenou signaturou. Všimněte si, že nedochází ke změnám v přepisu pro páry modifikátorů ref/in a ref readonly/ref; nelze je zaměnit, protože podpisy nejsou binárně kompatibilní. Pro konzistenci platí totéž pro jiné účely porovnávání podpisů (např. skrytí).

Kódování metadat

Jako připomenutí

  • ref parametry jsou emitovány jako prosté typy byref (T& v IL),
  • in parametry jsou jako ref a navíc jsou opatřeny poznámkami System.Runtime.CompilerServices.IsReadOnlyAttribute. V C# 7.3 a novějších verzích jsou také vytvářeny s [in] a pokud jsou virtuální, s modreq(System.Runtime.InteropServices.InAttribute).

ref readonly parametry budou vydány jako [in] T&a budou dále opatřeny následujícím atributem:

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
    public sealed class RequiresLocationAttribute : Attribute
    {
    }
}

Navíc, pokud jsou virtuální, budou emitovány s modreq(System.Runtime.InteropServices.InAttribute), aby se zajistila binární kompatibilita s parametry in. Všimněte si, že na rozdíl od parametrů in se pro [IsReadOnly] parametry nevygenerují žádné ref readonly, aby nedocházelo ke zvýšení velikosti metadat a také aby starší verze kompilátoru interpretovala parametry ref readonly jako parametry ref (a proto refref readonly nebude zásadní změnou zdroje ani mezi různými verzemi kompilátoru).

RequiresLocationAttribute se bude shodovat s názvem kvalifikovaným oborem názvů a syntetizován kompilátorem, pokud ještě není součástí kompilace.

Zadání atributu ve zdroji bude chybou, pokud se použije u parametru, podobně jako u ParamArrayAttribute.

Ukazatele na funkce

Ve funkčních ukazatelích se parametry in vysílají pomocí modreq(System.Runtime.InteropServices.InAttribute) (viz návrh funkčních ukazatelů). Parametry ref readonly budou vydávány bez této modreq, ale s modopt(System.Runtime.CompilerServices.RequiresLocationAttribute). Starší verze kompilátoru budou ignorovat modopt, a proto interpretuji parametry ref readonly jako parametry ref (v souladu se starším chováním kompilátoru pro normální metody s parametry ref readonly, jak je popsáno výše). Nové verze kompilátoru, které jsou si vědomy modopt, budou využívat tuto informaci k rozeznávání ref readonly parametrů, což povede ke generování upozornění během konverzí a vyvolání . Pro zachování konzistence se staršími verzemi kompilátoru budou nové verze kompilátoru s LangVersion <= 11 hlásit chyby, že parametry ref readonly nejsou podporovány, pokud nejsou předány odpovídající argumenty s modifikátorem ref.

Všimněte si, že změna modifikátorů v signaturách ukazatelů na funkce, pokud jsou součástí veřejných API, představuje binární zlom, a proto se jedná o binární zlom při změně ref nebo in na ref readonly. K přerušení zdroje dojde pouze u volajících s LangVersion <= 11 při změně inref readonly (pokud vyvoláte ukazatel s modifikátorem in volání), což je v souladu s běžnými metodami.

Zásadní změny

Redukce nesouladu ref/in v řešení přetížení představuje změnu narušující chování, jak ukazuje následující příklad:

class C
{
    string M(in int i) => "C";
    static void Main()
    {
        int i = 5;
        System.Console.Write(new C().M(ref i));
    }
}
static class E
{
    public static string M(this C c, ref int i) => "E";
}

V jazyce C# 11 se volání sváže s E.M, a proto se vytiskne "E". V jazyce C# 12 je C.M umožněno svázat (s upozorněním) a nejsou prohledány žádné obory rozšíření, protože máme vhodného kandidáta, a proto se vytiskne "C".

Existuje také změna způsobující chybu zdroje z důvodu stejného důvodu. Následující příklad zobrazí "1" v jazyce C# 11, ale nelze zkompilovat kvůli chybě nejednoznačnosti v jazyce C# 12.

var i = 5;
System.Console.Write(C.M(null, ref i));

interface I1 { }
interface I2 { }
static class C
{
    public static string M(I1 o, ref int x) => "1";
    public static string M(I2 o, in int x) => "2";
}

Výše uvedené příklady ukazují přerušení při volání metod, ale vzhledem k tomu, že jsou způsobeny změnami v rozlišení přetíženého vyhodnocování, mohou být podobně vyvolány pro převody metod.

Alternativy

deklarace parametrů

Autoři rozhraní API mohou označit parametry in, které jsou určeny pouze k přijímání lvalue, pomocí vlastního atributu a poskytnout analyzátor, jenž označuje nesprávné použití. To by autorům rozhraní API neumožňovalo měnit podpisy existujících rozhraní API, která se přihlásila k použití parametrů ref k zakázání hodnot rvalue. Volající takových rozhraní API by stále museli provádět další práci, aby získali ref, pokud mají přístup pouze k proměnné ref readonly. Změna těchto rozhraní API z ref na [RequiresLocation] in by přinesla nekompatibilitu se zdrojovým kódem (a v případě virtuálních metod také binární nekompatibilitu).

Místo povolení modifikátoru ref readonlymůže kompilátor rozpoznat, kdy se na parametr použije speciální atribut (například [RequiresLocation]). Bylo diskutováno v LDM 2022-04-25, rozhodnuto, že se jedná o jazykovou funkci, ne analyzátor, takže by měla vypadat jako taková.

kontroly typů hodnot

Předávání hodnot lvalue bez jakýchkoli modifikátorů do ref readonly parametrů může být povoleno bez jakýchkoli upozornění, podobně jako implicitní parametry C++. To bylo diskutováno v LDM 2022-05-11, přičemž bylo poznamenáno, že primární motivací pro parametry ref readonly jsou rozhraní API, která zachycují nebo vracejí odkazy z těchto parametrů, takže nějaký druh indikátoru je dobrá věc.

Předání rvalue do ref readonly může být spíše chybou než upozorněním. To bylo původně přijato v LDM 2022-04-25, ale pozdější e-mailové diskuze zmírnily tuto pozici, protože bychom ztratili možnost měnit stávající API bez narušení uživatelského prostředí.

in může být "přirozeným" modifikátorem volání pro parametry ref readonly a použití ref může vést k upozorněním. Tím zajistíte konzistentní styl kódu a zviditelníte, že odkaz je jen pro čtení (na rozdíl od ref). Původně byl přijat v LDM 2022-04-25. Upozornění ale můžou být sporné body pro autory rozhraní API, aby přešli z ref na ref readonly. Také in byl předefinován jako ref readonly + praktické funkce, a proto byl v LDM 2022-05-11odmítnut.

Čeká na přezkoumání LDM

V jazyce C# 12 nebyla implementována žádná z následujících možností. Návrhy zůstávají potenciální.

deklarace parametrů

Je možné povolit inverzní řazení modifikátorů (readonly ref místo ref readonly). To by bylo nekonzistentní s tím, jak se readonly ref vrací a jak se pole chovají (inverzní řazení je zakázáno nebo znamená něco jiného) a mohlo by kolidovat s parametry určenými pouze ke čtení, pokud by byly v budoucnu implementovány.

Výchozí hodnoty parametrů mohou být chybou pro parametry ref readonly.

kontroly typů hodnot

Chyby mohou být generovány místo upozornění při předávání rhodnot do ref readonly parametrů nebo při neshodě poznámek na místě volání a modifikátorů parametrů. Podobně lze místo atributu použít speciální modreq, aby se zajistilo, že parametry ref readonly se liší od parametrů in na binární úrovni. To by poskytovalo silnější záruky, takže by bylo vhodné pro nová rozhraní API, ale zabránit přijetí ve stávajících rozhraních API modulu runtime, která nemohou zavádět zásadní změny.

Kontroly druhu hodnoty mohou být zmírněny, aby bylo možné předávat reference pouze pro čtení prostřednictvím ref do parametrů in/ref readonly. To by bylo podobné tomu, jak dnes fungují přiřazení a vracení odkazů – také umožňují předávání odkazů jako pouze pro čtení prostřednictvím modifikátoru ref ve zdrojovém výrazu. Nicméně, ref je obvykle blízko místa, kde cíl je deklarován jako ref readonly, takže je jasné, že předáváme odkaz jako jen pro čtení, na rozdíl od vyvolání, jejichž argument a modifikátory parametrů jsou obvykle daleko od sebe. Kromě toho umožňují pouze modifikátoru ref na rozdíl od argumentů, které umožňují také in, a proto in a ref budou zaměnitelné pro argumenty nebo in budou prakticky zastaralé, pokud by uživatelé chtěli svůj kód konzistentně použít (pravděpodobně by používali ref všude, protože je to jediný modifikátor povolený pro přiřazení ref a vrácení odkazu).

rozlišení přetížení

Rozlišení přetížení, přepsání a převod by mohly zakázat záměnnost modifikátorů ref readonly a in.

Změna rozlišení přetížení pro existující in parametry by mohla být provedena bezpodmínečně (bez ohledu na LangVersion), ale to by byla zásadní změna.

Vyvolání metody rozšíření s příjemcem ref readonly může vést k upozornění „Argument 1 by se měl předat s klíčovým slovem ref nebo in“, podobně jako by tomu bylo u vyvolání bez rozšíření bez modifikátorů volajících. Uživatel může toto upozornění opravit tím, že změní vyvolání metody rozšíření na vyvolání statické metody. Stejné upozornění může být hlášeno při použití vlastní inicializátoru kolekce nebo interpolované obslužné rutiny řetězců s parametrem ref readonly, i když uživatel ho nemohl obejít.

ref readonly přetížení lze upřednostňovat před přetíženími podle hodnoty, pokud neexistuje žádný modifikátor volání nebo může dojít k nejednoznačnosti chyby.

Převody metod

Mohli bychom povolit, aby parametr ref cílové metody odpovídal in a ref readonly parametr delegáta. To by autorům rozhraní API umožnilo změnit například ref na in v podpisech delegátů bez narušení uživatelů (konzistentně s povolenými podpisy normální metody). Výsledkem by však bylo také následující porušení readonly záruk s pouhým upozorněním:

class Program
{
    static readonly int f = 123;
    static void Main()
    {
        var d = (in int x) => { };
        d = (ref int x) => { x = 42; }; // warning: mismatch between `ref` and `in`
        d(f); // changes value of `f` even though it is `readonly`!
        System.Console.WriteLine(f); // prints 42
    }
}

Převody ukazatelů funkce by mohly upozornit na neshodu ref readonly/ref/in, ale pokud bychom chtěli, aby to bylo vázáno na verzi jazyka LangVersion, vyžadovala by se značná investice do implementace, protože převody typů dnes nevyžadují přístup k procesu kompilace. I když je neshoda v současné době chybou, uživatelům je navíc snadné přidat přetypování, aby v případě potřeby povolili neshodu.

kódování metadat

Zadání RequiresLocationAttribute ve zdroji může být povoleno podobně jako atributy In a Out. Alternativně to může být chyba při použití v jiných kontextech než jen parametry, podobně jako atribut IsReadOnly; aby se zachoval další prostor pro návrh.

Ukazatel funkce ref readonly parametry mohou být generovány různými kombinacemi modopt/modreq (všimněte si, že "konec zdroje" v této tabulce znamená pro volající s LangVersion <= 11):

Modifikátory Lze rozpoznat napříč kompilacemi. Staré kompilátory je vidí jako refref readonly inref readonly
modreq(In) modopt(RequiresLocation) Ano in binární soubor, konec zdroje binární přerušení
modreq(In) Ne in binární soubor, konec zdroje Ok
modreq(RequiresLocation) Ano nepodporovaný binární soubor, konec zdroje binární soubor, konec zdroje
modopt(RequiresLocation) Ano ref binární přerušení binární soubor, konec zdroje

Pro parametry [RequiresLocation] bychom mohli vygenerovat atributy [IsReadOnly] i ref readonly. Pak inref readonly by nebyla zásadní změnou ani pro starší verze kompilátoru, ale refref readonly by se stala zásadní změnou zdroje pro starší verze kompilátoru (protože by interpretovaly ref readonly jako in, nepovolovaly ref modifikátory) a nové verze kompilátoru s LangVersion <= 11 (pro konzistenci).

Chování pro LangVersion <= 11 se může lišit od chování starších verzí kompilátoru. Například by to mohla být chyba při každém volání parametru ref readonly (i při použití modifikátoru ref na místě volání), nebo by to mohlo být vždy povoleno bez chyb.

Zásadní změny

Tento návrh doporučuje přijetí změny, která porušuje chování, protože by měla být vzácná, je řízena verzí jazyka LangVersion a uživatelé ji mohou obejít explicitním voláním metody rozšíření. Místo toho bychom ho mohli zmírnit

  • zakázání neshody ref/in (to by zabránilo migraci pouze na in pro stará rozhraní API, která používala ref, protože in ještě nebyla dostupná)
  • úprava pravidel řešení přetížení tak, aby nadále hledala lepší shodu (určená níže uvedenými pravidly zlepšení), pokud v tomto návrhu došlo k neshodě typu ref,
    • nebo případně pokračujte pouze pro neshodu ref vs. in, ne u ostatních (ref readonly vs. ref/in/by-value).
Pravidla k lepšímu

Následující příklad aktuálně vede k třem nejednoznačným chybám pro tři vyvolání M. Mohli bychom přidat nová pravidla lepšího řešení nejednoznačností. Tím by se vyřešila také výše popsaná změna způsobující chybu zdroje. Jedním ze způsobů by bylo nastavení příkladu, aby vytiskl 221 (kde se parametr ref readonly shoduje s argumentem in, protože volání bez modifikátoru by vyvolalo varování, zatímco pro parametr in je toto volání povoleno).

interface I1 { }
interface I2 { }
class C
{
    static string M(I1 o, in int i) => "1";
    static string M(I2 o, ref readonly int i) => "2";
    static void Main()
    {
        int i = 5;
        System.Console.Write(M(null, ref i));
        System.Console.Write(M(null, in i));
        System.Console.Write(M(null, i));
    }
}

Nová pravidla zlepšení mohou označit parametr jako horší, kdy by jeho argument mohl být předán s jiným modifikátorem, aby byl lepší. Jinými slovy, uživatel by měl být vždy schopen změnit horší parametr na lepší parametr změnou jeho odpovídajícího modifikátoru argumentu. Pokud je například argument předán in, je preferován parametr ref readonly před parametrem in, protože uživatel může předat argument formou hodnoty a zvolit parametr in. Toto pravidlo je pouze rozšířením pravidla předvoleb podle hodnoty neboin, které je v platnosti dnes (jedná se o poslední pravidlo řešení přetížení a celé přetížení je lepší, pokud je některý z jeho parametrů lepší a žádný není horší než odpovídající parametr jiného přetížení).

argument lepší parametr horší parametr
ref/in ref readonly in
ref ref ref readonly/in
podle hodnoty podle hodnoty/in ref readonly
in in ref

Podobně bychom měli zpracovávat převody metod. Následující příklad momentálně vede ke dvěma nejednoznačnostním chybám při přiřazení dvou delegátů. Nová pravidla zlepšení by mohla upřednostňovat parametr metody, jehož modifikátor "refness" odpovídá modifikátoru "refness" v odpovídajícím parametru cílového delegáta před těmi, které mají nesoulad. Proto by následující příklad vytiskl 12.

class C
{
    void M(I1 o, ref readonly int x) => System.Console.Write("1");
    void M(I2 o, ref int x) => System.Console.Write("2");
    void Run()
    {
        D1 m1 = this.M;
        D2 m2 = this.M; // currently ambiguous

        var i = 5;
        m1(null, in i);
        m2(null, ref i);
    }
    static void Main() => new C().Run();
}
interface I1 { }
interface I2 { }
class X : I1, I2 { }
delegate void D1(X s, ref readonly int x);
delegate void D2(X s, ref int x);

Kreativní schůzky

  • LDM 2022-04-25: akceptovaná funkce
  • LDM 2022-05-09: diskuze rozdělená do tří částí
  • LDM 2022-05-11: povoleno ref a nejsou popisky volaného místa pro parametry ref readonly