2009-03-13 11 views
7

Mi stavo solo occupando di stringhe e mi trovo infastidito dal fatto che le stringhe possano essere annullabili. Quindi, devo avereQuale decisione linguistica in C# ti infastidisce?

if((teststring??string.Empty)==string.Empty) 

dappertutto. Stringa? sono stati così difficili da consentire il nullability nei relativamente pochi casi in cui è necessario (dbs, input utente idiota, ecc.). Anch'io mi trovo irritato dal dover esportare interfacce di sola lettura nei casi in cui desidero una qualche forma di correttezza const. Quindi, quale costrutto/decisione del linguaggio C# ti infastidisce?

EDIT: Grazie per la funzione isnullorempty, non l'avevo mai visto prima! Ancora non diminuisce il mio fastidio che sia annullabile: D

+10

o si potrebbe fare se (string.IsNullOrEmpty (teststring)) ... –

+0

non essere un tale jjnguy buzzkill. È una domanda divertente per un venerdì e relativa programmazione. Inoltre non è lamentarsi, sono curioso di cosa infastidisce le persone. Solo perché c'è un isnullorempty non rende la decisione di permettere stringhe nullable meno fastidiose per me. – Steve

+0

Vedere anche: http://stackoverflow.com/questions/411906/c-net-design-flaws/ –

risposta

21

Rendere la stringa un tipo di riferimento mi sembra del tutto ragionevole.

È un peccato che non si possa dichiarare un tipo di variabile/parametro/ritorno come non annullabile - ad es.

// Never returns null 
public string! Foo() 
{ 
} 

contratti di codice in .NET 4.0 vi aiuterà con questo, credo - ma è un po 'tardi per rendere più pervasiva.

Qualche tempo fa ho scritto un blog entry on the mistakes of C#. Per riassumere quel post:

C# 1:

  • Mancanza di getter separato/accesso setter per le proprietà.
  • Mancanza di farmaci generici. La vita sarebbe stata molto più dolce con i generici fin dall'inizio.
  • Classi non sigillati per impostazione predefinita.
  • I numeri vengono semplicemente nominati.
  • La sequenza di escape del carattere "\ x".
  • Varie cose circa l'istruzione switch :)
  • regole di risoluzione
  • Alcuni sovraccarico strano
  • La parola chiave "lock", invece di "utilizzare" con un tocken serratura.

