2012-06-27 25 views
7

tengo una clase de colección como esta:C# conversión implícita de clase base

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

pero no puede hacer esto:

SomeDataCollection someDatas = new List<ISomeData>(); 

No se puede implícitamente convertir el tipo List<ISomeData>-SomeDataCollection . existe una conversión explícita (¿falta un yeso?)

así que intenta crear un conversor implícita dentro de la clase SomeDataCollection colección:

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

pero dijo que no puedo crear dicho convertidor:

SomeDataCollection.implicit operator SomeDataCollection(List<ISomeData>): conversiones definidas por el usuario hacia o desde una clase base no se les permite

Y cuando yo echo de esta manera:

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

que arroja un error que dice:

System.InvalidCastException: No se puede convertir objeto de tipo List<ISomeData> para escribir SomeDataCollection.

¿Cómo puedo hacer esto:

SomeDataCollection someDatas = new List<ISomeData>(); 

sin conseguir un error? Por favor ayuda. Gracias por adelantado.

+0

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

Respuesta

6

A new List<ISomeData>(); sigue siendo solo List<ISomeData>. No es un SomeDataCollection. El punto de subclases es que la subclase podría tener un estado extra, etc., pero un objeto (una vez creado) nunca cambia.

No tiene permiso para crear operadores entre tipos en la misma jerarquía, ya que eso anularía el comportamiento de conversión habitual y esperado.

Usted podría utilizar simplemente:

var data = new SomeDataCollection(); 

Sin embargo debo añadir que, francamente, no suele ser útil a la subclase List<T>. No menos importante, no expone ningún método virtual útil, por lo que no puede modificar el comportamiento. Honestamente, simplemente usaría un List<ISomeData> (y eliminaría SomeDataCollection por completo) a menos que tenga un propósito claro y demostrable. Y luego: podría encapsular la lista o heredar desde Collection<T>.

¿Siempre podría simplemente agregar el método como método de extensión?

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

a continuación:

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

En realidad, no puse una recién instanciada 'List ' en 'SomeDataCollection', eso fue solo una muestra: P. Utilizo 'List 'porque ya tiene alguna función para agregar, eliminar, etc. objetos, y tengo algunos métodos y propiedades adicionales en mi clase' SomeDataCollection' que es específica solo para escribir 'List '. –

+1

@John IMO tener algo tanto ser una lista * y * tener su propio estado es un error; muchos frameworks/bibliotecas * odian * que - enlace, serialización, materialización, etc. IMO debería tener un objeto que * tenga * esas propiedades, y que también * tenga * un 'IList Items {get;}' –

2

Antes que nada, ¿por qué quiere escribir new List<ISomeData> en una variable definida como SomeDataCollection? Es posible que en realidad quería SomeDataCollection someDatas = new SomeDataCollection();

En cuanto a los mensajes de error, el primer mensaje de error que dice que List<ISomeData> no se deriva de SomeDataCollection, por lo tanto, no se puede hacer con ella algo que se haría con SomeDataCollection, por lo tanto, no se puede escribir en la variable que se define como SomeDataCollection (imagínese, por ejemplo, si SomeDataCollection tenía public void someMethod() en ella, y más tarde en el código llamaría al someDatas.someMethod()).

El segundo mensaje de error indica que los convertidores están destinados a la conversión entre tipos completamente diferentes, no entre el tipo basado y derivado. De lo contrario, ¿qué esperarías obtener, p. en el siguiente ejemplo:

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

¿Debería llamar a su convertidor o no?

Básicamente, para empezar, el código que intentas escribir está muy mal, así que necesitamos saber qué estás tratando de hacer, y entonces quizás podamos darte la solución de tu problema raíz (y no del problema "cómo hacer compilar este código").

2

No es mejor para implementar un constructor en SomeDataCollection?

public SomeDataCollection() : base() { } 

Esto podría, por supuesto, ser complementado con

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

Entonces usted debe ser capaz de inicializar su SomeDataCollection esta forma:

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

y seguir teniendo acceso a todos los métodos públicos y propiedades en List<ISomeData>.

0

No hay problema con los genéricos. En C# no está permitido convertir explícitamente una clase base en una clase derivada.

Cuestiones relacionadas