Funzionalità C # o .Net da tagliare presupponendo che non sia necessaria una retrocompatibilità? [chiuso]


18

Qualsiasi prodotto o framework si evolve. Principalmente è fatto per soddisfare le esigenze dei suoi utenti, sfruttare nuove capacità di elaborazione e semplicemente migliorarlo. A volte l'obiettivo di progettazione principale cambia anche con il prodotto. Il framework C # o .net non fa eccezione. Come vediamo, l'attuale 4a versione è molto diversa rispetto alla prima. Ma la cosa viene come una barricata a questa evoluzione, compatibilità all'indietro.

Nella maggior parte dei framework / prodotti ci sono funzionalità che sarebbero state tagliate se non fosse necessario supportare la compatibilità con le versioni precedenti. Secondo te, quali sono queste funzionalità in C # /. Net?

Si prega di citare una funzione per risposta.



4
La domanda non è chiaramente costruttiva secondo le linee guida e chiaramente costruttiva sulla base delle risposte fantastiche. Votazione per riaprire.
psr

1
peccato che sia chiuso, forse Eric scriverà questo blog invece di rispondere qui?
jk.

Risposte:


35

Metodi anonimi . Penso che tutti siano d'accordo sul fatto che la sintassi del metodo anonimo scelto per C # 2.0 sia pesante e goffa rispetto alla sintassi lambda che abbiamo aggiunto a C # 3.0. È profondamente spiacevole avere due sintassi quasi identiche per fare la stessa cosa.


1
D'accordo, i metodi anonimi erano fantastici quando non avevamo lambda ... ora sono semplicemente ridondanti.
Michael Brown,

9
C'è una caratteristica speciale dei metodi anonimi che è molto meglio delle espressioni lambda .... il loro nome perfetto !!
esplorazione

1
A questo punto, non ricordo nemmeno la sintassi di un metodo anonimo in C #. Dovrei cercarlo se per qualche bizzarra ragione avessi bisogno di usarne uno anziché un lambda.
Kyralessa,

33

Mi libererei delle collezioni non generiche. Sono un abominio ... e ci sono troppi casi in cui sto usando Linq e devo fare qualcosa del genere

var customObjects = container.CustomObjects.Cast<CustomObject>();

Ogni volta che devo farlo, una piccola parte della mia anima muore.


È troppo bello

1
Non tutte le porte di .NET supportano Generics. .NET Micro è un esempio. Potrebbe non essere applicabile se CustomObjects non passerà mai a questa piattaforma.
goodguys_activate il

2
Questo è il vantaggio di non avere un'anima.
CaffGeek,

29

vuoto come tipo . Perché mai "void" è un tipo? Non ha istanze, non ha valori, non è possibile utilizzarlo come argomento di tipo generico, tipo di parametro formale, tipo locale, tipo di campo o tipo di proprietà. Non ha significato come tipo; piuttosto, è un dato di fatto sull'effetto che una chiamata di metodo ha sullo stack della macchina virtuale. Ma la macchina virtuale è proprio questo: una macchina virtuale. La macchina reale inserirà il valore restituito in un registro (in genere EAX su x86) e non influenzerà affatto lo stack! Vuoto come tipo è solo una cattiva idea dappertutto.

Peggio ancora: quando usato in un tipo di puntatore come in void*esso significa qualcosa di completamente diverso da quello che significa quando usato come tipo di ritorno. Ora significa "un puntatore a una posizione di archiviazione di tipo sconosciuto", che non ha nulla a che fare con il suo significato come "un metodo che non restituisce alcun valore".

Possiamo sostituire void*come tipo di puntatore con IntPtr. (E void**con IntPtr*e così via.) Possiamo sostituire void come tipo di ritorno con "Unit", un tipo che ha un singolo valore, vale a dire null. Un'implementazione del CLR potrebbe quindi decidere che una chiamata di funzione tipizzata dall'unità potrebbe ottimizzare l'utilizzo di registri o stack in modo appropriato, sapendo che il null che viene "restituito" può essere tranquillamente ignorato.

