gpt4 book ai didi

c# - 匿名类型的 IEqualityComparer

转载 作者:太空狗 更新时间:2023-10-29 21:01:36 25 4
gpt4 key购买 nike

首先我看到IEqualityComparer for anonymous type那里的答案没有回答我的问题,很明显我需要一个 IEqualityComparer不和IComparer用于 Linq 的 Distinct()方法。我也检查了其他答案,但这些都没有解决方案......

问题

我有一些代码可以从 DataTable 中操作和提取记录

var glext = m_dtGLExt.AsEnumerable();
var cflist =
(from c in glext
orderby c.Field<string>(m_strpcCCType),
c.Field<string>(m_strpcCC),
c.Field<string>(m_strpcCCDesc),
c.Field<string>(m_strpcCostItem)
select new
{
CCType = c.Field<string>(m_strpcCCType),
CC = c.Field<string>(m_strpcCC),
CCDesc = c.Field<string>(m_strpcCCDesc),
CostItem = c.Field<string>(m_strpcCostItem)
}).Distinct();

但我需要 distinct 方法不区分大小写。把我扔在这里的是匿名类型的使用。

尝试的解决方案 1

如果我有 SomeClass它有我显然可以做的具体对象

public class SumObject
{
public string CCType { get; set; }
public string CC { get; set; }
public string CCDesc { get; set; }
public string CostItem { get; set; }
}

我当然可以做到这一点

List<SumObject> lso = new List<SumObject>() 
{
new SumObject() { CCType = "1-OCC", CC = "300401", CCDesc = "Rooney", CostItem = "I477" },
new SumObject() { CCType = "1-OCC", CC = "300401", CCDesc = "Zidane", CostItem = "I677" },
new SumObject() { CCType = "1-OCC", CC = "300401", CCDesc = "Falcao", CostItem = "I470" },
};
var e = lso.Distinct(new SumObjectComparer()); // Great :]

在哪里

class SumObjectComparer : IEqualityComparer<SumObject>
{
public bool Equals(SumObject x, SumObject y)
{
if (Object.ReferenceEquals(x, y))
return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
return x.CCType.CompareNoCase(y.CCType) == 0 &&
x.CC.CompareNoCase(y.CC) == 0 &&
x.CCDesc.CompareNoCase(y.CCDesc) == 0 &&
x.CostItem.CompareNoCase(y.CostItem) == 0;
}

public int GetHashCode(SumObject o)
{
if (Object.ReferenceEquals(o, null))
return 0;
int hashCCType = String.IsNullOrEmpty(o.CCType) ?
0 : o.CCType.ToLower().GetHashCode();
int hashCC = String.IsNullOrEmpty(o.CC) ?
0 : o.CC.ToLower().GetHashCode();
int hashCCDesc = String.IsNullOrEmpty(o.CCDesc) ?
0 : o.CCDesc.ToLower().GetHashCode();
int hashCostItem = String.IsNullOrEmpty(o.CostItem) ?
0 : o.CostItem.ToLower().GetHashCode();
return hashCCType ^ hashCC ^ hashCCDesc ^ hashCostItem;
}
}

但是,在上面的 Linq 查询中使用匿名类型让我很困惑。

尝试的解决方案 2

为了尝试另一种解决方案(并且因为我在其他地方也有同样的问题),我生成了以下通用比较器类

public class GenericEqualityComparer<T> : IEqualityComparer<T>
{
Func<T, T, bool> compareFunction;
Func<T, int> hashFunction;

public GenericEqualityComparer(Func<T, T, bool> compareFunction, Func<T, int> hashFunction)
{
this.compareFunction = compareFunction;
this.hashFunction = hashFunction;
}

public bool Equals(T x, T y) { return compareFunction(x, y); }
public int GetHashCode(T obj) { return hashFunction(obj); }
}

这样我就可以尝试做

var comparer = new GenericEqualityComparer<dynamic>(
(x, y) => { /* My equality stuff */ },
o => { /* My hash stuff */ });

但这会将返回值转换为 IEnumerable<dynamic>这反过来会影响我即将使用的 cflist , 所以在下面的查询中 join失败。

 var cf = 
(from o in cflist
join od in glext
on new { o.CCType, o.CC, o.CCDesc, o.CostItem } equals new
{
CCType = od.Field<string>(m_strpcCCType),
CC = od.Field<string>(m_strpcCC),
CCDesc = od.Field<string>(m_strpcCCDesc),
CostItem = od.Field<string>(m_strpcCostItem)
}
into c
select new { ... }

我不想在 IEnumerable<T> 之间进行丑陋的转换由于大量使用此代码...

问题

有没有办法创建我的 IEquailityComparer对于我的匿名类型?

感谢您的宝贵时间。

最佳答案

Is there a way I can create my an IEquailityComparer for my anonymous types?

当然。您只需要使用类型推断。例如,你可以有这样的东西:

public static class InferredEqualityComparer
{
public static IEqualityComparer<T> Create<T>(
IEnumerable<T> example,
Func<T, T, bool> equalityCheck,
Func<T, int> hashCodeProvider)
{
return new EqualityComparerImpl<T>(equalityCheck, hashCodeProvider);
}

private sealed class EqualityComparerImpl<T> : IEqualityComparer<T>
{
// Implement in the obvious way, remembering the delegates and
// calling them appropriately.
}
}

然后:

var glext = m_dtGLExt.AsEnumerable();
var query = from c in glext
orderby ...
select new { ... };
var comparer = InferredEqualityComparer.Create(query,
(x, y) => { ... },
o => { ... }
);
var distinct = query.Distinct(comparer);

基本上,该方法的第一个参数只是用于类型推断,以便编译器可以计算出用于 lambda 表达式参数的类型。

可以通过创建匿名类型的样本提前创建比较器:

var sample = new[] { new { ... } };
var comparer = InferredExqualityComparer.Create(sample, ...);
var distinct = (... query here ... ).Distinct(comparer);

但是任何时候您更改查询时,您也必须更改样本。

关于c# - 匿名类型的 IEqualityComparer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25934419/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com