.net - vacia - Lanzar una colección genérica al tipo base
recorrer list c# (6)
Esto se llama co-varianza y aunque actualmente no es compatible con genéricos en .net, se agregará en el marco 4.0 (junto con el opuesto, que es contra-varianza).
Este excelente video de PDC 2008 es una sesión sobre el futuro de C # dada por Anders Hejlsberg:
Tengo un IList<DerivedClass>
que quiero ICollection<BaseClass>
a ICollection<BaseClass>
pero cuando intento un lanzamiento explícito, obtengo null
. ¿Es posible hacer esto sin crear y completar una nueva colección?
Editar: como solo quiero leer de la colección, cambié a usar un método genérico:
public void PopulateList<BaseClass>(ICollection<T> collection)
Entonces puedo pasarle un IList<DerivedClass>
. ¿Hay una buena manera de almacenar en caché esta lista para que pueda actualizarla cuando sea necesario? Mi primera inclinación es usar:
Object cachedCollection;
Type cachedType;
public void PopulateList<BaseClass>(ICollection<T> collection) {
cachedCollection = collection;
cachedType = T;
// other stuff...
}
private void Refresh() {
PopulateList<cachedType>(cachedCollection as ICollection<cachedType>);
}
¿Alguien tiene una mejor manera de hacer esto?
La respuesta corta es no." Debería crear una nueva colección con el nuevo tipo de BaseClass y completarla.
Si lo piensas, tiene sentido. Si pudieras simplemente "lanzar" tu colección a BaseClass, podrías pegar en ella algo que era del tipo "BaseClass", forzando así a un objeto BaseClass simple a una Colección DerivedClass. Esto sería contrario al propósito de crear una Colección con Type-Safety.
En el caso extremo, si tuviera dos clases derivadas, Foo y Bar, podría forzar los objetos Bar en una colección de objetos Foo volviendo a escribir la colección en una colección de BaseClass.
No creo que sea posible, y de hecho no debería ser:
class BaseClass {}
class DerivedClass : BaseClass {}
class OtherClass : BaseClass {}
void test()
{
List<DerivedClass> list = new List<DerivedClass>();
slice(list); //you want to do this
}
void slice(IList<BaseClass> list)
{
//yikes! adding OtherClass to List<DerivedClass>
list.Add(new OtherClass());
}
No se admite el cambio entre contenedores genéricos de clases derivadas y clases base. (Funciona con matrices) Es posible escribir un convertidor de tipo para realizar el cambio de forma razonablemente limpia sin copiar elementos manualmente entre las listas.
Consulte este enlace para obtener una descripción del problema / limitación y una solución: http://www.25hoursaday.com/weblog/CommentView.aspx?guid=AF7AA888-A227-454C-8687-71FA77186064
Abajo en la parte inferior hay una buena versión genérica habilitada.
Si .NET 3.5 es una opción, puede usar el método de extensión Cast<T>
en System.Core.dll
para obtener un IEnumerable<T>
solo IEnumerable<T>
para la colección:
using System.Linq;
...
private void Refresh() {
PopulateList( cachedCollection.Cast<cachedType>( ) );
}
Puede convertir cada elemento en un nuevo iterador:
var collectionOfBase = (collectionOfDerived as IEnumerable).Cast<BaseClass>();