2009-03-18 10 views
70

Utilizzo di Resharper 4.1, ho trovato questo avviso interessante: "Accesso a un membro statico di un tipo tramite un tipo derivato". Ecco un esempio di codice di cui si verifica questo:Utilizzo del membro statico di una classe su un tipo derivato?

class A { 
    public static void SomethingStatic() { 
     //[do that thing you do...] 
    } 
} 

class B : A { 
} 

class SampleUsage { 
    public static void Usage() { 
     B.SomethingStatic(); // <-- Resharper warning occurs here 
    } 
} 

Qualcuno sa quali problemi ci sono (se presente) quando fanno uso di membri statici di A tramite B?

risposta

80

Un luogo in cui potrebbe essere fuorviante è quando la statica è un metodo di fabbrica, ad es. la classe WebRequest ha un metodo di fabbrica Create che consentirebbe di scrivere questo tipo di codice se vi si accede tramite una classe derivata.

var request = (FtpWebRequest)HttpWebRequest.Create("ftp://ftp.example.com"); 

Qui request è di tipo FtpWebRequest ma è confuso perché sembra che è stato creato da un (una classe di pari livello) HttpWebRequest anche se il metodo è in realtà Create definito WebRequest (classe base). Il seguente codice è identico significato, ma è chiaro:

var request = (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com"); 

definitiva non c'è nessun grande problema di accesso statica tramite un tipo derivato, ma il codice è spesso più chiare dalla non farlo.

+0

Questo è un problema che non avevo mai pensato prima. Grazie Greg! – Swim

+0

spiegazione bella e chiara con un buon esempio. – serg10

+0

ottima spiegazione, è stato davvero utile. Primo risultato anche su google ^^ – marcgg

15

Non è un avvertimento, di solito, solo un suggerimento. Stai creando una dipendenza da qualcosa inutilmente.

Supponiamo che in seguito si decida che B non ha bisogno di ereditare A. Se si segue il consiglio di Resharper, non sarà necessario modificare tale riga di codice.

+1

avresti lo stesso problema anche con i metodi di istanza. Con tutta questa logica, perché ereditare qualcosa? o mi manca qualcosa? – NullVoxPopuli

+0

@NullVoxPopuli - C'è chi consiglia di evitare del tutto l'ereditarietà dell'implementazione. Diversi libri popolari su Java e C# lo suggeriscono (vedi anche questo documento: http://www.isase.us/wisr3/7.pdf). Ma in ogni caso, se si ha un metodo di istanza 'Foo' in' A', quindi si dà un'istanza di 'B' a cui fa riferimento la variabile' b', non si ha la stessa libertà del caso statico a dì "dove" si dovrebbe cercare "Foo". Devi iniziare con 'b', qualunque cosa tu faccia. Quindi non è proprio la stessa cosa con la statica. –

2

Sì, ho visto anche questo, ho sempre pensato che fosse solo un avvertimento perché non era necessario. A.SomethingStatic(); farebbe la stessa cosa

29

B.SomethingStatic() rende la dichiarazione che SomethingStatic è un membro di B. Questo non è vero. SomethingStatic è inequivocabilmente un membro di A. Il fatto che sia accessibile non qualificato ai membri di B (come se fosse un membro di B) è una questione di convenienza. Il fatto che sia accessibile quando qualificato con un B è, IMO, un errore.

+2

+1 imo, la tua spiegazione è la migliore qui. –

+0

Penso che una sottoclasse dovrebbe sempre ereditare ogni proprietà di una superclasse. Soprattutto per il progetto a cui sto lavorando adesso, è super utile con i modelli di fabbrica. – NullVoxPopuli

+0

Non sono d'accordo. Ho un caso valido quando il comportamento attuale è vantaggioso.Ecco l'idea: 'class Validator: ValidatorBase {}'. Uso: 'Validator.CheckNonEmpty (str)'. Confrontalo con 'ValidatorBase .CheckNonEmpty (str)'. – Gebb