Conversion of interface list into object list: (List<Interface> in List<Object>)

Asked

Viewed 708 times

1

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

Take 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 right way to accomplish this conversion?

4 answers

3


What you want to do is not possible, C# does not support covariance 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 put in the Github for future reference.

2

It is not very clear your problem but I believe you can use 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 couldn’t test the code now for lack of time, but I also believe the class Aluno should not return a list of Aluno, Perhaps a Class Turma yes should return a list of Aluno or a repository Alunos.

Edit:

Or You can popular the list of IObjetosBase with objects of the type Aluno:

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 go through the objects of the 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)
        {

        }
    }
  • The new does not generate polymorphism and it seems that he wants it.

  • Yeah, I put in to have an extra option for the colleague, his code is not very clear what the need is most always try to help. I edited and put another way that I believe, can help you

1

I think I understand what you want. You want a Student type class containing a list of Iobjetobase 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 by the code below. No compilation error for 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 (e.g., use of generic types), but I think this method is more direct and succinct to your case.

0

I found your example extremely strange 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.

Behold: https://dotnetfiddle.net/FKVzwE

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: http://www.macoratti.net/15/04/c_mgen1.htm

Browser other questions tagged

You are not signed in. Login or sign up in order to post.