"použití na základě vzoru" a "using deklarací"
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 poznámkách 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/114
Shrnutí
Tento jazyk přidá kolem příkazu using
dvě nové funkce, které zjednoduší správu prostředků: using
by kromě IDisposable
měl rozpoznat jednorázový vzor a přidat do jazyka deklaraci using
.
Motivace
Prohlášení using
je dnes efektivním nástrojem pro správu prostředků, ale vyžaduje poměrně hodně obřadnosti. Metody, které mají řadu prostředků ke správě, mohou být syntakticky zatíženy řadou příkazů using
. Zátěž spojená se syntaxí je natolik významná, že většina pokynů pro styl kódování má explicitní výjimku ve vztahu ke složeným závorkám pro tento scénář.
Deklarace using
zde odstraňuje většinu obřadu a staví jazyk C# na stejnou úroveň s jinými jazyky, které zahrnují bloky správy prostředků. Kromě toho vzorový přístup using
umožňuje vývojářům rozšířit sadu typů, které se zde mohou zapojit. V mnoha případech odstranění potřeby tvoření obalových typů, které existují pouze k použití hodnot v příkazu using
.
Společně tyto funkce umožňují vývojářům zjednodušit a rozšířit scénáře, ve kterých je možné using
použít.
Podrobný návrh
deklarace klíčového slova using
Jazyk umožní přidání using
do deklarace místní proměnné. Taková deklarace bude mít stejný účinek jako deklarování proměnné v příkazu using
ve stejném umístění.
if (...)
{
using FileStream f = new FileStream(@"C:\source\using.md");
// statements
}
// Equivalent to
if (...)
{
using (FileStream f = new FileStream(@"C:\source\using.md"))
{
// statements
}
}
Životnost lokální proměnné using
bude prodloužena do konce bloku, ve kterém je deklarována. Místní proměnné using
budou poté odstraněny v opačném pořadí, ve kterém byly deklarovány.
{
using var f1 = new FileStream("...");
using var f2 = new FileStream("...");
using var f3 = new FileStream("...");
...
// Dispose f3
// Dispose f2
// Dispose f1
}
Neexistují žádná omezení týkající se goto
ani jiných konstrukcí řízení toku ve vztahu k deklaraci using
. Místo toho kód funguje stejně jako pro ekvivalentní příkaz using
:
{
using var f1 = new FileStream("...");
target:
using var f2 = new FileStream("...");
if (someCondition)
{
// Causes f2 to be disposed but has no effect on f1
goto target;
}
}
Místní proměnná deklarovaná v deklaraci using
bude automaticky pouze pro čtení. To odpovídá chování lokálních proměnných deklarovaných v příkazu using
.
Gramatika jazyka pro deklarace using
bude následující:
local-using-declaration:
'using' type using-declarators
using-declarators:
using-declarator
using-declarators , using-declarator
using-declarator:
identifier = expression
Omezení týkající se deklarace using
:
- Nemusí se zobrazovat přímo uvnitř popisku
case
, ale musí být uvnitř bloku uvnitř popiskucase
. - Nemusí se zobrazit jako součást deklarace proměnné
out
. - Musí mít inicializátor pro každý deklarátor.
- Místní typ musí být implicitně konvertibilní na
IDisposable
nebo musí splňovat vzorusing
.
na základě vzorů pomocí
Jazyk přidá koncept uvolnitelného vzoru pro typy ref struct
: jedná se o ref struct
, která má dostupnou metodu instance Dispose
. Typy, které odpovídají jednorázovému vzoru, se mohou účastnit příkazu using
nebo deklarace, aniž by musely implementovat IDisposable
.
ref struct Resource
{
public void Dispose() { ... }
}
using (var r = new Resource())
{
// statements
}
To vývojářům umožní využívat using
pro typy ref struct
. Tyto typy nemůžou implementovat rozhraní v jazyce C# 8, a proto se nemůžou účastnit příkazů using
.
Stejná omezení z tradičního příkazu using
platí i zde: místní proměnné deklarované v using
jsou jen pro čtení, hodnota null
nezpůsobí vyvolání výjimky atd. Generování kódu se bude lišit pouze v tom, že před voláním Dispose nedojde k přetypování na IDisposable
:
{
Resource r = new Resource();
try {
// statements
}
finally {
if (r != null) r.Dispose();
}
}
Aby bylo možné přizpůsobit jednorázový vzor, musí být metoda Dispose
přístupným členem instance, bez parametrů a mít void
návratový typ. Nemůže se jednat o metodu rozšíření.
Úvahy
V jazyce C# 8 nebyla implementována žádná z těchto aspektů.
popisky velkých a malých písmen bez bloků
using declaration
není přípustný přímo uvnitř štítku case
kvůli komplikacím kolem jeho skutečné životnosti. Jedním z možných řešení je prostě dát tomu stejnou životnost jako out var
na stejném místě. Byla považována za dodatečnou složitost implementace funkce a snadné řešení (stačí přidat blok na popisek case
) neodůvodnilo provedení této trasy.
Budoucí rozšíření
Opravené místní nastavení
Příkaz fixed
má všechny vlastnosti příkazů using
, které vyžadují schopnost mít using
lokální proměnné. Je třeba zvážit rozšíření této funkce i na lokální komponenty fixed
. Pravidla životnosti a řazení by měla platit stejně dobře pro using
a fixed
zde.
C# feature specifications