2016-08-04 1 views
-1

Je souhaite GroupBy plusieurs objets dans une liste d'enregistrements et pas simplement plusieurs valeurs.Utilisation de LINQ GroupBy pour regrouper par objets de référence au lieu d'objets valeur

J'ai du mal à faire fonctionner le regroupement avec des objets de type référence. J'ai une collection d'objets qui contiennent Room, Type et DateTime. Room, Type et DateTime ont tous des propriétés qui leur sont associées. J'ai déjà ajouté l'interface IEquateable à la pièce et le type pensant que cela suffirait à avec le groupe.

var groups = collection 
    .Where(g => g.Stage == InventoryStage.StageA) 
    .GroupBy(g => new {g.BirthDate, g.Room, g.Type}); 

Pour que ce code fonctionne, je dois appeler notre propriété spécifique sur ces objets pour le grouper. Le problème avec cela est que j'ai besoin des objets complexes stockés dans la « clé » du groupement afin que je puisse accéder à ces groupes d'informations spécifiques

var groups = collection 
    .Where(g => g.Stage == InventoryStage.StageA) 
    .GroupBy(g => new { 
    Birthday = g.BirthDate, 
    RoomName = g.Room.Name, 
    TypeName = g.Type.Name 
    }); 

Je finissent par avoir à faire^pour obtenir le regroupement au travail, Cependant, les groupes perdent l'objet compliqué que je voulais.

+0

Vos 'Room' et' Type' devraient remplacer 'Equals' +' GetHashCode' ou/et implémenter 'IEquatable '. –

Répondre

1

Pour accomplir cette tâche, vous pouvez remplacer Equals() et GetHashCode() pour vos classes:

public class Room { 
    public string Name; 
    public string Foo; 

    public override bool Equals(object obj) 
    { 
     Room other = obj as Room; 
     if (other == null) return false; 
     return this.Name == other.Name && this.Foo == other.Foo; 
    } 

    public override int GetHashCode() 
    { 
     return (Name.GetHashCode()^Foo.GetHashCode()).GetHashCode(); 
    } 
} 

Jetez un oeil here par exemple plus compliqué

0
  1. Votre pourrait remplacer Equals + GetHashCode dans la classe principale qui contient ces propriétés au lieu d'utiliser le type anonyme dans le GroupBy. Une autre approche consisterait à implémenter un IEqualityComparer<YourMainType> personnalisé. Vous pouvez en utiliser une instance pour la surcharge de GroupBy.
  2. votre Room et Type peuvent remplacer Equals + GetHashCode ou/et implémenter IEquatable<T>. La mise en œuvre IEquatable/IEquatable<> n'est pas suffisante car GroupBy utilise d'abord GetHashCode pour déterminer le code haché avant de commencer à comparer les objets avec Equals, c'est le filtre initial.

Voici un exemple pour la classe de chambre:

public class Room:IEquatable<Room> 
{ 
    public Room(string name) 
    { 
     Name = name; 
    } 

    public string Name { get; } 

    /// <summary>Indicates whether the current object is equal to another object of the same type.</summary> 
    /// <returns>true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.</returns> 
    /// <param name="other">An object to compare with this object.</param> 
    public bool Equals(Room other) 
    { 
     return String.Equals(this.Name, other?.Name); 
    } 

    /// <summary>Determines whether the specified object is equal to the current object.</summary> 
    /// <returns>true if the specified object is equal to the current object; otherwise, false.</returns> 
    /// <param name="obj">The object to compare with the current object. </param> 
    public override bool Equals(object obj) 
    { 
     if(ReferenceEquals(this, obj)) 
      return true; 
     Room other = obj as Room; 
     return this.Equals(other); 
    } 

    /// <summary>Serves as the default hash function. </summary> 
    /// <returns>A hash code for the current object.</returns> 
    public override int GetHashCode() 
    { 
     return Name?.GetHashCode() ?? Int32.MinValue; 
    } 
} 

Maintenant, vous pouvez même utiliser des types complexes comme une propriété d'un type anonyme.