简体   繁体   English

在Lambda表达式中使用相等比较器

[英]Using equality comparer in lambda expression

I have a Venue class, and a Coordinate class like so: 我有一个Venue类和一个Coordinate类,如下所示:

class Venue
{
    string Name;
    Coordinate coordinate;
}

class Coordinate
{
    double latitute;
    double longitude;
}

Now, I want to be able to select a venue based on a coordinate as follows: 现在,我希望能够根据如下所示的坐标来选择场地:

List<Venue> venues = GetAllVenues();

var myVenue = venues.FirstOrDefault(venue=>venue.coordinate == myCoordinate);

I have an IEqualityComparer implementation, but the lambda expression does not have an overload which takes the IEqualityComparer as a parameter. 我有IEqualityComparer实现,但是lambda表达式没有将IEqualityComparer作为参数的重载。

How do I use my equality comparer in a lambda expression? 如何在lambda表达式中使用我的相等比较器?

EDIT: 编辑:

My equality comparer looks like this: 我的平等比较器如下所示:

class CoordinatesEqualityComparer:IEqualityComparer<Coordinate>
    {
        public bool Equals(Coordinate x, Coordinate y)
        {
            return x.RowIndex == y.RowIndex && x.ColumnIndex == y.ColumnIndex;
        }

        public int GetHashCode(Coordinate obj)
        {
            return obj.GetHashCode();
        }
    }

When I do a Union() operation, like so, it does not work correctly, even though coordinates in both lists are same. 当我像这样执行Union()操作时,即使两个列表中的坐标相同,它也无法正常工作。

List<Coordinates> coordinates; 
CoordinatesEqualityComparer comparer; 
coordinates.Union(someOtherListOfCoordinates, comparer); 

However, when I do a union with itself, it works. 但是,当我与自己进行联合时,它会起作用。 What am I doing wrong? 我究竟做错了什么? Does it have something to do with the GetHashCode() implementation? 它与GetHashCode()实现有关吗?

Edit 2: Fixing the GetHashCode() method seems to do the trick. 编辑2:修复GetHashCode()方法似乎可以解决问题。

public int GetHashCode(Coordinates obj)
        {
            // Warning:Hack. Use two prime numbers to generate a hash based on two properties.
            return obj.RowIndex.GetHashCode() * 7 + obj.ColumnIndex.GetHashCode() * 13 ;
        }

Have you tried: 你有没有尝试过:

var ec = new YourEqualityComparer();
var myVenue = venues.FirstOrDefault(venue => 
                                         ec.Equals(venue.coordinate, myCoordinate));




Of course, another approach would be to define the == operator for your Coordinate class and then you wouldn't need an IEqualityComparer : 当然,另一种方法是为您的Coordinate类定义==运算符,然后就不需要IEqualityComparer

class Coordinate
{
    double latitude;
    double longitude;

    public override bool Equals(object obj)
    {
        return Object.ReferenceEquals(this, obj)) ||
               this == (other as Coordinate);
    }

    public static bool operator ==(Coordinate l, Coordinate r)
    {
        return ((object)l == null && (object)r == null) || 
               ((object)l != null && (object)r != null) &&
               // equality check including epsilons, edge cases, etc.
    }

    public static bool operator !=(Coordinate l, Coordinate r)
    {
        return !(l == r);
    }
}

I would implement IEquatable<Coordinate> , override Equals(object), override GetHashCode(), and == != operators like this: 我将实现IEquatable<Coordinate> ,覆盖Equals(object),覆盖GetHashCode()和==!=运算符,如下所示:

public class Coordinate : IEquatable<Coordinate>
{
    public double Latitide { get; set; }
    public double Longitude { get; set; }

    public bool Equals(Coordinate other)
    {
        if (other == null)
        {
            return false;
        }
        else
        {
            return this.Latitide == other.Latitide && this.Longitude == other.Longitude;
        }
    }

    public override bool Equals(object obj)
    {
        return this.Equals(obj as Coordinate);
    }

    public override int GetHashCode()
    {
        return this.Latitide.GetHashCode() ^ this.Longitude.GetHashCode();
    }

    public static bool operator ==(Coordinate value1, Coordinate value2)
    {
        if (!Object.ReferenceEquals(value1, null) && Object.ReferenceEquals(value2, null))
        {
            return false;
        }
        else if (Object.ReferenceEquals(value1, null) && !Object.ReferenceEquals(value2, null))
        {
            return false;
        }
        else if (Object.ReferenceEquals(value1, null) && Object.ReferenceEquals(value2, null))
        {
            return true;
        }
        else
        {
            return value1.Latitide == value2.Latitide && value1.Longitude == value2.Longitude;
        }
    }

    public static bool operator !=(Coordinate value1, Coordinate value2)
    {
        return !(value1 == value2);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM