2012-01-25 2 views
1
using System; 
using System.Collections.Generic; 
using System.Linq; 
using NUnit.Framework; 

namespace UnitTest.Model 
{ 
[TestFixture] 
public class SampleEquatableObjectTest 
{ 
    [Test] 
    public void TwoIdenticalUsersComparedEqualTrue() 
    { 
     var user1 = new SampleObject { Id = 1, Name = "Test User" }; 
     var user2 = new SampleObject { Id = 1, Name = "Test User" }; 

     Assert.IsTrue(user1.Equals(user2)); 
    } 

    [Test] 
    public void TwoDifferentUsersComparedEqualFalse() 
    { 
     var user1 = new SampleObject { Id = 1, Name = "Test User 1" }; 
     var user2 = new SampleObject { Id = 2, Name = "Test User 2" }; 

     Assert.IsFalse(user1.Equals(user2)); 
    } 

    [Test] 
    public void CollectionOfUsersReturnsDistinctList() 
    { 
     var userList = new List<SampleObject> 
          { 
           new SampleObject {Id = 1, Name = "Test User"}, 
           new SampleObject {Id = 1, Name = "Test User 1"}, 
           new SampleObject {Id = 2, Name = "Test User 2"} 
          }; 

     Assert.AreEqual(userList.Count, 3); 

     var result = userList.Distinct(); 

     Assert.AreEqual(result.Count(), 2); 

     var multipleTest = (from r in result group r by new { r.Id } into multGroup where multGroup.Count() > 1 select multGroup.Key).Any(); 

     Assert.IsFalse(multipleTest); 
    } 

    public class SampleObject : IEquatable<SampleObject> 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 

     public bool Equals(SampleObject other) 
     { 
      if (ReferenceEquals(this, other)) 
       return true; 
      if (ReferenceEquals(other, null) || ReferenceEquals(this, null)) 
       return false; 

      return Id.Equals(other.Id); 
     } 
    } 
} 

}Linq Distinct не работает, как на форуме и Microsoft примеры

Четкий метод в этом тесте не возвращает отличный список. Утверждение для count не будет выполнено. Я рассмотрел другие подобные вопросы и примеры Microsoft, но они выглядят точно так же, как и код, который у меня есть в тесте. Любой вход?

+0

Вы уверены, что ваш метод .Equals вызывается, и он не использует оператор ==? – BlackICE

+0

[This post] (http://stackoverflow.com/questions/1365748/distinct-not-working-with-linq-to-objects) охватывает большую часть той же информации. –

ответ

3

Вам также необходимо переопределить методы GetHashCode() и Equals из класса Object. Для получения дополнительной информации см. Соответствующие FXCOP violation.

Тогда ваши тесты будут работать, как и ожидалось.

public class SampleObject : IEquatable<SampleObject> 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    public bool Equals(SampleObject other) 
    { 
     if (ReferenceEquals(this, other)) 
      return true; 
     if (ReferenceEquals(other, null) || ReferenceEquals(this, null)) 
      return false; 

     return Id.Equals(other.Id); 
    } 

    public override int GetHashCode() 
    { 
     return Id; 
    } 

    public override bool Equals(object obj) 
    { 
     return Equals(obj as SampleObject); 
    } 
} 
+1

для полноты, следует, вероятно, также переопределить Object.Equals (рядом с реализацией IEquatable) – jeroenh

0

Вы реализуете интерфейс без определения обоих членов спецификации интерфейса. Ваш код должен выглядеть примерно так:

public bool Equals(SampleObject x, SampleObject y) 
    { 
     if (ReferenceEquals(x, y)) 
      return true; 
     if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) 
      return false; 

     return x.Id.Equals(y.Id); 
    } 

    public int GetHashCode(SampleObject obj) 
    { 
       public int GetHashCode(SampleObject obj) 
    { 
     if (Object.ReferenceEquals(obj, null)) return 0; 
     int hashId = obj.Id == null ? 0 : obj.Id.GetHashCode(); 
     int hashName = obj.Name == null ? 0 : obj.Name.GetHashCode(); 
     return hashId^hashName; // or what ever you want you hash to be, hashID would work just as well. 
    } 
    } 
+2

GetHashCode не должен зависеть от имени, потому что Name не используется при определении равенства. Для любых двух объектов, которые равны, GetHashCode должен возвращать одно и то же значение. Кроме того, obj.Id никогда не будет null, потому что это int. – phoog