2016-08-04 68 views
-1

我想GroupBy记录列表中的多个对象,而不是简单的多个值。使用LINQ GroupBy按引用对象进行分组而不是值对象

我无法使用引用类型对象进行分组。我有一个包含Room,Type和DateTime的对象集合。房间,类型和日期时间都具有与它们相关联的属性。我已经将IE适配界面添加到了房间,并且这种类型认为这足以与群组一起使用。

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

为了使此代码正常工作,我必须调用我们对这些对象的特定属性进行分组。但问题是,我需要存储在分组的“密钥”复杂的对象,这样我就可以访问该组的具体信息

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

我最终不得不做^拿到分组工作,然而这些团体失去了我想要的复杂的东西。

+0

你的'房间'和'类型'应该重写'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. 您的RoomType可能会覆盖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; 
    } 
} 

现在,你甚至可以使用复杂类型作为一个匿名类型的属性。

相关问题