Sdílet prostřednictvím


Výrazy new typu cíle

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. Poznámky ze schůzky o návrhu jazyka (LDM) zachycují tyto rozdíly.

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/100

Shrnutí

Pokud je typ známý, nevyžadují specifikaci typu pro konstruktory.

Motivace

Povolit inicializaci polí bez duplikování typu

Dictionary<string, List<int>> field = new() {
    { "item1", new() { 1, 2, 3 } }
};

Povolte vynechání typu, když ho lze odvodit z použití.

XmlReader.Create(reader, new() { IgnoreWhitespace = true });

Bez výslovného uvedení typu vytvořte instanci objektu.

private readonly static object s_syncObj = new();

Specifikace

Nová syntaktická forma, target_typed_newobject_creation_expression, ve které je typ volitelný, je přijata.

object_creation_expression
    : 'new' type '(' argument_list? ')' object_or_collection_initializer?
    | 'new' type object_or_collection_initializer
    | target_typed_new
    ;
target_typed_new
    : 'new' '(' argument_list? ')' object_or_collection_initializer?
    ;

Výraz target_typed_new neobsahuje typ. Existuje však nový převod objektu, který je implicitním převodem vycházejícím z výrazu target_typed_new na každý jeden typ.

Je-li dán cílový typ T, pak je základním typem Ttyp T0, pokud je T instancí System.Nullable. V opačném případě T0 je T. Význam výrazu target_typed_new převedeného na typ T je stejný jako význam odpovídajícího object_creation_expression, který určuje T0 jako typ.

Jedná se o chybu v době kompilace, pokud se target_typed_new používá jako operand unárního nebo binárního operátoru, nebo pokud se používá tam, kde není předmětem převodu objektu.

Otevřený problém: měli bychom povolit delegáty a n-tice jako cílový typ?

Výše uvedená pravidla zahrnují delegáty (referenční typ) a n-tice (strukturovaný typ). I když jsou oba typy konstruktovatelné, pokud je typ odvozený, je možné použít anonymní funkci nebo literál řazené kolekce členů.

(int a, int b) t = new(1, 2); // "new" is redundant
Action a = new(() => {}); // "new" is redundant

(int a, int b) t = new(); // OK; same as (0, 0)
Action a = new(); // no constructor found

Různé

Toto jsou důsledky specifikace:

  • throw new() je povolená (cílový typ je System.Exception)
  • Cílový typ new není povolen s binárními operátory.
  • Je zakázáno, pokud neexistuje žádný typ, na který se má cílit: unární operátor, kolekce foreach, v using, v dekonstrukci, ve výrazu await, jako vlastnost anonymního typu (new { Prop = new() }), v příkazu lock, v sizeof, v příkazu fixed, v přístupu člena (new().field), v dynamicky vyžádané operaci (someDynamic.Method(new())), v dotazu LINQ, jako operand operátoru is, jako levý operand operátoru ??, ...
  • Je také zakázáno jako ref.
  • Následující typy typů nejsou povoleny jako cíle převodu.
    • typy výčtu:new() bude fungovat (protože new Enum() funguje s výchozí hodnotou), ale new(1) nebude fungovat, protože typy výčtu nemají konstruktor.
    • Typy rozhraní: To by fungovalo stejně jako odpovídající výraz pro vytváření pro typy modelu COM.
    • typy polí: pole potřebují speciální zápis pro určení délky.
    • dynamické: nepovolujeme new dynamic(), takže new() s dynamic jako cílovým typem nepovolujeme.
    • n-tice: Mají stejný význam jako vytvoření objektu ze základního typu.
    • Všechny ostatní typy, které nejsou povoleny v object_creation_expression jsou vyloučeny také, například typy ukazatelů.

Nevýhody

S cílovým typem new vytváření zásadních změn v nových kategoriích vyvolalo určité obavy, ale už to máme s null a default, a to nebylo významným problémem.

Alternativy

Většina stížností na typy, které jsou příliš dlouhé na duplikování v inicializaci polí, se týká argumentů typu, jako jsou a, ne samotného typu. Mohli bychom odvodit pouze argumenty typu, jako je new Dictionary(...) (nebo podobně), a odvodit argumenty typu místně z argumentů nebo inicializátoru kolekce.

Otázky

  • Měli bychom zakázat použití ve stromech výrazů? (ne)
  • Jak funkce komunikuje s dynamic argumenty? (žádné zvláštní zacházení)
  • Jak má IntelliSense fungovat s new()? (pouze pokud existuje jeden cílový typ)

Schůzky o designu