Conversion of list of interfaces in object list: (ListInterface in ListObject)

1

I need to convert a IList<Interface> to a List<Objeto> .

See the example:

public interface IObjetosBase
{
     IList<IObjetosBase> get();
}

public class ObjetosBase : IObjetosBase
{
    public virtual IList<IObjetosBase> get() { ... }
}

public class Aluno : ObjetosBase 
{
    public override IList<IObjetosBase> get() { 
      //Aqui eu quero retornar um List<Aluno>
    }
}

Sample codes for didactic effect, may contain errors

What is the correct way to do this conversion?

    
asked by anonymous 22.07.2017 / 14:33

4 answers

3

What you want to do is not possible, C # does not support covariance for return type. One can think of another solution depending on the problem, but in fact the example is anti-didactic, so it is even difficult to find a real solution.

One of the things you can do is create a list with the same base type.

public interface IObjetosBase {
     IList<IObjetosBase> Get();
}

public class ObjetosBase : IObjetosBase {
    public virtual IList<IObjetosBase> Get() { return new List<IObjetosBase>(); }
}

public class Aluno : ObjetosBase {
    public override IList<IObjetosBase> Get() { return new List<IObjetosBase>() { new Aluno() }; }
}

I placed GitHub for future reference .

    
22.07.2017 / 15:22
2

Your problem is not very clear but I believe you can use the keyword new instead of overwriting the method:

 namespace ClassLibrary1
{
    public interface IObjetosBase
    {
        IList<IObjetosBase> get();
    }

    public class ObjetosBase : IObjetosBase
    {
        public virtual IList<IObjetosBase> get() { return new List<IObjetosBase>(); }
    }

    public class Aluno : ObjetosBase
    {
        public new IList<Aluno> get()
        {
            return new List<Aluno>();
        }
    }
}

I could not test the code now for lack of time, but I also believe that the Aluno class should not return a list of Aluno , Maybe a Turma should return a list of Aluno or else , a% repository of%.

Edit:

Or You can populate the list of Alunos with objects of type IObjetosBase :

public class Aluno : ObjetosBase
{
    public override IList<IObjetosBase> get()
    {
        List<IObjetosBase> lista = new List<IObjetosBase>();
        Aluno obj;
        for (int i = 0; i < 10; i++)
        {
            obj = new Aluno();
            lista.Add(obj);
        }
        return lista;
    }
}

And then to scroll through objects of type Aluno :

    public void Processo()
    {
        IList<IObjetosBase> lista = this.get();
        //Se for necessário checar o tipo do objeto:
        foreach (var obj in lista)
        {
            if (obj is Aluno)
            {
                Aluno a = obj as Aluno;
            }
        }

        //Se não for necessário checar o tipo do objeto:
        foreach (Aluno obj in lista)
        {

        }
    }
    
22.07.2017 / 17:05
1

I think I understand what you want. You want a Student type class containing a list of IObjectBase interfaces to return a list of Student type objects.

There are several ways to do this, and even some, if done directly, can give compilation error. The closest you can get to this, in my view, would be: (i) Creating a new GetAlunos function; or (ii) Converting the function return to what you want.

Two plausible suggestions follow the code below. None gave compile error to me.

    using System.Linq;
    using System.Collections.Generic;

    public interface IObjetosBase
    {
        IList<IObjetosBase> Get();
    }

    public class ObjetosBase : IObjetosBase
    {
        protected IList<IObjetosBase> listaObjetosBase;

        public ObjetosBase()
        {
            List<ObjetosBase> objBase = new List<ObjetosBase>(); // Crie uma lista para o tipo de objeto que você deseja
            listaObjetosBase = objBase.Select(ele => ele as IObjetosBase).ToList(); // Converta essa lista para uma lista de interfaces
        }
        public virtual IList<IObjetosBase> Get()
        {
            return listaObjetosBase;
        }
    }

    public class Aluno : ObjetosBase
    {
        public override IList<IObjetosBase> Get()
        {
            return listaObjetosBase;
        }
        public List<Aluno> GetAlunos()  // Implementação alternativa e direta usando Linq
        {
            return listaObjetosBase.OfType<Aluno>().Select(elem => elem as Aluno).ToList();
        }
    }

    public static void Main(params string[] args)
    {
        Aluno alunoQualquer = new Aluno();
        List<Aluno> outrosAlunos;
        // 1ª opção: Selecione os alunos separadamente pelo Get() sobreescrito usando Linq
        outrosAlunos = alunoQualquer.Get().OfType<Aluno>().Select(elem => elem as Aluno).ToList();
        // 2ª opção: Use a função GetAlunos(), que já faz isso por si só
        outrosAlunos = alunoQualquer.GetAlunos();
    }

There are other forms (eg use of generic types), but I find this method to be more straightforward and succinct for you.

    
22.07.2017 / 22:28
0

I found your example extremely weird and impractical, but you can do it using generic types. It is the only possible way if you want to maintain the polymorphism and references of your lists.

See: link

public interface IPessoa<T> where T : IPessoa<T>
{
    string Nome { get; set; }
    IList<T> Get();
}

public class Pessoa<T> : IPessoa<Pessoa<T>> where T : Pessoa<T>
{
    public string Nome { get; set; }

    public virtual IList<Pessoa<T>> Get()
    {
        return new List<Pessoa<T>>();
    }
}

public class Aluno : Pessoa<Aluno>
{
    public override IList<Pessoa<Aluno>> Get()
    {
        return new List<Pessoa<Aluno>>();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var aluno = new Aluno();

        IList<Pessoa<Aluno>> alunos = aluno.Get();
        alunos.Add(new Aluno { Nome = "Vítor"});
        alunos.Add(new Aluno { Nome = "Bruno" });

        foreach (Pessoa<Aluno> a in alunos)
            Console.WriteLine(a.Nome);

        Console.ReadLine();
    }
}

You can read more about generic types here: link

    
23.07.2017 / 02:06