使用LINQ GroupBy按引用对象进行分组而不是值对象
问题描述:
我想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
});
我最终不得不做^拿到分组工作,然而这些团体失去了我想要的复杂的东西。
答
为了完成这个任务,你可以重写的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更复杂的例子
答
- 您可以覆盖
Equals
+GetHashCode
在保留这些属性的主类中,而不是在GroupBy
中使用匿名类型。 - 另一种方法是实施自定义
IEqualityComparer<YourMainType>
。您可以将其实例用于GroupBy
的超载。 - 您的
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;
}
}
现在,你甚至可以使用复杂类型作为一个匿名类型的属性。
你的'房间'和'类型'应该重写'Equals' +'GetHashCode'或/并实现'IEquatable'。 –