Perché i metodi magici sono stati implementati in C #?

14

In C #, ho iniziato a vedere tutti questi metodi magici spuntare, senza essere supportati da un'interfaccia. Perché Anders Hejlsbjerg (o chi è attualmente responsabile dello sviluppo di C #) sceglie questo?

Lasciami spiegare.

Precedentemente in C #, se un oggetto implementava l'interfaccia IEnumerable , sarebbe automaticamente iterabile da un ciclo foreach . Questo ha senso per me, dal momento che è supportato da un'interfaccia, e se dovessi avere la mia funzione Iterator all'interno della classe che viene ripetuta, potrei farlo senza preoccuparmi che significhi magicamente qualcos'altro.

Ora, a quanto pare, (non è sicuro quando), queste interfacce non sono più necessarie. Ha solo bisogno delle giuste conversioni di denominazione.

Un altro esempio è rendere qualsiasi oggetto attendibile con un metodo denominato esattamente GetAwaiter che ha alcune proprietà specifiche.

Perché non creare un'interfaccia come hanno fatto con IEnumerable o INotifyPropertyChanged per eseguire il backup di questa "magia" su staticamente?

Maggiori dettagli su cosa intendo qui:

link

Quali sono i pro e i contro dei metodi magici, e c'è un posto online dove posso trovare qualcosa sul perché sono state prese queste decisioni?

    
posta Mathias Lykkegaard Lorenzen 13.08.2014 - 22:07
fonte

1 risposta

14

In generale i "metodi magici" sono usati quando non è possibile creare un'interfaccia che funzioni allo stesso modo.

Quando foreach è stato introdotto per la prima volta in C # 1.0 (che il comportamento non è certamente recente), ha dovuto usare metodi magici, perché non c'erano generici. Le opzioni erano fondamentalmente:

  1. Utilizza il non generico IEnumerable e IEnumerator che funzionano con object s, che significa tipi di valore di boxe. Poiché iterare qualcosa come un elenco di int s dovrebbe essere molto veloce e certamente non dovrebbe creare molti valori di garbage box, questa non è una buona scelta.

  2. Aspetta i generici. Questo probabilmente significherebbe ritardare. Net 1.0 (o almeno foreach ) di più di 3 anni.

  3. Usa i metodi magici.

Quindi, hanno scelto l'opzione n. 3 e sono rimasti con noi per motivi di compatibilità con le versioni precedenti, anche se dal momento che .Net 2.0, che richiede IEnumerable<T> avrebbe funzionato.

Gli inizializzatori della raccolta possono avere un aspetto diverso su ciascun tipo di raccolta. Confronta List<T> :

public void Add(T item)

e Dictionary<TKey, TValue> :

public void Add(TKey key, TValue value)

Non puoi avere una singola interfaccia che supporti solo il primo modulo per List<T> e solo il secondo per Dictionary<TKey, TValue> .

I metodi LINQ vengono solitamente implementati come metodi di estensione (in modo che ci possa essere una sola implementazione, ad esempio LINQ to Object, per tutti i tipi che implementano IEnumerable<T> ), il che significa che non è possibile utilizzare un'interfaccia.

Per await , il metodo GetResult() può restituire void o qualche tipo T . Di nuovo, non puoi avere una singola interfaccia in grado di gestire entrambi. Sebbene await sia parzialmente basato sull'interfaccia: il cameriere deve implementare INotifyCompletion e può anche implementare ICriticalNotifyCompletion .

    
risposta data 13.08.2014 - 23:42
fonte

Leggi altre domande sui tag