1
votes

Comment convertir une «liste de classes» en une «liste de son interface»?

J'ai besoin de convertir une liste de classes en sa propre liste d'interfaces.

J'ai donc l'interface Demo_Interface et deux classes basées sur Demo_Interface , Maintenant, je crée une liste de classes comme List

Et j'ai une fonction avec le paramètre List .

Voici l'interface:

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);
            }
        }
    }
}

Voici le code complet:

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

Comment puis-je convertir List en List , lorsque Test_Class1 utilise Demo_Interface ?


2 commentaires

Quelle exception vous obtenez ici ...?


@PrasadTelkikar J'acceptais votre réponse pourquoi vous l'avez supprimée? ça a marché!


3 Réponses :


0
votes

Vous pouvez essayer

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

Ceci est sûr car nous ne convertissons pas directement testDemo sur son interface. Nous gardons testDemo tel quel et nous créons un résultat qui est la liste de Demo_Interface


0 commentaires

0
votes

Si vous avez seulement besoin d'énumérer via la List comme indiqué dans l'exemple, vous n'avez pas à effectuer de conversion explicite. List implémente IEnumerable qui est covariant type générique.

La covariance pour les collections permet la conversion implicite d'une collection d'un type plus dérivé en une collection d'un type moins dérivé

Dans votre cas, List implémente IEnumerable , mais puisque Test_Class1 implémente Demo_Interface , vous pouvez tirer parti de la variance des génériques et écrire, par exemple, quelque chose comme ceci:

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

// Method invocation
Output_Class(new_main_class.class_list_1);

Cela signifie essentiellement que votre Output_Class peut prendre l'argument IEnumerable et vous pourrez passer les deux listes sans les cast explicitement en utilisant Cast ou en créant une nouvelle collection en utilisant ToList .

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


2 commentaires

Merci pour votre méthode, j'ai accepté la réponse @PrasadTelkikar pour sa manière plus simple.


Bien sûr, prenez simplement en compte que ToList créera un nouvel objet, qui peut être facilement vérifié à l'aide de object.ReferenceEquals (testDemo, result) - renvoie false, ou en utilisant GetHashCode () sur chaque objet - renvoie des valeurs différentes



0
votes

Vous ne pouvez pas convertir une List en une List .

Si vous pouviez, et vous l'avez fait:

MethodINeedToPassTheArgumentTo(testClassList.Cast<IDemoInterface>);

... alors vous pourrez faire ceci:

void MethodINeedToPassTheArgumentTo(IEnumerable<IDemoInterface> items)

Mais la diffusion de la liste ne crée pas une nouvelle liste. Dans l'exemple ci-dessus, il n'y a pas deux listes. Il existe deux variables avec des références à la même liste. Si vous pouviez effectuer un cast comme indiqué ci-dessus, vous seriez en mesure de définir une liste d'un type et d'y ajouter un type complètement différent. Le compilateur empêche cela.

Vous pourriez

  • créez une nouvelle List et ajoutez-y les éléments. (Ou un tableau, IEnumerable, etc.)
  • Laissez la liste telle quelle et lancez simplement des éléments individuels lorsque / si vous en avez besoin. Dans la plupart des cas, nous n'aurions pas besoin de convertir quelque chose en tant qu'interface qu'il implémente.

Si nous devons convertir une collection entière sous un type différent, c'est probablement parce que nous la passons en argument.

C'est en fait une bonne raison pas de définir un argument de méthode comme un type de collection comme une List qui peut être modifiée à moins que ce ne soit notre intention pour modifier la collection.

C'est l'une des raisons pour lesquelles nous transmettons des types de collection moins spécifiques, comme IEnumerable.

Supposons que l'argument de la méthode ressemble à ceci: p >

interfaceList.Add(new SomeOtherClassThatImplementsTheInterface);

Nous pouvons maintenant prendre notre List et faire ceci:

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

Nous sommes ne pas créer une nouvelle collection. Nous transmettons une référence qui permet à l'autre méthode de visualiser les éléments de la liste, chacun individuellement cast comme IDemoInterface . Pour des raisons pratiques, il ressemble à l'autre méthode comme une collection de IDemoInterface , et ce n'est pas grave car l'autre élément ne peut pas modifier la collection. Il ne peut pas tenter d'ajouter d'autres types dans la List .


4 commentaires

merci pour l'excellente explication, alors comment la solution @PrasadTelkikar fonctionne-t-elle bien?


Parce qu'il ne s'agit pas de transformer la liste en une autre liste. Il crée une nouvelle List et place tous les éléments de la première liste dans la deuxième liste. C'est bon. Lorsque nous «jetons» quelque chose, nous ne créons pas un nouvel objet. Nous nous référons simplement à l'objet existant comme un type différent qu'il implémente. Nous pouvons seulement présenter quelque chose comme ce qu'il est déjà. Mais nous pouvons prendre un objet existant et l'utiliser pour créer un nouvel objet.


Je pense que créer une nouvelle liste avec uniquement les champs obligatoires est plus sûr que de la diffuser


Créer une nouvelle liste est plus sûr. Tout type de conversion qui n'est pas sûr ou qui n'est même pas possible est empêché par le compilateur, c'est pourquoi il ne vous permet pas de le lancer.