Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
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 příslušné 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/5529
Shrnutí
Povolte modifikátor file u deklarací typů nejvyšší úrovně. Typ existuje pouze v souboru, kde je deklarován.
// File1.cs
namespace NS;
file class Widget
{
}
// File2.cs
namespace NS;
file class Widget // different symbol than the Widget in File1
{
}
// File3.cs
using NS;
var widget = new Widget(); // error: The type or namespace name 'Widget' could not be found.
Motivace
Naší primární motivací jsou generátory zdrojového kódu. Zdrojové generátory fungují přidáním souborů do kompilace uživatele.
- Tyto soubory by měly být schopné obsahovat podrobnosti implementace, které jsou skryté od zbytku kompilace, ale jsou použitelné v celém souboru, ve kterém jsou deklarovány.
- Chceme snížit potřebu generátorů hledat názvy typů, které nebudou kolidovat s deklaracemi v uživatelském kódu nebo kódu z jiných generátorů.
Podrobný návrh
- Modifikátor
filepřidáme do následujících sad modifikátoru: - Modifikátor
filelze použít pouze v typu nejvyšší úrovně.
Pokud má typ modifikátor file, říká se o něm, že jde o místní typ souboru .
Přístupnost
Modifikátor file není klasifikovaný jako modifikátor přístupnosti. Na typu nelze použít, v kombinaci s file, žádné modifikátory přístupnosti.
file se považuje za nezávislý koncept od přístupnosti. Protože místní typy souborů nelze zanořit, lze u typů internal použít pouze výchozí přístupnost file.
public file class C1 { } // error
internal file class C2 { } // error
file class C3 { } // ok
Pojmenování
Implementace zaručuje, že místní typy souborů v různých souborech se stejným názvem se liší od modulu runtime. Přístupnost a název typu v metadatech je definovaný implementací. Záměrem je umožnit kompilátoru přijmout jakékoli budoucí funkce omezení přístupu v modulu runtime, které jsou pro tuto funkci vhodné. Očekává se, že v počáteční implementaci se použije přístupnost internal a vygeneruje se nesrozumitelný název, který závisí na souboru, ve kterém je typ deklarován.
Vyhledat
Změníme oddíl vyhledávání členů následujícím způsobem (nový text v tučným písmem):
- Pokud je
Knula, odeberou se všechny vnořené typy, jejichž deklarace zahrnují parametry typu. PokudKnení nula, odeberou se všechny členy s jiným počtem parametrů typu. Pokud jeKnula, metody s parametry typu se neodeberou, protože proces odvozování typu (§11.6.3) může být schopen odvodit argumenty typu.- Dále nechte F být kompilační jednotkou, která obsahuje výraz, ve kterém probíhá vyhledávání členů. Všechny členy, které jsou místní typy souborů a nejsou deklarovány v F jsou ze sady odebrány.
- Další, pokud sada přístupných členů obsahuje místní typy souborů, odeberou se ze sady všechny členy, které nejsou typy místních souborů.
Poznámky
Tato pravidla nepovolují použití místních typů souborů mimo soubor, ve kterém jsou deklarovány.
Tato pravidla také umožňují místnímu typu souboru stínové oboru názvů nebo jiného než místního typu:
// File1.cs
class C
{
public static void M() { }
}
// File2.cs
file class C
{
public static void M() { }
}
class Program
{
static void Main()
{
C.M(); // refers to the 'C' in File2.cs
}
}
Všimněte si, že obory části specifikace neaktualizujeme. Je to proto, že jak uvádí specifikace:
Rozsah názvu je oblast textu programu, ve které je možné odkazovat na entitu deklarovanou názvem bez kvalifikace názvu.
Obor má vliv jenom na vyhledávání nekvalifikovaných názvů. To není úplně správný koncept, který bychom mohli využít, protože musíme také ovlivnit vyhledávání kvalifikovaných názvů:
// File1.cs
namespace NS1
{
file class C
{
public static void M() { }
}
}
namespace NS2
{
class Program
{
public static void M()
{
C.M(); // error: C is not in scope
NS1.C.M(); // ok: C can be accessed through NS1.
}
}
}
// File2.cs
namespace NS1
{
class Program
{
C.M(); // error
NS1.C.M(); // error
}
}
Proto neurčíme funkci z hlediska rozsahu, ve kterém je typ obsažen, ale jako další "pravidla filtrování" ve vyhledávání členů.
Atributy
Místní třídy souborů mohou být typy atributů a lze je použít jako atributy v rámci místních typů souborů i jiných než souborových místních typů, stejně jako kdyby byl typ atributu jiným než místním typem. Název metadat typu atributu file-local stále prochází stejnou strategií generování názvů jako jiné typy file-local. To znamená, že zjištění přítomnosti místního typu souboru pomocí pevně zakódovaného názvu řetězce bude pravděpodobně nepraktické, protože to vyžaduje v závislosti na interní strategii generování názvů kompilátoru, která se může v průběhu času měnit. Detekce prostřednictvím typeof(MyFileLocalAttribute) ale funguje.
using System;
using System.Linq;
file class MyFileLocalAttribute : Attribute { }
[MyFileLocalAttribute]
public class C
{
public static void Main()
{
var attribute = typeof(C).CustomAttributes.Where(attr => attr.AttributeType == typeof(MyFileLocalAttribute)).First();
Console.Write(attribute); // outputs the generated name of the file-local attribute type
}
}
Použití v podpisech
Obecně je potřeba zabránit tomu, aby se typy lokální pro soubor objevovaly v parametrech člena, návratových hodnotách a omezeních parametrů typu, kde v okamžiku použití člena nemusí být typ lokální pro soubor v dosahu.
Všimněte si, že nesouborové místní typy mají povoleno implementovat místní rozhraní, podobně jako typy mohou implementovat méně přístupná rozhraní. V závislosti na typech, které jsou přítomné ve členech rozhraní, může dojít k porušení pravidel v následující části.
Povolit pouze použití podpisu ve členech místních typů souborů
Nejjednodušší způsob, jak to zajistit, je vynutit, aby se místní typy souborů mohly objevit pouze v podpisech nebo jako základní typy jiných typů souborů:
file class FileBase
{
}
public class Derived : FileBase // error
{
private FileBase M2() => new FileBase() // error
}
file class FileDerived : FileBase // ok
{
private FileBase M2() => new FileBase(); // ok
}
Všimněte si, že to omezuje použití v explicitních implementacích, i když jsou takové použití bezpečné. Provedeme to, abychom zjednodušili pravidla pro počáteční iteraci funkce.
file interface I
{
void M(I i);
}
class C : I
{
void I.M(I i) { } // error
}
global using static
Jedná se o chybu v době kompilace při použití místního typu souboru v direktivě global using static, tj.
global using static C; // error
file class C
{
public static void M() { }
}
Implementace/přepsání
Deklarace místních typů souborů mohou implementovat rozhraní, přepsat virtuální metody atd. stejně jako běžné deklarace typu.
file struct Widget : IEquatable<Widget>
{
public bool Equals(Widget other) => true;
}
C# feature specifications