2012-06-27 10 views
7

ho una classe di raccolta come questa:C# implicita conversione da classe base

public class SomeDataCollection : List<ISomeData> 
{ 
    // some method ... 
} 

ma non posso fare questo:

SomeDataCollection someDatas = new List<ISomeData>(); 

Impossibile implicitamente convertito tipo List<ISomeData>-SomeDataCollection . Una conversione esplicita esiste (Vi manca un cast?)

così cerco di creare un coverter implicita all'interno della classe SomeDataCollection collezione:

public static implicit operator SomeDataCollection(List<ISomeData> l) 
{ 
    var someDatas = new SomeDataCollection(); 
    someDatas.AddRange(l); 
    return someDatas; 
} 

ma ha detto che non posso creare tale convertitore:

SomeDataCollection.implicit operator SomeDataCollection(List<ISomeData>): conversioni definite dall'utente o da una classe base non sono ammessi

E quando ho gettato in questo modo:

SomeDataCollection someDatas = (SomeDataCollection)new List<ISomeData>(); 

getta un errore che ha detto:

System.InvalidCastException: Impossibile eseguire il cast oggetto di tipo List<ISomeData> digitare SomeDataCollection.

Come posso fare questo:

SomeDataCollection someDatas = new List<ISomeData>(); 

senza ottenere un errore? Per favore aiuto. Grazie in anticipo.

+0

possibile dupplicate: http://stackoverflow.com/questions/3401084/user-defined-conversion-operator-from-base-class – albertjan

risposta

6

A new List<ISomeData>(); è ancora solo un List<ISomeData>. Non è un SomeDataCollection. Il punto di sottoclasse è che la sottoclasse potrebbe avere uno stato extra ecc., Ma un oggetto (una volta creato) mai tipo di modifiche.

Non è consentito creare operatori tra tipi nella stessa gerarchia, in quanto ciò sovvertire il comportamento di trasmissione normale e previsto.

Si potrebbe usare semplicemente:

var data = new SomeDataCollection(); 

Tuttavia devo aggiungere che francamente è raramente utile per creare una sottoclasse List<T>. Non ultimo, non espone alcun utile metodo virtual, quindi non è possibile modificare il comportamento. Onestamente, userò semplicemente uno List<ISomeData> (e rimuoverò completamente SomeDataCollection) a meno che non abbia uno scopo chiaro e dimostrabile per questo. E poi: potrei o incapsulare l'elenco o ereditare da Collection<T>.

Si può sempre aggiungere il metodo come metodo di estensione?

public static class Utils { 
    public static void SomeMethod(this IList<ISomeData> list) { 
     ... 
    } 
} 

poi:

var list = new List<ISomeData>(); 
... 
list.SomeMethod(); 
+0

In realtà non ho appena inserito un 'Elenco ' in 'SomeDataCollection', quello era solo un esempio: P. Io uso'Lista 'perché ha già qualche funzione per aggiungere, rimuovere, oggetti etc, e ho alcuni metodi e proprietà aggiuntivi nella mia classe' SomeDataCollection', che è specifica solo per digitare 'Lista '. –

+1

@John IMO avere qualcosa sia una lista * che * avere il proprio stato è un errore; molti framework/librerie * odio * che - binding, serializzazione, materializzazione, ecc. IMO dovresti avere un oggetto che * ha * quelle proprietà, e che anche * ha * un 'IList Items {get;}' –

2

Prima di tutto, perché si desidera scrivere new List<ISomeData> in una variabile definita come SomeDataCollection? E 'possibile che in realtà voleva SomeDataCollection someDatas = new SomeDataCollection();

Per quanto riguarda i messaggi di errore, il primo messaggio di errore vi dice che List<ISomeData> non deriva da SomeDataCollection, quindi non si può fare con qualcosa che si farebbe con SomeDataCollection, pertanto è non è possibile scriverlo alla variabile che è definita come SomeDataCollection (ad esempio, ad esempio se SomeDataCollection aveva public void someMethod() in esso, e più avanti nel codice che si chiama someDatas.someMethod()).

Il secondo messaggio di errore indica che i convertitori sono concepiti per la conversione tra tipi completamente diversi, non tra il tipo basato e il tipo derivato. Altrimenti, cosa ti aspetti di ottenere, ad es. nell'esempio seguente:

SomeDataCollection a = new SomeDataCollection(); 
List<ISomeData> b = (List<ISomeData>)a; 
SomeDataCollection c = (SomeDataCollection)b; 

Se si chiama il convertitore o no?

In pratica il codice che stai cercando di scrivere è molto sbagliato, quindi dobbiamo sapere che cosa stai cercando di fare, e quindi forse non sarei in grado di dirti la soluzione del tuo problema di root (e non del problema "come compilare questo codice").

2

Non è meglio per implementare un costruttore in SomeDataCollection?

public SomeDataCollection() : base() { } 

Questo naturalmente potrebbe essere completata con

public SomeDataCollection(IEnumerable<ISomeData> collection) 
    : base(collection) { } 

Poi si dovrebbe essere in grado di inizializzare il SomeDataCollection come questo, invece:

SomeDataCollection someData = new SomeDataCollection(); 
SomeDataCollection someOtherData = 
    new SomeDataCollection(collectionOfSomeData); 

e hanno ancora accesso a tutti i metodi pubblici e proprietà in List<ISomeData>.

0

Non ha problemi con i generici. In C# non è consentito convertire esplicitamente una classe base in una classe derivata.

Problemi correlati