2009-04-28 7 views
7

Quali sono le situazioni e i relativi benefici associati all'uso di Generics over Inheritance e viceversa e come dovrebbero essere combinati al meglio?Quando è appropriato usare Generics Versus Ereditarietà?

Grazie per la risposta ragazzi.

ho intenzione di cercare di affermare la motivazione per questa domanda come meglio posso: Ho una classe come illustrato di seguito:

class InformationReturn<T> where T : Info 
{ 
    InformationReturn(Employee employee, List<T>) { ... } 
} 

Ora supponiamo di avere un repository che prende un argomento InformationReturn, che deve stringere campi diversi in un DB a seconda del tipo di oggetto Info T. È meglio creare repository diversi ciascuno per il tipo T; un repository che utilizza la reflection per determinare il tipo; o c'è un modo migliore di usare le capacità di ereditarietà sopra/con i generici?

Nota: l'altro codice client deve funzionare in modo diverso in base al tipo di T.

risposta

4

Sono idee davvero diverso. I generici consentono di dichiarare funzionalità "specifiche" comuni (a rischio di suonare ossimorici) in generale. A List<int> non funziona in modo diverso da uno List<string>, a parte il tipo di dati che è contenuto all'interno.

Mentre eredità potrebbe essere usato per fare la stessa cosa, ho potuto creare una classe List, poi un e una classe IntListStringList che ereditano da essa. Potrei facilmente far funzionare queste due classi in modo completamente diverso, o avere una funzionalità di offerta non disponibile nell'altra.

Modifica

Dopo aver esaminato la modifica alla domanda, la risposta sortof è "dipende". È possibile creare argomenti per entrambe le parti - e, in effetti, LINQ to SQL e Entity Framework sono entrambi una combinazione di entrambe le ispezioni riflessive utilizzando generici e classi di entità fortemente tipizzate e altre classi di repository. Puoi certamente prendere l'approccio che stai guardando, ma sappi che, in generale, un problema che può essere risolto con la riflessione o con qualcos'altro è LIKELY che sarà più veloce una volta risolto dal "qualcos'altro". Si tratta di quanto un compromesso si desidera tra prestazioni, manutenibilità, leggibilità e affidabilità.

+0

Questa risposta mi ha aiutato a punto dovrei usare farmaci generici, quando non v'è alcuna differenza di comportamento e l'eredità altrimenti, grazie. Ho modificato la domanda per chiarire le mie motivazioni. – Laz

10

Generici ed ereditarietà sono due cose separate. L'ereditarietà è un concetto di OOP e i generici sono una funzionalità CLR che consente di specificare i parametri del tipo in fase di compilazione per i tipi che li espongono.

Ereditarietà e generici funzionano davvero abbastanza bene insieme.

Ereditarietà:

Inheritance mi permette di creare un tipo:

class Pen { } 

e poi creare un altro tipo che si estende Pen:

class FountainPen : Pen { } 

Questo è utile perché posso riutilizzare tutti gli stati e il comportamento della classe base ed esporre qualsiasi nuovo comportamento o stato in FountainPen. L'ereditarietà mi consente di creare rapidamente una versione più specifica di un tipo esistente.

Generics:

Generics sono una caratteristica CLR che mi permette di creare un tipo come questo:

class Foo<T> 
{ 
    public T Bar { get; set; } 
} 

Ora quando uso Foo<T> posso specificare quale tipo di T sarà fornendo un argomento di tipo generico:

Foo<int> foo = new Foo<int>(); 

Ora, poiché ho specificato che T deve essere un int per l'oggetto che ho appena creato, il tipo di Foo.Bar sarà anche int poiché è stato dichiarato di tipo T.

+3

Ma quando si dovrebbe utilizzare ciascuno? –

+1

Picky bit of pedantry: fornisci un tipo generico * argomento *, cioè T è il parametro type, int è l'argomento type. Ti permetterò di decidere se vale la pena o meno una modifica :) –

+0

Risolto! Grazie per avermelo fatto notare, la pedanteria non è mai sgradita - chissà che ne so distribuirla in abbondanza :) –

3

L'ereditarietà è molto più di "is-a" (la rana è un animale) in cui i generici riguardano la creazione di contenitori che agiscono su dati digitati (Elenco di T, Processore di T, ecc.). Sono non si escludono a vicenda.

Si può avere questo se si vuole:

public class Base<T> 
{ 

} 

public class Derived : Base<Foo> 
{ 

} 
+0

E infatti, si può avere interfacce generiche: interfaccia pubblica IBase -> pubblica di base astratta : IBase -> public class Derived: Base

4

Penso che dovresti usare i generici quando vuoi applicare la stessa funzionalità a vari tipi (Aggiungi, Rimuovi, Conta) e verrà implementato allo stesso modo. L'ereditarietà è quando è necessaria la stessa funzionalità (GetResponse) ma si desidera che venga implementata in modi diversi.

+0

IMO, questa è in realtà la migliore risposta a questa domanda! Dopo aver cercato SE per circa 20 minuti .. – Pingi

7

Utilizzare i generici per specificare un comportamento dell'algoritmo o del tipo che può essere espresso in termini di alcuni "tipi sconosciuti" pur mantenendo un'API fortemente digitato in termini di tale tipo sconosciuto. Il tipo sconosciuto è conosciuto come un parametro di tipo e si esprime nel codice come questo:

public class List<T> 
{ 
    public void Add(T item) 
} 

(ecc) - qui T è il parametro di tipo. metodi generici sono simili:

public void Foo<T>(T item) 

Il chiamando codice specifica il tipo di argomento si vuole lavorare con, ad esempio,

List<string> list = new List<string>(); 
list.Add("hi"); 

Utilizzare l'ereditarietà per specializzare il comportamento di un tipo.

non posso davvero pensare a molti luoghi dove sono alternative l'una all'altra ...

+0

Downvoters: indicare i motivi ... –

+1

+1 Per una definizione concisa di "programmazione generica". –

+3

Anche se non ti ho minimizzato, la tua risposta è piuttosto inutile. L'OP è ovviamente nuovo di .NET e la definizione del dizionario estremamente breve e concisa probabilmente farà ben poco per chiarire la sua confusione. – BFree

4

utilizzare farmaci generici quando si desidera creare un "modello" che può applicarsi a molti stili di classi sconosciute. Per esempio. Collezioni in possesso ??? sono buoni candidati per i generici. L'ereditarietà è per quando si ha una base di riferimento che i bambini "sono" un'estensione di quel concetto.

mie regole generali

  • se si inizia a definire properites come oggetto nel codice e digita gettando un sacco, poi la sua, probabilmente il tempo per i medicinali generici.
  • Se si desidera programmare contro il "concetto superiore" e la classe derivata, quindi la sua ereditarietà.
  • Se la tua classe sta per concludere o lavorare su una classe concerte, i suoi generici.
  • Se ti affidi alle specifiche di una classe sconosciuta "ancora da definire", allora probabilmente stai meglio con i generici.
  • Se le classi derivate sono "è a", quindi la sua ereditarietà di solito
  • Se la tua superclasse "usa un po 'di x" allora i suoi generici.
+0

Ora puoi commentare! – Vaccano

Problemi correlati