Wyrażenia typu docelowego new
Notatka
Ten artykuł jest specyfikacją funkcji. Specyfikacja służy jako dokument projektowy dla funkcji. Zawiera proponowane zmiany specyfikacji wraz z informacjami wymaganymi podczas projektowania i opracowywania funkcji. Te artykuły są publikowane do momentu sfinalizowania proponowanych zmian specyfikacji i włączenia ich do obecnej specyfikacji ECMA.
Mogą wystąpić pewne rozbieżności między specyfikacją funkcji a ukończoną implementacją. Te różnice są przechwytywane w odpowiednich spotkania projektowego języka (LDM).
Więcej informacji na temat procesu wdrażania specyfikacji funkcji można znaleźć w standardzie języka C# w artykule dotyczącym specyfikacji .
Problem dotyczący czempiona: https://github.com/dotnet/csharplang/issues/100
Streszczenie
Nie wymagaj specyfikacji typu dla konstruktorów, gdy typ jest znany.
Motywacja
Zezwalaj na inicjowanie pól bez duplikowania typu.
Dictionary<string, List<int>> field = new() {
{ "item1", new() { 1, 2, 3 } }
};
Zezwalaj na pominięcie typu, gdy można go wywnioskować z użycia.
XmlReader.Create(reader, new() { IgnoreWhitespace = true });
Utwórz wystąpienie obiektu bez określania typu.
private readonly static object s_syncObj = new();
Specyfikacja
Nowa forma składniowa target_typed_new dla object_creation_expression jest akceptowana, w której typ jest opcjonalny.
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?
;
Wyrażenie target_typed_new nie posiada typu. Istnieje jednak nowa konwersja tworzenia obiektów, która jest niejawną konwersją z wyrażenia, umożliwiająca przejście z target_typed_new na każdy typ.
Biorąc pod uwagę typ docelowy T
, typ T0
jest typem bazowym dla T
, jeśli T
jest wystąpieniem System.Nullable
. W przeciwnym razie T0
jest T
. Znaczenie wyrażenia target_typed_new konwertowanego na typ T
jest takie samo jak znaczenie odpowiadającego object_creation_expression określającego T0
jako typ.
Jest to błąd czasu kompilacji, jeśli target_typed_new jest używany jako operand jednoargumentowego lub binarnego operatora, lub jeśli jest używany, gdy nie podlega konwersji tworzenia obiektu.
otwarty problem: czy należy zezwolić delegatom i krotkom na typ docelowy?
Reguły powyżej obejmują delegaty (typ odwołania) i krotki (typ struktury). Chociaż oba typy można skonstruować, jeśli typ można wywnioskować, można już użyć funkcji anonimowej lub literału krotki.
(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óżne
Poniżej przedstawiono konsekwencje specyfikacji:
-
throw new()
jest dozwolona (typ docelowy toSystem.Exception
) - Typ docelowy
new
nie jest dozwolony w przypadku operatorów binarnych. - Nie jest dozwolone, gdy nie ma typu docelowego: operatory jednoargumentowe, kolekcja
foreach
, wusing
, w dekonstrukcji, w wyrażeniuawait
, jako właściwość typu anonimowego (new { Prop = new() }
), w instrukcjilock
, w instrukcjisizeof
, w instrukcjifixed
, w dostępie do członka (new().field
), w operacji dynamicznie wysyłanej (someDynamic.Method(new())
), w zapytaniu LINQ, jako operand operatorais
, jako lewy operand operatora??
, ... - Jest również niedozwolony jako
ref
. - Następujące rodzaje typów nie są dozwolone jako obiekty docelowe konwersji
-
typy wyliczenia:
new()
będzie działać (ponieważnew Enum()
działa, aby nadać wartość domyślną), alenew(1)
nie będzie działać, ponieważ typy wyliczenia nie mają konstruktora. - Typy interfejsów: To działałoby tak samo jak odpowiednie wyrażenie tworzenia dla typów COM.
- typy tablic: tablice wymagają specjalnej notacji, aby określić długość.
-
dynamiczna: nie zezwalamy na
new dynamic()
, więc nie zezwalamy nanew()
zdynamic
jako typ docelowy. - Krotki: Mają to samo znaczenie, co tworzenie obiektu za pomocą typu bazowego.
- Wszystkie inne typy, które nie są dozwolone w object_creation_expression, są również wykluczone, na przykład, typy wskaźników.
-
typy wyliczenia:
Wady
Wystąpiły pewne obawy związane z new
przypisanym do wartości docelowych, tworząc nowe kategorie zmian niezgodności, ale mamy już to z null
i default
, a to nie było znaczącym problemem.
Alternatywy
Większość skarg dotyczących typów zbyt długich do zduplikowania w inicjowaniu pola dotyczy argumentów typu , a nie samego typu; możemy wywnioskować tylko argumenty typu w niektórych przypadkach, takich jak new Dictionary(...)
, i wywnioskować je lokalnie z kontekstu argumentów lub inicjatora kolekcji.
Pytania
- Czy powinniśmy zabraniać użycia w drzewach wyrażeń? (nie)
- Jak funkcja współdziała z argumentami
dynamic
? (bez specjalnego traktowania) - Jak funkcja IntelliSense powinna działać z
new()
? (tylko wtedy, gdy istnieje jeden typ docelowy)
Spotkania projektowe
C# feature specifications