2016-08-04 8 views
-1

Я хочу GroupBy несколько объектов в списке записей, а не просто нескольких значений.Использование LINQ GroupBy для группировки по ссылочным объектам вместо объектов значений

У меня возникли проблемы с группировкой для работы с объектами ссылочного типа. У меня есть коллекция объектов, которые содержат Room, Type и DateTime. В комнате, типе и DateTime есть свойства, связанные с ними. Я уже добавил интерфейс IEquateable в комнату и тип мышления, которого было бы достаточно, чтобы с группой.

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

Для того чтобы этот код работал, я должен называть наше конкретное свойство на этих объектах группой. Проблема в том, что мне нужны сложные объекты, хранящиеся в «Key» в группировке, так что я могу получить доступ, что группы конкретной информации

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

Я в конечном итоге того, чтобы сделать ^, чтобы получить группировку на работу, однако группы теряют сложный объект, который я хотел.

+0

Ваши 'Room' и' Type' должны переопределять 'Equals' +' GetHashCode' или/и реализовывать 'IEquatable '. –

ответ

1

Для выполнения этой задачи, вы можете переопределить Equals() и GetHashCode() методы для ваших классов:

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

Посмотрите here для более сложного примера

0
  1. Ваш может переопределить Equals + GetHashCode в основном классе, который содержит эти свойства вместо использования анонимного типа в GroupBy.
  2. Другим подходом было бы реализовать пользовательский IEqualityComparer<YourMainType>. Вы можете использовать его экземпляр для перегрузки GroupBy.
  3. Ваш Room и Type могут переопределить Equals + GetHashCode и/или осуществить IEquatable<T>. Внедрение IEquatable/IEquatable<> недостаточно, так как GroupBy сначала использует GetHashCode, чтобы определить хэш-код, прежде чем он начнет сравнивать объекты с Equals, так что это начальный фильтр.

Вот пример для класса номера:

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

Теперь вы можете даже использовать сложные типы как свойство анонимного типа.

 Смежные вопросы

  • Нет связанных вопросов^_^