Necesito emitir una lista de clase a su propia lista de interfaz.

Entonces tengo la interfaz Demo_Interface y dos clases basadas en Demo_Interface, Ahora creo una lista de clases como List<Test_Class1>

Y tengo una función con el parámetro List<Demo_Interface>.

Aquí está la interfaz:

       interface Demo_Interface
        {
            int test_int { get; set; }
        }

Aquí está el código completo:

using System;
using System.Collections.Generic;

namespace ConsoleApp3
{
    class Program
    {
        ///// Main Interface
        interface Demo_Interface
        {
            int test_int { get; set; }
        }

        //// Class 1 Based On Demo_Interface
        class Test_Class1 : Demo_Interface
        {
            public int test_int { get; set; }
            public string test_string { get; set; }

        }
        ///// Class 2 Based On Demo_Interface
        class Test_Class2 : Demo_Interface
        {
            public int test_int { get; set; }
            public string test_string { get; set; }

        }

        //// And Main Class
        class Main_Class
        {
            public List<Test_Class1> class_list_1 { get; set; }

            public List<Test_Class2> class_list_2 { get; set; }

            public Main_Class()
            {
                class_list_1 = new List<Test_Class1>() { };
                class_list_2 = new List<Test_Class2>() { };
            }
        }

        //// Console Main
        static void Main(string[] args)
        {
            var new_main_class = new Main_Class();

            Output_Class(new_main_class.class_list_1); ///// ==> ERROR

            Console.ReadKey();
        }

        //// Simple Function for do something with interface
        static void Output_Class(List<Demo_Interface> inter_input)
        {
            for (int i = 0; i < inter_input.Count; i++)
            {
                Console.WriteLine("{0} - {1}",i, inter_input[i].test_int);
            }
        }
    }
}

¿Cómo puedo transmitir List<Test_Class1> a List<Demo_Interface>, cuando Test_Class1 usa Demo_Interface ?

2
LinkinGarden 9 may. 2019 a las 14:43

3 respuestas

La mejor respuesta

Puedes probar

List<Test_Class1> testDemo = new List<Test_Class1>(); //list of Test_Class1 instances
List<Demo_Interface> result = testDemo.ToList<Demo_Interface>();

Esto es seguro porque no estamos enviando directamente testDemo a su interfaz. Mantenemos testDemo tal como está y estamos creando result, que es una lista de Demo_Interface

2
Prasad Telkikar 9 may. 2019 a las 12:22

Si solo necesita enumerar a través de List<Demo_Interface> como se muestra en el ejemplo, no tiene que hacer ningún tipo de conversión explícita. List<T> implementa IEnumerable<T> que es tipo genérico covariante.

La covarianza para colecciones permite la conversión implícita de una colección de un tipo más derivado a una colección de un tipo menos derivado

En su caso, List<Test_Class1> implementa IEnumerable<Test_Class1>, pero dado que Test_Class1 implementa Demo_Interface, puede aprovechar la variación genérica y escribir, por ejemplo, algo como esto:

IEnumerable<Test_Class1> col = new List<Test_Class1>();
IEnumerable<Demo_Interface> colImplicit = col;

Eso básicamente significa que su método Output_Class puede tomar el argumento IEnumerable<Demo_Interface> y podrá pasar ambas listas sin emitirlas explícitamente usando Cast<T> o crear una nueva colección usando ToList<T> .

private void Output_Class(IEnumerable<Demo_Interface> inter_input)
{
    // do your thing
}

// Method invocation
Output_Class(new_main_class.class_list_1);
2
Darjan Bogdan 9 may. 2019 a las 12:38

No puedes lanzar un List<ClassThatImplementsInterface> como List<IInterfaceItImplements>.

Si pudiste, e hiciste esto:

var classList = new List<ClassThatImplementsInterface>();
var interfaceList = (List<IInterfaceItImplements>)classList;

... entonces podrías hacer esto:

interfaceList.Add(new SomeOtherClassThatImplementsTheInterface);

Pero lanzar la lista no crea una nueva lista. En el ejemplo anterior no hay dos listas. Hay dos variables con referencias a la misma lista. Si pudiera emitir como se ve arriba, podría definir una lista de un tipo y agregarle un tipo completamente diferente. El compilador lo impide.

Tú podrías

  • cree un nuevo List<IDemoInterface> y agréguele los elementos. (O una matriz, IEnumerable, etc.)
  • Deje la lista tal como está y simplemente eche elementos individuales cuando sea necesario. En la mayoría de los casos, no necesitaríamos lanzar algo como una interfaz que implementa.

Si necesitamos lanzar una colección completa como un tipo diferente, es probable porque la estamos pasando como argumento.

De hecho, esa es una buena razón no para definir un argumento de método como un tipo de colección como List<T> que se puede modificar a menos que sea nuestra intención modificar la colección.

Esa es una razón por la que pasamos tipos de colección menos específicos, como IEnumerable<T>.

Supongamos que el argumento del método se ve así:

void MethodINeedToPassTheArgumentTo(IEnumerable<IDemoInterface> items)

Ahora podemos tomar nuestra List<TestClass> y hacer esto:

MethodINeedToPassTheArgumentTo(testClassList.Cast<IDemoInterface>);

No estamos creando una nueva colección. Estamos pasando una referencia que permite que el otro método vea los elementos en la lista, cada individualmente emitido como IDemoInterface. Para fines prácticos, se ve al otro método como una colección de IDemoInterface, y eso está bien porque el otro elemento no puede modificar la colección. No puede intentar agregar otros tipos en List<TestClass>.

1
Scott Hannen 9 may. 2019 a las 12:25