12
votes

Pourquoi ne peut-je pas passer la liste comme paramètre à une méthode qui accepte la liste ?

Le code suivant me donne cette erreur:

ne peut pas convertir de 'System.Collections.Generic.List' à 'System.Collections.Generic.List'.

Comment puis-je indiquer au compilateur que le client hérite effectivement de l'objet? ou est-ce que cela ne fait-il pas de l'héritage avec des objets de collecte génériques (envoi d'une liste < / code> obtient la même erreur). xxx


6 commentaires

Pourquoi prenez-vous la liste articles?


de faire une réflexion sur eux et les traiter dynamiquement


Vous pouvez toujours effectuer une réflexion sur un objet comme vous pouvez sur un objet .


Je vais envoyer des collections d'autres objets autres que le client, j'ai corrigé le code un peu pour refléter cela.


Ne pas répondre à votre question mais résoudre probablement votre problème :) Public Void FillsMartGrid (Liste Articles) pourrait être réécrit à: Public Void Fillsmartgrid (liste articles). Le compilateur déterminera ce que T est tellement vous n'avez pas besoin de le fournir et que vous faites simplement une réflexion dans le corps de la méthode qui devrait fonctionner pour tous vos types.


@Runefs +1 pour votre commentaire, résolu mon problème.


8 Réponses :


7
votes

C # (à l'heure actuelle) ne prend pas en charge la variance pour les types génériques.

Cependant, si vous utilisez C # 3.0, vous pouvez le faire: P>

FillSmartGrid( customers.Cast<object>() );


1 commentaires

+1 pour cela. Si vous êtes pré-version-3, vous pouvez écrire une méthode pour convertir la liste en une liste .




8
votes

C'est le problème de la covariance et ce n'est pas aussi facile que cela semble à première vue. C # 4 aura un certain soutien à cela.

Pour obtenir l'idée des problèmes, imaginez dans votre cas que cette distribution fonctionnerait réellement. Maintenant, vous avez une liste , laquelle par exemple dispose également d'une méthode Ajouter . Cependant, l'argument pour le add doit être un client , de sorte que cela viole clairement la mise en œuvre; La mise en œuvre ne fournit pas la méthode add (objet obj) .

Malheureusement, certains problèmes auraient pu être résolus en utilisant une conception intelligente (ER) des interfaces avec des méthodes génériques où la covariance est correcte, telle que pour Getenumerator.


0 commentaires

6
votes

C'est parce qu'une liste d'une classe n'est pas convertible vers une liste de la classe de base. C'est une décision délibérée de faire la sécurité de la langue. Cette question se pose souvent.

Ici est ma réponse standard de la manière de contourner le problème: p> xxx pré>

ou: p>

List<A> listOfA = new List<C>().Cast<A>().ToList();


0 commentaires

2
votes

Ceci a été couvert Ad-Nauseum dans de nombreuses autres réponses. La réponse courte est la suivante:

considère que j'ai ces variables: p> xxx pré>

maintenant, voici là qu'il arrête de compiler: P>

objects = customers; // sounds OK, since a Customer is an object, right?

objects.Add("foo"); 


0 commentaires

1
votes

au lieu de la liste de réussite qui ne fonctionne pas pour les raisons ci-dessus, pourriez-vous ne pas simplement passer simplement une référence d'objet, puis obtenir le type de liste après, un peu comme ...

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

namespace ConsoleApplication1 {

    class Customer {
        public int id;
        public string name;
    }

    class Monkey {

        public void AcceptsObject(object list) {

            if (list is List<Customer>) {
                List<Customer> customerlist = list as List<Customer>;
                foreach (Customer c in customerlist) {
                    Console.WriteLine(c.name);
                }
            }
        }
    }

    class Program {
        static void Main(string[] args) {

            Monkey monkey = new Monkey();
            List<Customer> customers = new List<Customer> { new Customer() { id = 1, name = "Fred" } };
            monkey.AcceptsObject(customers);
            Console.ReadLine();
        }
    }
}


0 commentaires

0
votes

Pourquoi le paramètre ne peut-il pas être de type IList?

Public Void FillsMartGrid (iList Articles)


0 commentaires

0
votes

Je suis d'accord avec la réponse de Winston Smith.

Je voulais juste souligner comme une alternative (bien que cela n'ait éventuellement pas le meilleur moyen de gérer la situation) que, lors de la liste code> Ne dérive pas de list code>, le client [] dérive de l'objet []. p>

Par conséquent, il est possible de le faire: P>

    {
        List<Customer> customers = new List<Customer>();
        // ...
        FillSmartGrid(customers.ToArray());
        // ...
    }

    public void FillSmartGrid(object[] items)
    {
    }


0 commentaires