简体   繁体   中英

IEquatable doesnt call Equals method

Ih, i am facing a problem with IEquatable (C#). As you can see in the following code, I got a class where i've implement IEquatable but it's "Equals" method is not getting reach. My objective is: I have a datetime column in my database and i would like to distinct only date, not considering the "time" part.

for example: 12-01-2014 23:14 would be equal to 12-01-2014 18:00.

namespace MyNamespace
{
    public class MyRepository
    {
        public void MyMethod(int id)
        {
            var x = (from t in context.MyTable
                     where t.id == id
                     select new MyClassDatetime()
                     {
                         Dates = v.Date
                     }).Distinct().ToList();
        }
    }


public class MyClassDatetime : IEquatable<MyClassDatetime>
{
    public DateTime? Dates { get; set; }

    public bool Equals(MyClassDatetime other)
    {
        if (other == null) return false;
        return (this.Dates.HasValue ? this.Dates.Value.ToShortDateString().Equals(other.Dates.Value.ToShortDateString()) : false);
    }

    public override bool Equals(object other)
    {
        return this.Equals(other as MyClassDatetime );
    }

    public override int GetHashCode()
    {
        int hashDate = Dates.GetHashCode();
        return hashDate;
    }
}
}

Have you know how can i make it work properly or other option to do what i need?? Thank you!!

Your implementation of GetHashCode is incorrect for the desired equality semantics. That's because it returns different hash codes for dates that you want to compare equal, which is a bug .

To fix it, change it to

public override int GetHashCode()
{
    return Dates.HasValue ? Dates.Value.Date.GetHashCode() : 0;
}

You should also update Equals in the same spirit, it's not a good idea to mess with string representations of dates:

public bool Equals(MyClassDatetime other)
{
    if (other == null) return false;
    if (Dates == null) return other.Dates == null;
    return Dates.Value.Date == other.Dates.Value.Date;
}

Update: As usr very correctly points out , since you are using LINQ on an IQueryable the projection and Distinct call will be translated to a store expression and this code will still not run. To get around that you can use an intermediate AsEnumerable call:

var x = (from t in context.MyTable
         where t.id == id
         select new MyClassDatetime()
         {
             Dates = v.Date
         }).AsEnumerable().Distinct().ToList();

Thans for reply but it still not solving my problem.

I finally found a way to do it but without using IEquatable.

var x = (from t in context.MyTable where t.Id == id select EntityFunctions.CreateDateTime(t.Date.Value.Year, t.Date.Value.Month,t.Date.Value.Day, 0, 0, 0)).Distinct();

=)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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