In un mondo simile non hai più bisogno di separati Func<A, R>e Action<T>delegati. Action<T>è giusto Func<T, Unit>.


4
... ed Taskè solo un Task<Unit>. La reimplementazione dei bit della libreria del CTP asincrono mi ha fatto davvero desiderare questo ...
Jon Skeet,

24

L'affermazione vuota; . A rischio di errore, quasi sempre un errore di battitura, e non ti dà alcun significato aggiunto che non sia già espresso da {}.


7
Per non parlare dell'enorme penalità prestazionale ai sensi del JIT a 64 bit </snark>.
Jesse C. Slicer,

7
Una dichiarazione vuota ha una penalità di prestazione? Perché?
Quentin-starin,

22

Covarianza non sicura su array di tipo di riferimento . Con la covarianza di typesafe attiva IEnumerable<T>, almeno una parte della necessità di covarianza di array è andata via. (Se avessimo un'interfaccia di elenco di sola lettura covariante, non ne avremmo affatto bisogno.)


Stavo per scriverlo quando ho visto il titolo della domanda - mi hai battuto :(
Chris Smith,

1
È utile la possibilità di ricevere un riferimento di matrice covariante e di scrivere in modo sicuro sui riferimenti di matrice che sono stati letti da esso . Se come IList<T>ereditato da IReadableList<out T>e non generico IPemutable, potrebbe supportare cose come l'ordinamento, ma gli array lo supportano più facilmente.
supercat

14

L'operatore plus unario . L'operatore meno utile di tutti i tempi. Se non avessimo dovuto tenerlo per compatibilità con le versioni precedenti, lo avrei eliminato in un batter d'occhio. Chi usa questa cosa, qualcuno?

(Chiarimento: l'operatore plus unario +xnon è l'operatore di preincremento ++x, non l'operatore postincremento x++e non l'operatore di aggiunta binaria x+y.)


1
per (int i = 0; i <soffitto; i ++)
Michael Brown,

13
Non sta parlando del preincremento e gli operatori post-incremento: sta parlando del più unario, l'opposto del segno negativo su un numero: +1 == 1. È dannatamente vicino a una non-operazione.
Jesse C. Slicer,

8
Non è solo l'effetto sull'uscita a lettura ottica, può migliorare l'aspetto del codice per gli esseri umani: if(a == +1 || a == -1){...}.
Thomas Bratt,

5
@ShuggyCoUK: Ciò che è particolarmente bizzarro è che è sovraccarico . Perché succede molto. Sai, come stai scrivendo un po 'di JavaScript e pensi che amico, vorrei che JS mi permettesse di rendere unaria la semantica dell'operatore più unaria definita dall'utente come fa C # .
Eric Lippert,

2
@Eric Non mi ero reso conto che fosse sovraccarico. wow potresti fare qualche brutta offuscamento con quello :)
ShuggyCoUk

12

Valori numerici predefiniti a double

Per la maggior parte delle app aziendali , decimalè comunque più appropriato ... o forse sarebbe meglio rimuovere l'idea di un valore predefinito e forzare lo sviluppatore a fare effettivamente la scelta.

(Quel "rimuovere il default" sarebbe appropriato per alcune altre cose, anche. Ad esempio, ho rinunciato a cercare di convincere tutti che le classi devono essere sigillati per impostazione predefinita, ma ho il sospetto che sia più facile convincere la gente che dovrebbero pensare su se la loro nuova classe debba essere sigillata o meno e renderla esplicita.)


Forse mi affiderei all'identificazione dei letterali che implicano un valore che non può essere rappresentato esattamente come un doppio / float ...
ShuggyCoUk

Se sono in Java - riferiscili ai testi sacri di Joshua Bloch "design o documento per ereditarietà oppure proibiscili" martinfowler.com/bliki/DesignedInheritance.html IIRC kotlin sigilla le classi di default, quindi l'industria si sta spostando in una direzione migliore in questo senso.
Elazar Leibovich,

Perché le lezioni dovrebbero essere sigillate?
James

@James: esattamente per le ragioni fornite da Josh. Progettare una classe che consenta l'eredità in modo sensato e coerente richiede tempo, e farlo senza sapere come verrà usata l'eredità è ancora peggio.
Jon Skeet,

1
@Pacerier: pensa all'immutabilità, per esempio. Una classe non sigillata non può pretendere di essere immutabile, in quanto le sottoclassi possono introdurre mutabilità.
Jon Skeet,

7

Questa è più una linea guida che una caratteristica, ma penso che sia importante perché è già troppo radicata nella mente delle persone come la soluzione canonica e migliore:

Il modello ufficiale da implementare IDisposable.

È ingombrante e ci sono modi migliori .


6

Io so che ci sono grandi differenze tra le varie classi del timer. Ma non potremmo liberarcene uno o due, comunque?


4

Metodi e tipi di Arraye List<T>che sono diventati obsoleti con Linq, ad esempio:

  • Array.TrueForAll può essere sostituito con Enumerable.All
  • Array.FindAll può essere sostituito con Enumerable.Where
  • List<T>.ConvertAll può essere sostituito con Enumerable.Select
  • Predicate<T> può essere sostituito con Func<T, bool>
  • Converter<T,R> può essere sostituito con Func<T, R>
  • IComparer<T> davvero dovrebbe essere un delegato Func<T, T, int>

3
Mi piace il Predicate<T>perché cattura l'intenzione su come viene utilizzata la funzione e consente di risparmiare un po 'di digitazione.
Zebi,

2

Delegati non generici Come le raccolte non generiche, i delegati non generici sono inutili ora che abbiamo le serie Func e Action. E avrei tagliato le varianti con tre parametri. Se hai più di tre parametri, crea una struttura e usala come singolo parametro. Dichiarare un delegato specifico per la gestione degli eventi non è molto ASCIUTTO.


3
Come definirebbe un delegato a un metodo che accetta un riferimento con Action o Func? Come definiresti un combinatore con Func? Cioè, non c'è modo di dire "delegato DD (D d);" con Func.
Eric Lippert,

2
hmmm ... rimango corretto. Ecco perché lascio il lavoro di creazione degli strumenti che uso nelle tue mani abili;)
Michael Brown,

