2010-10-09 90 views
3

爲什麼var excludes = users.Except(matches);不排除matcheslinq物體相等以及如何正確覆蓋它

如果我想讓相等比較器僅使用ID,那麼正確的方法是什麼?例如,將不勝感激。

public class User 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 

    public override string ToString() 
    { 
     return ID.ToString() + ":" + Name; 
    } 
} 

private static void LinqTest2() 
{ 
    IEnumerable<User> users = new List<User> 
    { 
     new User {ID = 1, Name = "Jack"}, 
     new User {ID = 2, Name = "Tom"}, 
     new User {ID = 3, Name = "Jim"}, 
     new User {ID = 4, Name = "Joe"}, 
     new User {ID = 5, Name = "James"}, 
     new User {ID = 6, Name = "Matt"}, 
     new User {ID = 7, Name = "Jon"}, 
     new User {ID = 8, Name = "Jill"} 
    }.OfType<User>(); 

    IEnumerable<User> localList = new List<User> 
    { 
     new User {ID = 4, Name = "Joe"}, 
     new User {ID = 5, Name = "James"} 
    }.OfType<User>(); 


    //After creating the two list 
    var matches = from u in users 
        join lu in localList 
        on u.ID equals lu.ID 
        select lu; 
    Console.WriteLine("--------------MATCHES----------------"); 
    foreach (var item in matches) 
    { 
     Console.WriteLine(item.ToString()); 
    } 

    Console.WriteLine("--------------EXCLUDES----------------"); 
    var excludes = users.Except(matches); 
    foreach (var item in excludes) 
    { 
     Console.WriteLine(item.ToString()); 
    }    
} 
+0

請注意,在'matches'我做'選擇lu' – VoodooChild 2010-10-09 20:10:48

回答

7
sealed class CompareUsersById : IEqualityComparer<User> 
    { 
     public bool Equals(User x, User y) 
     { 
      if(x == null) 
       return y == null; 
      else if(y == null) 
       return false; 
      else 
       return x.ID == y.ID; 
     } 

     public int GetHashCode(User obj) 
     { 
      return obj.ID; 
     } 
    } 

然後

var excludes = users.Except(matches, new CompareUsersById()); 
+0

+1:這工作。你爲什麼讓這門課「密封」? – VoodooChild 2010-10-09 20:20:13

+1

只是一種習慣 - 如果我非常確定該類不會被繼承,或者沒有理由繼承它,那麼我會將其封閉。 – max 2010-10-09 20:22:34

3

您的用戶類沒有重載EqualsGetHashCode因此使用的Equals默認實現。在這種情況下,這意味着它會比較參考。您創建了兩個具有相同值的用戶對象,但由於它們是不同對象,所以它們會比較不相等。

重寫Equals的替代方法是使用overload of Except that takes an IEqualityComparer

+0

「以壓倒一切的替代Equals已是使用不同之處在於採用的的IEqualityComparer超載」 - 這是max的答案顯示的,還是不同的? – VoodooChild 2010-10-09 20:22:25

+2

是的,這正是這種情況。應該謹慎考慮重寫'Equals',因爲這個邏輯將適用於任何使用'用戶'對象的地方(但實際上你可能需要這種行爲)。提供'IEqualityComparer'將限制比較規則僅限於一次調用。順便說一句,我想知道他們爲什麼沒有做一個'Except'重載,它需要一個更輕量級的'Comparison'委託,這樣就不需要聲明一個全新的類,因爲委託可以是匿名的。 – max 2010-10-09 20:30:06