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 ?
3 Réponses :
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
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;
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
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
List
et ajoutez-y les éléments. (Ou un tableau, IEnumerable, etc.) 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
.
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.
Quelle exception vous obtenez ici ...?
@PrasadTelkikar J'acceptais votre réponse pourquoi vous l'avez supprimée? ça a marché!