C# IEnumerable.GroupBy未分组
我在.NET中使用GroupBy扩展时遇到问题(4.5,无论VB.NET还是C#。示例是C#)。情况如下: 2个示例类:C# IEnumerable.GroupBy未分组,c#,.net,vb.net,equality,C#,.net,Vb.net,Equality,我在.NET中使用GroupBy扩展时遇到问题(4.5,无论VB.NET还是C#。示例是C#)。情况如下: 2个示例类: public class Office : IEquatable<Office> { public String Name { get; set; } public int Id { get; set; } public String Stuff { get; set; } // Compare by values pub
public class Office : IEquatable<Office>
{
public String Name { get; set; }
public int Id { get; set; }
public String Stuff { get; set; }
// Compare by values
public bool Equals(object obj)
{
if (obj is Office)
{
Office cmp = (Office) obj;
bool result = true;
result &= cmp.Id == this.Id;
result &= cmp.Name == this.Name;
result &= cmp.Stuff == this.Stuff;
return result;
}
else return false;
}
// Hashcode by values
public int GetHashCode()
{
var obj = new { Id = this.Id, Name = this.Name, Stuff = this.Stuff };
return obj.GetHashCode();
}
// IEquatable uses overriden Equals implementation
bool IEquatable<Office>.Equals(Office other)
{
return this.Equals(other);
}
}
public class Company
{
public Office Office { get; set; }
public String Name { get; set; }
}
公共类办公室:IEquatable
{
公共字符串名称{get;set;}
公共int Id{get;set;}
公共字符串填充{get;set;}
//按值比较
公共布尔等于(对象obj)
{
如果(obj是办公室)
{
办公室cmp=(办公室)obj;
布尔结果=真;
result&=cmp.Id==this.Id;
result&=cmp.Name==this.Name;
result&=cmp.Stuff==this.Stuff;
返回结果;
}
否则返回false;
}
//哈希值编码
public int GetHashCode()
{
var obj=new{Id=this.Id,Name=this.Name,Stuff=this.Stuff};
返回obj.GetHashCode();
}
//IEquatable使用覆盖的Equals实现
bool IEquatable.Equals(其他办公室)
{
返回此。等于(其他);
}
}
公营公司
{
公共办公室{get;set;}
公共字符串名称{get;set;}
}
类办公室重写了相等比较函数并实现了IEquatable接口,在这种情况下(据我所知),默认的EqualityComparer使用我的Equals实现
现在,我想根据公司所占的办公室将公司列表分组,如下所示:
List<Company> companies = new List<Company>();
Office office1 = new Office();
office1.Id = 1;
office1.Name = "Office";
office1.Stuff = "Stuff";
Office office2 = new Office();
office2.Id = 1;
office2.Name = "Office";
office2.Stuff = "Stuff";
Company date1 = new Company();
date1.Office = office1;
date1.Name = "Date 1";
Company date2 = new Company();
date2.Office = office2;
date2.Name = "Date 2";
companies.Add(date1);
companies.Add(date2);
IEnumerable<IGrouping<Office, Company>> grouping = companies.GroupBy(x => x.Office);
Console.WriteLine("Groups: " + grouping.Count()); // returns 2!!!
Console.WriteLine("Equals: " + office1.Equals(office2)); // returns true
Console.WriteLine("Hash 1: " + office1.GetHashCode()); // returns 2067935290
Console.WriteLine("Hash 2: " + office2.GetHashCode()); // returns 2067935290
IEqualityComparer cmp = EqualityComparer<Office>.Default;
Console.WriteLine("Comparer: " + cmp.Equals(office1, office2)); // returns true
上市公司=新上市公司();
Office office1=新办公室();
office1.Id=1;
office1.Name=“Office”;
office1.Stuff=“Stuff”;
Office office2=新办公室();
office2.Id=1;
office2.Name=“Office”;
office2.Stuff=“Stuff”;
公司日期1=新公司();
日期1.办公室=办公室1;
date1.Name=“date1”;
公司日期2=新公司();
日期2.办公室=办公室2;
date2.Name=“日期2”;
公司。添加(日期1);
公司。添加(日期2);
IEnumerable分组=companys.GroupBy(x=>x.Office);
Console.WriteLine(“Groups:+grouping.Count());//返回2!!!
Console.WriteLine(“等于:”+office1.Equals(office2));//返回true
Console.WriteLine(“散列1:+office1.GetHashCode());//返回2067935290
Console.WriteLine(“散列2:+office2.GetHashCode());//返回2067935290
IEqualityComparer cmp=EqualityComparer.Default;
Console.WriteLine(“Comparer:+cmp.Equals(office1,office2));//返回true
您可以看到,每个公司都有不同的Office对象,但在我的应用程序逻辑中,这些对象被认为是相等的。因此,调用office1.Equals(office2)
返回true,对象hashcodes是相等的,使用EqualityComparer.Default
的函数Equals
也返回true
现在的谜团是为什么调用GroupBy office返回两个组,即使办公室是“相等的”。文档说明使用了密钥的默认EqualityComparer()
感谢您的帮助~默认比较器正在调用
Object.GetHashCode
和IEquatable.Equals
这对您不起作用,因为您正在隐藏GetHashCode()
成员,而不是覆盖它
您的Equals
和GetHashCode
方法应该更改:
public **override** bool Equals(object obj)
public **override** int GetHashCode()
Jan,您可以在继承的方法
GetHashCode
和Equals
中设置修饰符override
,然后计数组等于1。这是因为,在Office比较器中,默认情况下调用方法Equal
,并调用Office
类中包含的非方法Equal
。正确,例如:
public class Office : IEquatable<Office>
{
public String Name { get; set; }
public int Id { get; set; }
public String Stuff { get; set; }
// Compare by values
public override bool Equals(object obj)
{
if (obj is Office)
{
Office cmp = (Office) obj;
bool result = true;
result &= cmp.Id == this.Id;
result &= cmp.Name == this.Name;
result &= cmp.Stuff == this.Stuff;
return result;
}
else return false;
}
// Hashcode by values
public override int GetHashCode()
{
var obj = new { Id = this.Id, Name = this.Name, Stuff = this.Stuff };
return obj.GetHashCode();
}
// IEquatable uses overriden Equals implementation
bool IEquatable<Office>.Equals(Office other)
{
return this.Equals(other);
}
}
公共类办公室:IEquatable
{
公共字符串名称{get;set;}
公共int Id{get;set;}
公共字符串填充{get;set;}
//按值比较
公共覆盖布尔等于(对象对象对象)
{
如果(obj是办公室)
{
办公室cmp=(办公室)obj;
布尔结果=真;
result&=cmp.Id==this.Id;
result&=cmp.Name==this.Name;
result&=cmp.Stuff==this.Stuff;
返回结果;
}
否则返回false;
}
//哈希值编码
公共覆盖int GetHashCode()
{
var obj=new{Id=this.Id,Name=this.Name,Stuff=this.Stuff};
返回obj.GetHashCode();
}
//IEquatable使用覆盖的Equals实现
bool IEquatable.Equals(其他办公室)
{
返回此。等于(其他);
}
}
您必须正确重写GetHashCode()
方法。您可能也不需要按位&=
运算符,只需使用&&组合布尔值,这样可能会缩短计算过程。我不明白“正确”一词是什么意思。类Office
重写此函数,并且office1
和office2
的哈希代码相等。匿名类型上的GetHashCode
将哈希并合并其所有成员。很好,伙计们。对于超负荷的GroupBy
(来自MSDN),默认的相等比较器默认值用于比较键。
Bingo。非常感谢。添加override
关键字修复了问题。建议的方法只是覆盖相等成员I可满足
在这种情况下没有任何交易。@Hamlet我不知道你的意思EqualityComparer.Default
将使用IEquatable.Equals
覆盖Object.Equals
(如果可用)。我的意思是,如果您已覆盖类的equality成员,则无需实现IEquatable
。在IEquatable.Equals
和overridedEquals
中有不同的行为已经注定了。明白了。在大多数情况下,唯一的区别应该是性能。