@EricLippert: mi piacerebbe vedere una classe speciale di delegati che attraverso la magia CLR avrebbe contenuto delegati di "ogni" arità e combinazione di parametri valore / riferimento [la ricerca di un delegato nella classe magica con un nome adeguatamente formattato avrebbe creato il tipo], e tutti i delegati con firma corretta ereditano da quello. Il codice che desidera un determinato delegato richiederebbe comunque un tipo esatto, ma il codice che desidera una particolare firma potrebbe usare il nome magico.
supercat

-1

asmx Web Services

Penso che al giorno d'oggi siano piuttosto obsoleti con WCF.


6
Sì, ma a volte molto più facile da grok. . .
Wyatt Barnett,

-2

Winforms
Sarebbe bello non dover navigare tra due piattaforme desktop. WPF è dove stanno andando le cose, quindi è frustrante avere una ridondanza completa a livello di piattaforma.


Winforms sembra molto più stabile, più veloce e meno buggy di WPF ...
Pacerier

Quando hai solo bisogno di hackerare una piccola app desktop, WPF è un grosso problema.
Kyralessa

Sembra che tra WPF sia diventato piuttosto obsoleto a favore di WinRT. Tuttavia, per me sembra che Winforms sia più vivo di WPF nello sviluppo del business. Vedi anche stackoverflow.com/questions/913417/…
Doc Brown,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.