IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Linq Where() et Cast


Sujet :

C#

  1. #1
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut Linq Where() et Cast
    Bonjour,

    J'ai un souci de typage et de spécialisation avec la méthode Where() sur une liste.

    Voici mes classes :
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    public class Vehicule
    {
        public int id;
        public string name;
        public string type = "vehicule";
    }
     
    public class Voiture : Vehicule
    {
        public Voiture()
        {
              type = "voiture";
        }
    }
     
    public class Camion : Vehicule
    {
        public Camion()
        {
              type = "camion";
        }
    }

    Et mon code qui coince :
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    IEnumerable<Vehicule> vehicules = new() { new Voiture() { id=1, name="Voiture 1" }, new Camion() { id=1, name="Camion 1" }};
    IEnumerable<Voiture> voitures = (IEnumerable<Voiture>)vehicules.Where(a => a.type == "voiture");

    Ca plante sur la seconde ligne.
    Pourtant, le Where ne retourne bien que des Voitures... Comment faire pour lui faire comprendre ?
    On ne jouit bien que de ce qu’on partage.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 198
    Points : 12 774
    Points
    12 774
    Par défaut
    Bonjour,
    Je viens de tester ton code, mais VS n'en veut pas en l'état:
    Gravité Code Description Projet Fichier Ligne État de la suppression
    Erreur CS1061 'IEnumerable<Vehicule>' ne contient pas de définition pour 'Add' et aucune méthode d'extension accessible 'Add' acceptant un premier argument de type 'IEnumerable<Vehicule>' n'a été trouvée (une directive using ou une référence d'assembly est-elle manquante*?) TestEFCoreMultibases C:\Users\f_demilly\source\repos\TestEFCore\TestEFCoreMultibases\Program.cs 40 Actif
    Erreur CS0144 Impossible de créer une instance du type abstract ou de l'interface 'IEnumerable<Vehicule>' TestEFCoreMultibases C:\Users\f_demilly\source\repos\TestEFCore\TestEFCoreMultibases\Program.cs 40 Actif

    Mais celui-ci fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    List<Vehicule> vehicules = new() { new Voiture() { id=1, name="Voiture 1" }, new Camion() { id=1, name="Camion 1" }};
    List<Voiture> voitures = vehicules.Where(a => a.type == "voiture") as List<Voiture>;
    Tatayo.

  3. #3
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Bonjour Tatayo,

    En effet, par mesure de simplification j'avais réécrit le code sans forcément le tester.

    J'ai corrigé en ajoutant un .Cast<Voiture>() après le Where()

    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        public class Response
        {
            public List<ResponseElement> ResponseElements = new();
     
            public IEnumerable<ResponseQuery> ResponseQueries => ResponseElements.Where(a => a.Type == ResponseElement.ResponseType.Query).Cast<ResponseQuery>();
     
            public IEnumerable<ResponseCatalog> ResponseGetcat => ResponseElements.Where(a => a.Type == ResponseElement.ResponseType.Getcat).Cast<ResponseCatalog>();
     
            public IEnumerable<ResponseXQuery> ResponseXQueries => ResponseElements.Where(a => a.Type == ResponseElement.ResponseType.XQuery).Cast<ResponseXQuery>();
     
            [...]
        }

    Merci d'avoir regardé
    On ne jouit bien que de ce qu’on partage.

  4. #4
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 674
    Points : 5 259
    Points
    5 259
    Par défaut
    il y a plus simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IEnumerable<Voiture> voitures = vehicules.OfType<Voiture>();

  5. #5
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 899
    Points : 1 916
    Points
    1 916
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    IEnumerable<Vehicule> vehicules = new() { new Voiture() { id=1, name="Voiture 1" }, new Camion() { id=1, name="Camion 1" }};
    IEnumerable<Voiture> voitures = (IEnumerable<Voiture>)vehicules.Where(a => a.type == "voiture");
    Bien qu'il est possible de cast un Vehicule en Voiture par le mécanisme de l'héritage, cette relation n'existe pas entre un IEnumerable<Vehicule> et un IEnumerable<Voiture>, de même que s'il est par exemple possible de cast un int en double il n'est pas possible de cast un int[] en double[]. Il aurait par exemple été possible de cast un IEnumerable<Vehicule> en IQueryable<Vehicule> puisqu'ici la relation d'héritage existe.

    Je pense que la meilleure approche est celle de popo avec OfType<T>, qui va filtrer les éléments sur leur type sous-jacent (contrairement à Cast<T> qui assume que le type sous-jacent est compatible) et va convertir le type déclaré ; la collection retournée peut-être vide mais il n'y aura au moins pas d'exception levée sur les éléments incompatibles.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. LINQ : WHERE IN
    Par smarties dans le forum Linq
    Réponses: 8
    Dernier message: 08/09/2011, 10h42
  2. [Linq to SQL] Clause Where dynamique
    Par Kamishu dans le forum Accès aux données
    Réponses: 2
    Dernier message: 14/08/2008, 14h17
  3. [LINQ] Where avec une Generic.List
    Par Firedeal dans le forum Framework .NET
    Réponses: 2
    Dernier message: 28/03/2008, 15h32
  4. [LINQ To SQL] Clauses WHERE dynamiques
    Par SaumonAgile dans le forum Accès aux données
    Réponses: 7
    Dernier message: 23/02/2008, 01h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo