Espressioni tipate di destinazione new
Nota
Questo articolo è una specifica di funzionalità. La specifica funge da documento di progettazione per la funzionalità. Include le modifiche specifiche proposte, insieme alle informazioni necessarie durante la progettazione e lo sviluppo della funzionalità. Questi articoli vengono pubblicati fino a quando le modifiche specifiche proposte non vengono completate e incorporate nella specifica ECMA corrente.
Potrebbero verificarsi alcune discrepanze tra la specifica di funzionalità e l'implementazione completata. Quelle differenze vengono acquisite nelle note pertinenti ai language design meeting (LDM).
Altre informazioni sul processo per l'adozione di speclet di funzionalità nello standard del linguaggio C# sono disponibili nell'articolo sulle specifiche di .
Problema del campione: https://github.com/dotnet/csharplang/issues/100
Sommario
Non richiedere la specifica del tipo per i costruttori quando il tipo è noto.
Motivazione
Consenti inizializzazione dei campi senza duplicare il tipo.
Dictionary<string, List<int>> field = new() {
{ "item1", new() { 1, 2, 3 } }
};
Consente di omettere il tipo quando può essere dedotto dall'utilizzo.
XmlReader.Create(reader, new() { IgnoreWhitespace = true });
Creare un'istanza di un oggetto senza specificare il tipo.
private readonly static object s_syncObj = new();
Specificazione
Viene accettata una nuova forma sintattica, target_typed_new del object_creation_expression in cui il tipo è facoltativo.
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?
;
Un'espressione target_typed_new non dispone di un tipo. Tuttavia, esiste una nuova conversione di creazione di oggetti che è una conversione implicita da un'espressione, che va da un target_typed_new a ogni tipo.
Dato un tipo di destinazione T
, il tipo T0
è il tipo sottostante di T
se T
è un'istanza di System.Nullable
. In caso contrario, T0
è T
. Il significato di un'espressione target_typed_new convertita nel tipo T
corrisponde al significato di un object_creation_expression corrispondente che specifica T0
come tipo.
Si tratta di un errore in fase di compilazione se un target_typed_new viene usato come operando di un operatore unario o binario o se viene usato in cui non è soggetto a una conversione di creazione di oggetti .
Problema aperto: dovremmo consentire delegati e tuple come tipo obiettivo?
Le regole precedenti includono delegati (un tipo di riferimento) e tuple (un tipo struct). Anche se entrambi i tipi sono costruttibili, se il tipo è inferibile, è già possibile usare una funzione anonima o un valore letterale di tupla.
(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
Misto
Di seguito sono riportate le conseguenze della specifica:
-
throw new()
è consentito (il tipo di destinazione èSystem.Exception
) - L'
new
tipizzato di destinazione non è consentito con operatori binari. - Non è consentito quando non esiste alcun tipo di destinazione: operatori unari, raccolta di un
foreach
, in unusing
, in una decostruzione, in un'espressioneawait
, come proprietà di tipo anonimo (new { Prop = new() }
), in un'istruzionelock
, in unsizeof
, in un'istruzionefixed
, in un accesso membro (new().field
), in un'operazione gestita dinamicamente (someDynamic.Method(new())
), in una query LINQ, come operando dell'operatoreis
, come operando sinistro dell'operatore??
, ... - Non è consentito anche come
ref
. - I tipi seguenti non sono consentiti come destinazioni della conversione
-
tipi di enumerazione:
new()
funzionerà (comenew Enum()
funziona per assegnare il valore predefinito), manew(1)
non funzionerà poiché i tipi di enumerazione non dispongono di un costruttore. - Tipi di interfaccia: questa operazione funziona come l'espressione di creazione corrispondente per i tipi COM.
- Tipi di matrice: matrici necessitano di una sintassi speciale per fornire la lunghezza.
-
dinamica: non consentiamo
new dynamic()
, quindi non consentiamonew()
condynamic
come tipo di destinazione. - tuple: hanno lo stesso significato della creazione di un oggetto usando il tipo sottostante.
- Tutti gli altri tipi non consentiti nel object_creation_expression vengono esclusi anche, ad esempio, tipi di puntatore.
-
tipi di enumerazione:
Svantaggi
Ci sono state alcune preoccupazioni riguardo alla creazione di nuove categorie di modifiche significative con il tipo di destinazione new
, ma questo lo avevamo già con null
e default
, e non è stato un problema significativo.
Alternative
La maggior parte delle lamentele relative ai tipi troppo lunghi da duplicare nell'inizializzazione dei campi riguarda gli argomenti di tipo , non il tipo stesso; potremmo dedurre solo argomenti di tipo come new Dictionary(...)
(o simili) e dedurre localmente gli argomenti di tipo dagli argomenti o dall'inizializzatore della raccolta.
Domande
- È consigliabile proibire gli utilizzi negli alberi delle espressioni? (no)
- In che modo la funzionalità interagisce con gli argomenti
dynamic
? (nessun trattamento speciale) - Come funziona IntelliSense con
new()
? (solo quando è presente un singolo tipo di destinazione)
Riunioni di design
C# feature specifications