C# 如何为lambda表达式中的匿名变量编写IEqualityComparer?
我想知道有没有一种方法可以为lambda表达式中的匿名变量实现IEqualityComparer,或者,在任何情况下,我都需要编写一个类来将匿名变量转换为sprecific类,并创建一个需要实现IEqualtyComparer的类 我编写了创建CartesianDecart产品的代码: 我定义了脱碳班C# 如何为lambda表达式中的匿名变量编写IEqualityComparer?,c#,linq,lambda,C#,Linq,Lambda,我想知道有没有一种方法可以为lambda表达式中的匿名变量实现IEqualityComparer,或者,在任何情况下,我都需要编写一个类来将匿名变量转换为sprecific类,并创建一个需要实现IEqualtyComparer的类 我编写了创建CartesianDecart产品的代码: 我定义了脱碳班 public class Decart { public int X; public int Y; } 我为Decart类定义了IEqualtityComparer public
public class Decart
{
public int X;
public int Y;
}
我为Decart类定义了IEqualtityComparer
public class Ext : IEqualityComparer<Decart>
{
public bool Equals(Decart x, Decart y)
{
if ((x.X == y.X && x.Y == y.Y) ||
x.X == y.Y && x.Y == y.X)
return true;
return false;
}
public int GetHashCode(Decart obj)
{
return obj.X + obj.Y;
}
}
怎么做?不清楚你在问什么 我假设您希望像这样泛化这个类的维度
public class Decart
{
public int[] dim;
}
然后可以扩展比较器
public class Ext : IEqualityComparer<Decart>
{
public bool Equals(Decart x, Decart y)
{
for(int i=0; i< x.dim.Length;i++)
if (x.dim[i] != y.dim[i] )
return false;
return true;
}
public int GetHashCode(Decart obj)
{
return obj.dim.Sum();
}
}
您可以声明IEqualityComparer实现,它将委托作为GetHashCode和Equals接口方法的实现。然后可以将匿名方法作为实现传入
public static IEqualityComparer<T> CreateEqualityComparer<T>(T ignore, Func<T, int> getHashCode, Func<T, T, bool> equals) => new DelegatedEqualityComparer<T>(getHashCode, equals);
public class DelegatedEqualityComparer<T> : EqualityComparer<T> {
private Func<T, int> getHashCode;
private Func<T, T, bool> equals;
public DelegatedEqualityComparer(Func<T, int> getHashCode, Func<T, T, bool> equals) {
if(getHashCode==null) throw new ArgumentNullException(nameof(getHashCode));
if(equals==null) throw new ArgumentNullException(nameof(equals));
this.getHashCode=getHashCode;
this.equals=equals;
}
public override int GetHashCode(T x) => getHashCode(x);
public override bool Equals(T x, T y) => equals(x, y);
}
真的是什么意思?null:new{x=0,y=0}:
CreateEqualityComparer T ignore的第一个参数需要允许编译器推断类型T,因为您不能拼写匿名类型的名称。三元运算符的true条件使编译器始终选择左分支null,但由于三元运算符的两个分支必须返回相同的类型,因此新的{x=0,y=0}使编译器隐式地将null强制转换为给定的匿名类型
此外,规范中的相关注释:
7.6.10.6匿名对象创建表达式
在同一程序中,两个匿名对象初始值设定项以相同顺序指定相同名称和编译时类型的属性序列,将生成相同匿名类型的实例
我想知道,是否有任何方法可以用匿名变量类的独特方法编写IEqualityComparer。不幸的是,我的理解是,没有办法做到这一点。也许可以解释一下三元函数的用途和伪参数的意义?@pinkfloydx33 C编译器无法从委托中识别静态方法CreateEqualityComparer使用的类型t,所以你给他一个类型为t new{x=0,y=0}的对象,但是PetSer是一个喜欢优化代码的人,他认为创建一个无用的对象是不好的,那么三元运算符是真的吗?null:新的,不会创建对象,但编译器仍然可以识别未创建对象的类型:-我认为三元的东西很棒:-@xantos我知道答案。我建议它可能会帮助其他人,特别是OP或任何想对匿名类型进行类似操作的人。如果他们知道这个问题的重要性/原因,他们就不一定要先问这个问题place@pinkfloydx33在你写的评论v1中,你知道,我的评论仍然是正确的:-简单地说,这不适合你,而是适合他们:-@xanatos是的,在你的手机上写评论的危险:-。我并不是说你的评论是错误的。我只是建议通过详细说明它的作用来改进答案。如果我是初学者,我就不明白它的目的。这些答案对于复制/粘贴来说非常有用,但是一个解释会更好。本文中有几个主题:类型推断、泛型和匿名类型,以及编译器如何生成相同的类型。我会写我自己的答案,但它几乎是一样的,因此commentsIt看起来像是用匿名对象默认获得的相同的每属性相等来定义相等,那么为什么不在没有传递比较器的情况下使用Distinct呢?@JonHanna with Distinct我得到这个结果://11//12//13//21//2//23//31//32//3 with Distinct新的Ext我得到这个结果://11//12//13//2//23//3,它不关心秩序。对不起,我读得太快了。
public class Ext : IEqualityComparer<Decart>
{
public bool Equals(Decart x, Decart y)
{
for(int i=0; i< x.dim.Length;i++)
if (x.dim[i] != y.dim[i] )
return false;
return true;
}
public int GetHashCode(Decart obj)
{
return obj.dim.Sum();
}
}
public static IEqualityComparer<T> CreateEqualityComparer<T>(T ignore, Func<T, int> getHashCode, Func<T, T, bool> equals) => new DelegatedEqualityComparer<T>(getHashCode, equals);
public class DelegatedEqualityComparer<T> : EqualityComparer<T> {
private Func<T, int> getHashCode;
private Func<T, T, bool> equals;
public DelegatedEqualityComparer(Func<T, int> getHashCode, Func<T, T, bool> equals) {
if(getHashCode==null) throw new ArgumentNullException(nameof(getHashCode));
if(equals==null) throw new ArgumentNullException(nameof(equals));
this.getHashCode=getHashCode;
this.equals=equals;
}
public override int GetHashCode(T x) => getHashCode(x);
public override bool Equals(T x, T y) => equals(x, y);
}
var equalityComparer = CreateEqualityComparer(true ? null : new { x = 0, y = 0 }, a => a.x+a.y, (a, b) => (a.x==b.x&&a.y==b.y)||(a.x==b.y&&a.y==b.x));
var result = input
.SelectMany(x => input
.Select(y => new { x, y }))
.Distinct(equalityComparer);