Pergunta

Eu sinto a minha pergunta é muito burro, ou outra forma de colocá-lo é: Eu estou muito perdida no meu código para ver uma solução alternativa para agora. Ficar muito tempo em um problema, e sua visão se torna mais estreito e mais estreito> <. Além disso, eu não sou bom o suficiente com herança, polimorfismo e assim

Aqui está a idéia: eu tenho lista múltiplo de classe derivada, e eu gostaria de chamar funções genéricas nessas listas (accesing e modificar os membros da classe base). Sinto que há algo a ver com a herança, mas não conseguem fazê-lo funcionar como eu quero por agora.

Aqui está um exemplo muito simples do que estou pretendendo fazer:

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
}
Foi útil?

Solução

variância amor

Gotta. A List<DerivedClass1> é não a List<Baseclass> -. Caso contrário, FuncOnBase poderia tentar adicionar um Baseclass à lista, eo compilador não manchá-lo

Um truque é usar um método genérico:

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

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

    // ...
}

Em termos do exemplo I apresentada acima - nota que somos capazes de adicionar um T à lista; útil, em particular, se adicionarmos a restrição T : new(), ou passar em (por exemplo) um params T[].

Note também que IEnumerable<T> se torna covariant em C # 4.0 / .NET 4.0, então se você passou em apenas uma IEnumerable<Baseclass> (em vez de uma lista) que iria funcionar "como é":

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

Outras dicas

Se você está apenas fazendo um foreach, FuncOnBase(IEnumerable<Baseclass> collection) declarar, que você pode chamar de FuncTest assim:

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

Quando você declarar um método com um parâmetro List<T> mas apenas usar seus recursos IEnumerable<T>, você está adicionando restrições de API que não significam nada em seu código.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top