C# 2:

  • La mancanza di metodi parziali (è venuto in C# 3)
  • La mancanza della varianza generici (provenienti in C# 4)
  • Il System.Nullable classe (non Nullable<T> - va bene!)
  • InternalsVisiblePer richiedere l'intera chiave pubblica per assembly fortemente firmati anziché il token di chiave pubblica.

C# 3:

  • mancanza di supporto per immutabilità - un sacco di cambiamenti opportunità migliorato per mutare i tipi (proprietà automatiche, degli oggetti e raccolta inizializzatori) ma nessuno di questi funziona davvero per i tipi mutabili
  • Estensione metodo di rilevamento
+0

bella lista. Mi piace l'approccio storico! – Steve

+0

Gran parte della lista è in gran parte "mancavano le cose che arrivavano nella prossima versione"; eppure siamo sempre sopravvissuti fino a quando non sono stati aggiunti ... Alcuni di loro sono errori veri, però - lo garantisco. –

+0

A proposito di "cose ​​nella prossima versione" - alcuni di questi erano semplicemente stupidi. Non consentire un setter privato? Ick. Quella avrebbe dovuto essere una bontà ovvia. I metodi parziali sarebbero stati un po 'più difficili da individuare. Generics era ovviamente richiesto, ma difficile da definire (vale a dire più tempo necessario). –

28

stringhe Controllare per NULL o vuota è meglio fatto utilizzando:

if (string.IsNullOrEmpty(testString)) 
{ 
} 
+0

Poiché questa domanda ottiene ancora un bel po 'di traffico, vale la pena notare che ora abbiamo anche 'String.IsNullOrWhiteSpace'. – Yuck

0

Il modo che ho per implementare oggetti di un'interfaccia in C# 3.0 anche anche se sono esattamente uguali all'interfaccia quando non cambio il comportamento predefinito delle proprietà auto.

ad es.

public interface MyInterface 
{ 
    int MyProperty { get; set;} 
} 

public class MyClass : MyInterface 
{ 
    public int MyProperty { get; set; } 
} 

public class MyClass2 : MyInterface 
{ 
    public int MyProperty { get; set; } 
} 

public class MyClass3 : MyInterface 
{ 
    public int MyProperty { get; set; } 
} 

MODIFICA: Per rispondere ad alcuni dei commenti su questo. Non sto cambiando alcun comportamento predefinito del mio getter. Capisco la differenza tra la classe e l'interfaccia grazie, il mio punto è che il mio marcatura con l'interfaccia non dovrebbe avere questa proprietà all'interno di ogni classe di implementazione a meno che non voglia cambiare il comportamento predefinito del getter o setter. Immaginate che 500 classi implementino questa interfaccia?

anche la mancanza di mixin ..

+1

Come questo non ha senso? Anche se è lo stesso testo, il significato è molto diverso. L'interfaccia sta dicendo "La proprietà avrà un getter". La classe sta dicendo "compilatore, si prega di creare un campo privato e restituirlo immodificato all'interno del getter". –

+1

Questa decisione ha senso per me. Senza questo, come dovresti differenziare se la tua interfaccia richiede SOLO una proprietà get, o solo una proprietà set? Cosa succede se la tua classe non ha usato le proprietà automatiche (o è stata estesa con la logica in v2)? –

+0

Sì, ma quello che sto dicendo è che una volta implementata l'interfaccia, la proprietà dovrebbe essere implementata dietro le quinte a meno che non vogliate cambiarla. Ho appena trovato, in particolare con gli oggetti di trasferimento dati, che sto scrivendo lo stesso codice più e più volte. –

5

out e ref parametri

+1

Come gestirlo diversamente? –

+4

Restituisce un oggetto composito. –

+0

+1 Sì, questo, 100%. Io ** odio ** che 'TryParse' utilizza i parametri di output. Sarebbe bello per 'Int32.TryParse' restituire un oggetto' ParseResult 'con le proprietà' Exception' e 'Value'. – Yuck

1

Ampliando la risposta di Mitch.

Questa è in realtà una decisione CLR, non una C#. C# non ha alcun controllo sui dettagli di implementazione della classe System.String del BCL.

True C# potrebbe avere una stringa speciale nel compilatore e ha affermato che faremo dei controlli Null speciali ma che sarebbe IMHO, è stata una decisione sbagliata. String.IsNullOrEmpty è un compromesso accettabile.

+0

grazie per la spiegazione. – Steve

6

Probabilmente il più grande buco lampante in C# è, per me, enumerazioni.

Le enumerazioni Java sono classi tipografiche che è possibile dare un comportamento, possono implementare interfacce e così via.

C# /. Le enumerazioni nette sono solo glorificate inte con tutti i problemi che le costanti int hanno avuto in C e C++.

+1

D'altra parte, è possibile emulare facilmente enumerazioni Java complesse scrivendole come classe: p L'unica cosa che si perde è la possibilità di 'passare' su di essi. – JulianR

+0

Non c'è altro da aggiungere, come controllare quante istanze ci sono di un valore nozionale attraverso la serializzazione/deserializzazione e così via. – cletus

1

Applicazione di interruzione in un caso non vuoto.

Verbosità delle enumerazioni, in particolare nelle dichiarazioni dei casi. Se ho switch (expr) ed expr è un enum, non dovrei essere costretto a qualificare pienamente ogni enum in ogni caso, a meno che non ci sia un conflitto di denominazione.

0

Non permettere modifiche co/contra-varianza o diritti di accesso quando si esegue l'override classe di base o di attuazione di metodi di interfaccia:

public class A 
{ 
    protected virtual Stream method() 
    { 
     //...stuff... 
    } 
} 

public class B : A 
{ 
    // compiler borks... 
    public override FileStream method() 
    { 
     //...more stuff... 
    } 
} 
1

Eccezioni controllate sarebbe stato grande. So che molte persone li odiano da Java, ma penso che siano sempre i controlli di integrità forzata, specialmente su I/O. Mi piace la maggior parte delle cose che C# è stata modificata e/o aggiunta rispetto a Java, ma mi sarebbe piaciuto avere delle eccezioni controllate. Ormai è troppo tardi (il framework .NET è stato modificato in modo da farli rompere praticamente tutti i programmi là fuori) ma penso che sarebbe stato meglio averli.

0

Odio dover digitare IEnumerable<MyType> dappertutto. È così difficile da leggere. Preferirei una sorta di mano breve per rendere il mio codice più pulito.

Questo SO post riassume bene.

0

Trovo enormemente irritante il fatto che così tanti metodi di base siano statici, specialmente intorno a cose comunemente usate come Stringhe e Array.

Perché:

Array.Sort(myArray); 
String.IsNullOrEmpty(myString); 

invece di:

myArray.Sort(); 
myString.IsNullOrEmpty 

Non dire che non ci sono buone ragioni per questo e non è un grosso problema, ma se JS in grado di gestire, perché può' t C#? *

Anche l'implementazione dell'interruttore. Credo davvero che avrebbero dovuto fidarsi di noi con il fall-through.

* Vieni a questo mi manca anche la sintassi di chiusura di JS.

0

Non mi piace IDisposable/Dispose ecc. Venendo dal C++ è molto fastidioso trovarsi a dover pensare alla gestione della memoria in C#. L'istruzione using va bene se l'oggetto usa e getta è usato solo in una funzione. Se deve essere passato attorno a te è necessario referenziare manualmente il conteggio o fare qualcos'altro per sapere quando è possibile smaltire l'oggetto.

0

Mi piacerebbe vedere gli oggetti di classe come oggetti di prima classe nella lingua.

Ciò consentirebbe di sovrascrivere i metodi statici e dichiararli nelle interfacce.

Problemi correlati