2011-02-09 8 views
18

Mi fa piacere che C# non ti consenta di accedere ai membri statici "come se" fossero membri di istanze. Questo evita un errore comune in Java:Perché è utile accedere ai membri statici "attraverso" i tipi ereditati?

Thread t = new Thread(..); 
t.sleep(..); //Probably doesn't do what the programmer intended. 

D'altra parte, si fa permetterà di accedere membri statici 'attraverso' tipi derivati. Oltre agli operatori (dove ti evita di scrivere cast), non riesco a pensare a casi in cui ciò sia effettivamente utile. In realtà, si incoraggia attivamente errori come ad esempio:

// Nasty surprises ahead - won't throw; does something unintended: 
// Creates a HttpWebRequest instead. 
var ftpRequest = FtpWebRequest.Create(@"http://www.stackoverflow.com"); 

// Something seriously wrong here. 
var areRefEqual = Dictionary<string, int>.ReferenceEquals(dict1, dict2); 

Personalmente continuo a commettere simili errori più e più volte, quando sto cercando la mia strada attraverso le API sconosciute (ricordo partendo con alberi di espressione; mi ha colpito BinaryExpression. nell'editor e mi chiedevo perché mai IntelliSense mi stesse offrendo MakeUnary come opzione).

A mio parere (miopi), questa funzione:

  1. Non riduce la verbosità; il programmatore deve specificare un nome-tipo in un modo o nell'altro (esclusi operatori e casi in cui si accede ai membri statici ereditati del tipo corrente).
  2. Incoraggia bug/codice fuorviante come quello sopra.
  3. Può suggerire al programmatore che i metodi statici in C# mostrano una sorta di "polimorfismo", quando non lo fanno.
  4. (Minore) Introduce possibilità "silenziose", probabilmente involontarie, di rebinding sulla ricompilazione.

(IMO, gli operatori sono un caso speciale che garantisce la loro discussione.)

Dato che C# è normalmente un "pozzo di successo" la lingua, perché questa funzione esiste? Non riesco a vedere i suoi benefici (oltre alla "rilevabilità", che potrebbe essere sempre risolta nell'IDE), ma vedo molti problemi.

+3

O, peggio, 'UTF8Encoding.ASCII'. – SLaks

+1

Sono d'accordo che può essere leggermente fuorviante, ma è coerente con il principio che * i membri ereditati sono trattati come membri del tipo derivato *.Si noti che noi * esplicitamente * non permettiamo questo modello su parametri di tipo vincolato perché in questo caso è potenzialmente abbastanza fuorviante. Vedi http://blogs.msdn.com/b/ericlippert/archive/2007/06/14/calling-static-methods-on-type-parameters-is-illegal-part-one.aspx per i dettagli. –

risposta

7

Sono d'accordo che questa è una disfunzione. Non so quante volte qualcuno su Stack Overflow ha pubblicato il codice di:

ASCIIEncoding.ASCII 

ecc ... che, pur innocuo in termini di esecuzione è fuorviante in termini di lettura del codice.

Ovviamente è troppo tardi per rimuovere questa "funzionalità" ora, anche se suppongo che il team di C# potrebbe introdurre una modalità di avviso super-verbosa per questo e altri problemi di stile.

Forse successore C# 's migliorerà le cose ...

+0

In realtà, l'ho visto solo [una sola volta] (http://stackoverflow.com/questions/4252426/webclient-unicode-which-utf8) su SO. – SLaks

+0

StyleCop potrebbe provare a catturarli. – SLaks

+3

Come @SLaks ha detto, 'UTF8Encoding.ASCII' è anche peggio – digEmAll

2

Questo è utile in WinForms.

In ogni controllo o form, è possibile scrivere MousePosition, MouseButtons, o ModifierKeys di utilizzare i static membri ereditati da Control.

È ancora discutibile se sia stata una buona decisione.

+1

È ancora possibile accedere ai membri statici "ereditati" attraverso il contesto implicito della scrittura di una classe, ma non essere in grado di accedervi * quando si specifica un nome di tipo * diverso da quello giusto. –

+0

Vero. Non sono sicuro se posso pensare a qualche uso per questo. – SLaks

+0

Sono d'accordo con Jon, queste due cose sono in qualche modo ortogonali. Il problema del rebinding silenzioso è ancora lì, anche se è minore e improbabile che si verifichi in WinForms. – Ani

Problemi correlati