2015-01-05 63 views
3

假設我有這個對象,其中以下3個屬性(其他被省略)構成一個「唯一」Plan對象(如果這些屬性等於另一個Plan對象中的相同值)。正確的方法來加入對象集合的多個屬性?

public class Plan 
{ 
    public int ID { get; set; } 
    public Plan Parent { get; set; } 
    public ID SomeOtherProperty { get; set; } 
} 

這裏是我的Join代碼,在那裏我省略了匿名方法的Join運營商 (我知道,在默認情況下此代碼將無法正常工作):

oldPlans 
    .Join(newPlans, o => o, n => n, (o, n) => new { Old = o, New = n }) 
    .ForEach(e => 
    { 
     ... 
    }); 

我想執行一個C#Join關於兩個Plan對象集合。我知道一種方法是使用匿名方法來加入屬性,寫出這三個屬性。

但是有沒有不同的方法?我可以覆蓋GetHashCode嗎?當我嘗試這種方式時,似乎並沒有將它稱爲該方法。我也試圖壓倒Equals,但它似乎並沒有這麼說。我應該覆蓋==!=運營商嗎?我可以明確地調用.GetHashCode()作爲關鍵選擇器字段(假設我忽略它)?

是否有可能讓這個連接檢查這兩個對象的相等性而不會使關鍵字選擇器複雜化?謝謝。

+0

您不必使用匿名對象。您只需創建一個'Func resultSelector',它將告訴'Enumerable.Join'如何根據兩個鍵來選擇給定的值。 –

回答

1

您的代碼適合我 - 通過ReferenceSource進行跟蹤,默認比較最終使用的是ObjectEqualityComparer,它調用Equals(),所以您的想法是正確的。

所以這涉及到你如何實現EqualsGetHashCode。如果您覆蓋兩者,則應覆蓋兩者:如MSDN states

注意:如果覆蓋GetHashCode方法,則還應該覆蓋Equals,反之亦然。如果重寫的Equals方法在兩個對象測試相等時返回true,則重寫的GetHashCode方法必須爲這兩個對象返回相同的值。

注意你的ID類也需要正確地處理這兩種方法,它應該由Plan被用來檢查平等和獲得的哈希碼。

這個程序爲我工作,只打印與ID=2第二個條目(請注意,我做了SomeOtherPropertyint爲簡單起見,但這並不影響該方法或代碼):

class Program 
{ 
    public class Plan 
    { 
     public int ID { get; set; } 
     public Plan Parent { get; set; } 
     public int SomeOtherProperty { get; set; } 

     // added to show we don't care about this 
     public string IgnoreMe { get; set; } 

     public Plan(int id, int other, Plan parent, string ignore) 
     { 
      this.ID = id; 
      this.SomeOtherProperty = other; 
      this.Parent = parent; 
      this.IgnoreMe = ignore; 
     } 

     public override bool Equals(object obj) 
     { 
      Plan other = (Plan)obj; 
      // just check the relevant properties 
      return this.ID == other.ID 
       && this.SomeOtherProperty == other.SomeOtherProperty 
       && this.Parent == other.Parent; 

      // .. or alternatively 
      //return (new { ID, SomeOtherProperty, Parent }) 
      // .Equals(new { other.ID, other.SomeOtherProperty, other.Parent }); 
     } 

     // nicked from http://stackoverflow.com/a/4630550/1901857 
     public override int GetHashCode() 
     { 
      return new { ID, SomeOtherProperty, Parent }.GetHashCode(); 
     } 

     // just to help debug 
     public override string ToString() 
     { 
      return string.Format("[ID: {0}, Other:{1}, Parent:{2}]", ID, SomeOtherProperty, Parent); 
     } 
    } 

    static void Main(string[] args) 
    { 
     var parentPlans = new Plan[] { 
      new Plan(101, 2, null, "parent1"), 
      new Plan(102, 3, null, "parent2"), 
      new Plan(103, 4, null, "parent3"), 
      new Plan(104, 5, null, "parent4") 
     }; 

     List<Plan> oldPlans = new List<Plan>(new Plan[] { 
      new Plan(1, 2, parentPlans[0], "old1"), 
      new Plan(2, 3, parentPlans[1], "old2"), 
      new Plan(3, 4, parentPlans[2], "old3"), 
      new Plan(4, 5, parentPlans[3], "old4") 
     }); 

     List<Plan> newPlans = new List<Plan>(new Plan[] { 
      new Plan(11, 2, parentPlans[0], "new1"), // different ID 
      new Plan(2, 3, parentPlans[1], "new2"), // same 
      new Plan(3, 14, parentPlans[2], "new3"), // different other ID 
      new Plan(4, 5, parentPlans[2], "new4") // different parent 
     }); 

     foreach (var e in 
      oldPlans.Join(newPlans, o => o, n => n, (o, n) => new { Old = o, New = n })) 
     { 
      Console.WriteLine(e.Old + "/" + e.New); 
     }; 
    } 
} 

如果你認爲你的EqualsGetHashCode的實現應該已經工作了,那麼請將它們發佈在問題中,也許它們不太正確。

+0

我沒有實現BOTH Equals和GetHashCode,只有一個,然後嘗試另一個(移除另一個)。我會試一試,看看它是否有效。 –

+1

這就是答案。我必須實現Equals和GetHashCode(我沒有意識到它提前發出的警告表明這一點)。 –

相關問題