Pregunta

Siento que mi pregunta es bastante tonta, u otra forma de decirlo es: estoy demasiado perdido en mi código para ver una solución por el momento. Permanezca demasiado tiempo en un problema y su visión se volverá cada vez más estrecha & Gt; & Lt ;. Además, no soy lo suficientemente bueno con la herencia, el polimorfismo, etc.

Aquí está la idea: tengo una lista múltiple de clases derivadas, y me gustaría llamar a funciones genéricas en esas listas (acceder y modificar miembros de la clase base). Siento que hay algo que ver con la herencia, pero no logro hacer que funcione como quiero por ahora.

Aquí hay un ejemplo muy simple de lo que tengo la intención de hacer:

class Baseclass
{
    public int ID;
    public string Name;
}
class DerivedClass1 : Baseclass
{
}

private void FuncOnBase(List<Baseclass> _collection)
{
    // ...

    foreach (Baseclass obj in _collection)
    {
        ++obj.ID;
    }

    // ...
}
private void FuncTest()
{
    List<DerivedClass1> collection1 = new List<DerivedClass1>();
    collection1.Add(new DerivedClass1() { ID = 1 });
    collection1.Add(new DerivedClass1() { ID = 2 });
    collection1.Add(new DerivedClass1() { ID = 3 });

    FuncOnBase(collection1);   //  ==> forbidden, cannot convert the derived class list to the base class list
}
¿Fue útil?

Solución

Tengo que amar la variación. A List<DerivedClass1> es no a List<Baseclass> - de lo contrario, FuncOnBase podría intentar agregar un Baseclass a la lista, y el compilador no lo detectaría.

Un truco es usar un método genérico:

private void FuncOnBase<T>(List<T> _collection) where T : Baseclass
{
    // ...

    foreach (T obj in _collection)
    {
        obj.ID++;
    }

    // ...
}

En términos del ejemplo que presenté anteriormente, tenga en cuenta que podemos agregar un T a la lista; útil en particular si agregamos la restricción T : new(), o si pasamos (por ejemplo) un params T[].

Tenga en cuenta también que IEnumerable<T> se convierte en covariante en C # 4.0 / .NET 4.0, por lo que si pasa solo un IEnumerable<Baseclass> (en lugar de una lista) funcionaría " como es " :

private void FuncOnBase(IEnumerable<Baseclass> _collection)
{
   ///...
}

Otros consejos

Si solo está haciendo un foreach, declare FuncOnBase(IEnumerable<Baseclass> collection), al que puede llamar desde FuncTest así:

FuncOnBase(collection1.Cast<Baseclass>());

Cuando declaras un método con un parámetro List<T> pero solo usas sus funciones IEnumerable<T>, estás agregando restricciones de API que no significan nada en tu código.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top