使用 IEqualityComparer 基于 C# 中的两个属性生成不同的列表
Use IEqualityComparer to generate a distinct list based on two properties in C#
我正在尝试生成一个由两个字符串串联而成的项目列表框。我创建了一个实现 IEqualityComparer 的 class,我想让这个列表与众不同。
private void PopulateFamily()
{
var source = _mfgOrdersData
.Select(o => new FamilySelector(o.ItemWrapper.ItemClass, o.ItemWrapper.Family))
.Distinct()
.OrderBy(f => f.CodeFamily)
.ToList();
FamilyFilterListBox.DataSource = source;
FamilyFilterListBox.ValueMember = "Family";
FamilyFilterListBox.DisplayMember = "CodeFamily";
}
class FamilySelector : IEqualityComparer<FamilySelector>
{
public FamilySelector(string code, string family)
{
Code = code;
Family = family;
}
public string Code { get; set; }
public string Family { get; set; }
public string CodeFamily { get { return string.Format("{0}\t{1}", Code, Family); } }
public bool Equals(FamilySelector x, FamilySelector y)
{
return x.Code == y.Code && x.Family == y.Family;
}
public int GetHashCode(FamilySelector obj)
{
return obj.Code.GetHashCode() ^ obj.Family.GetHashCode();
}
}
问题是我得到的列表不明确。同一项目出现多次。
我认为 Equals() 或 GetHashCode() 没有正确实现。
目前您 运行 Distinct()
在 FamilySelector
个实例的集合上,这导致通过引用相等进行比较。
要正确执行,您应该将 IEqualityComparer
的实例传递给 Distinct()
调用:
var source = _mfgOrdersData
.Select(o => new FamilySelector(o.ItemWrapper.ItemClass, o.ItemWrapper.Family))
.Distinct(new FamilySelector())
.OrderBy(f => f.CodeFamily)
.ToList();
您应该将无参数构造函数添加到 FamilySelector
class 以便可以编译代码。
我还建议对 FamilySelector
class 进行小规模重构。目前它保存数据并进行比较。通常 IEqualityComparer 的实现是 data-less class ,它只执行比较:
class FamilyData
{
public FamilyData(string code, string family)
{
Code = code;
Family = family;
}
public string Code { get; set; }
public string Family { get; set; }
public string CodeFamily { get { return string.Format("{0}\t{1}", Code, Family); } }
}
class FamilySelector : IEqualityComparer<FamilyData>
{
public bool Equals(FamilyData x, FamilyData y)
{
return x.Code == y.Code && x.Family == y.Family;
}
public int GetHashCode(FamilyData obj)
{
return obj.Code.GetHashCode() ^ obj.Family.GetHashCode();
}
}
var source = _mfgOrdersData
.Select(o => new FamilyData(o.ItemWrapper.ItemClass, o.ItemWrapper.Family))
.Distinct(new FamilySelector())
.OrderBy(f => f.CodeFamily)
.ToList();
CodeFuller 的答案可以正常工作,但作为替代选项,您可以使用 MoreLINQ 及其 DistinctBy
方法,这将避免您需要创建一个单独的 class :
private void PopulateFamily()
{
var source = _mfgOrdersData
.Select(o => o.ItemWrapper)
.DistinctBy(o => new { o.ItemClass, o.Family })
.OrderBy(f => f.CodeFamily)
.ToList();
FamilyFilterListBox.DataSource = source;
FamilyFilterListBox.ValueMember = "Family";
FamilyFilterListBox.DisplayMember = "CodeFamily";
}
我假设您想要 select ItemWrapper
- 如果不查看所涉及的类型很难判断,但这看起来可能就是您想要的。
我正在尝试生成一个由两个字符串串联而成的项目列表框。我创建了一个实现 IEqualityComparer 的 class,我想让这个列表与众不同。
private void PopulateFamily()
{
var source = _mfgOrdersData
.Select(o => new FamilySelector(o.ItemWrapper.ItemClass, o.ItemWrapper.Family))
.Distinct()
.OrderBy(f => f.CodeFamily)
.ToList();
FamilyFilterListBox.DataSource = source;
FamilyFilterListBox.ValueMember = "Family";
FamilyFilterListBox.DisplayMember = "CodeFamily";
}
class FamilySelector : IEqualityComparer<FamilySelector>
{
public FamilySelector(string code, string family)
{
Code = code;
Family = family;
}
public string Code { get; set; }
public string Family { get; set; }
public string CodeFamily { get { return string.Format("{0}\t{1}", Code, Family); } }
public bool Equals(FamilySelector x, FamilySelector y)
{
return x.Code == y.Code && x.Family == y.Family;
}
public int GetHashCode(FamilySelector obj)
{
return obj.Code.GetHashCode() ^ obj.Family.GetHashCode();
}
}
问题是我得到的列表不明确。同一项目出现多次。 我认为 Equals() 或 GetHashCode() 没有正确实现。
目前您 运行 Distinct()
在 FamilySelector
个实例的集合上,这导致通过引用相等进行比较。
要正确执行,您应该将 IEqualityComparer
的实例传递给 Distinct()
调用:
var source = _mfgOrdersData
.Select(o => new FamilySelector(o.ItemWrapper.ItemClass, o.ItemWrapper.Family))
.Distinct(new FamilySelector())
.OrderBy(f => f.CodeFamily)
.ToList();
您应该将无参数构造函数添加到 FamilySelector
class 以便可以编译代码。
我还建议对 FamilySelector
class 进行小规模重构。目前它保存数据并进行比较。通常 IEqualityComparer 的实现是 data-less class ,它只执行比较:
class FamilyData
{
public FamilyData(string code, string family)
{
Code = code;
Family = family;
}
public string Code { get; set; }
public string Family { get; set; }
public string CodeFamily { get { return string.Format("{0}\t{1}", Code, Family); } }
}
class FamilySelector : IEqualityComparer<FamilyData>
{
public bool Equals(FamilyData x, FamilyData y)
{
return x.Code == y.Code && x.Family == y.Family;
}
public int GetHashCode(FamilyData obj)
{
return obj.Code.GetHashCode() ^ obj.Family.GetHashCode();
}
}
var source = _mfgOrdersData
.Select(o => new FamilyData(o.ItemWrapper.ItemClass, o.ItemWrapper.Family))
.Distinct(new FamilySelector())
.OrderBy(f => f.CodeFamily)
.ToList();
CodeFuller 的答案可以正常工作,但作为替代选项,您可以使用 MoreLINQ 及其 DistinctBy
方法,这将避免您需要创建一个单独的 class :
private void PopulateFamily()
{
var source = _mfgOrdersData
.Select(o => o.ItemWrapper)
.DistinctBy(o => new { o.ItemClass, o.Family })
.OrderBy(f => f.CodeFamily)
.ToList();
FamilyFilterListBox.DataSource = source;
FamilyFilterListBox.ValueMember = "Family";
FamilyFilterListBox.DisplayMember = "CodeFamily";
}
我假设您想要 select ItemWrapper
- 如果不查看所涉及的类型很难判断,但这看起来可能就是您想要的。