2014-10-01 28 views
0

我有一個基類「實體」與下面的方法(我不執行IEquatable,這是一個巨大的頭痛,所以我拋棄這種做法)如何獲得一個需要泛型類型的類,以從該類型的實例中調用方法?

virtual public bool Equals(Entity entity) 
    { 
     throw new Exception("The base Entity.Equals method should never be called"); 
    } 

我有幾個班擴展實體。每個人都會實現一個Equals方法,就像這樣。

virtual public bool Equals(TestPlan other) 
    { 
     if (this.TestPlanType.Equals(other.TestPlanType) && 
      this.Name.Equals(other.Name) && 
      this.Description.Equals(other.Description) && 
      this.DatetimeCreated.Equals(other.DatetimeCreated) && 
      this.UserNameCreated.Equals(other.UserNameCreated) && 
      this.Duration.Equals(other.Duration) && 
      this.Scenarios.SequenceEqual(other.Scenarios)) return true; 
     return false; 
    } 

我真的想要輸入的類型是TestPlan而不是Object。 (至少我認爲我這樣做,我不想失去強大的打字能力)。

我意識到這種方法不會「覆蓋」基類,因爲我使它成爲虛擬公共而不是公共覆蓋。

我有需要的通用類型,將調用.Equals()

public int GetIdenticalEntityId<T>(T entity) where T : Entity 
    { 
     List<T> exitingEntities = LoadEntities<T>(); 
     foreach (T existingEntity in exitingEntities) 
     { 
      if (existingEntity.Equals(entity)) 
      { 
       return existingEntity.Id; 
      } 
     } 
     return -1; 
    } 

的問題是,所述exitingEntity.Equals()調用基類.Equals的方法。

我怎樣才能得到一個類,需要泛型類型,從該類型的實例調用方法?

回答

3

只是覆蓋基地Equals(object other)方法。這很簡單。

你甚至可以把它強制性的,通過在Entity類聲明:現在

public override abstract bool Equals(object other); 
public override abstract int GetHashCode(); 

,在你的班,Equals方法是這樣的:

public override bool Equals(object obj) 
{ 
    var other = obj as TestPlan; 

    if (other == null) 
     return false; 

    if (ReferenceEquals(other, this)) 
     return true; 

    return this.TestPlanType.Equals(other.TestPlanType) && 
     this.Name.Equals(other.Name) && 
     this.Description.Equals(other.Description) && 
     this.DatetimeCreated.Equals(other.DatetimeCreated) && 
     this.UserNameCreated.Equals(other.UserNameCreated) && 
     this.Duration.Equals(other.Duration) && 
     this.Scenarios.SequenceEqual(other.Scenarios)); 
} 

現在,如果你想要實現IEquatable<T>它將是真的簡單:

public bool Equals(TestPlan obj) 
{ 
    return Equals((object)obj); 
} 

你也可以做到這一點的其他方式:

public override bool Equals(object obj) 
{ 
    return Equals(obj as TestPlan); 
} 

public bool Equals(TestPlan obj) 
{ 
    if (obj == null) 
     return false; 

    // Same code as before 
} 

哦,你應該實現GetHashCode也避免討厭的驚喜:

public override int GetHashCode() 
{ 
    var hash = TestPlanType.GetHashCode(); 

    hash = (hash * 397)^Name.GetHashCode(); 
    hash = (hash * 397)^Description.GetHashCode(); 
    hash = (hash * 397)^DatetimeCreated.GetHashCode(); 
    hash = (hash * 397)^UserNameCreated.GetHashCode(); 
    hash = (hash * 397)^Duration.GetHashCode(); 
    hash = (hash * 397)^Scenarios.GetHashCode(); 

    return hash; 
} 

這是真的重要。例如,您團隊中的某個人可能有一天想要將您的對象用作字典中的關鍵字。如果您從一開始就正確實施GetHashCode函數,您將在將來的代碼中避免出現此類陷阱。今天爲避免未來的大型WTF而付出的代價很小。

在這裏,你走了,這是你真正需要的。

+0

如果有人通過錯誤的類型會發生什麼?不會因爲TestPlan引發異常而導致var other = obj?我沒有實現IEquatable,我還需要實現GetHashCode()嗎?只用1個方法來實現IEquatable的好處是什麼?此代碼有一個唯一目的,即在複製時檢查數據庫條目是否相等。所以它不像我們期望的那樣人們傳遞物體並且一直比較它們。 – Miebster 2014-10-01 20:40:57

+1

@Miebster我會擴展我的答案。但是現在,如果'obj'不是'TestPlan',那麼'obj as TestPlan'將返回'null'。 – 2014-10-01 20:41:51

+0

@Miebster你不想覆蓋Equals而不是GetHashCode。 .Net的一些類(比如Dictionary)對這兩個類做了一些假設,你真的不想破壞它們。 – 2014-10-01 20:42:33

0

爲了覆蓋函數,參數必須是同一時間。所以你的TestPlan.Equals應該類似於:

override public bool Equals(Entity entity) 
{ 
    TestPlan other = entity as TestPlan; 
    if (other == null) 
     return false; 
    if (this.TestPlanType.Equals(other.TestPlanType) && 
     this.Name.Equals(other.Name) && 
     this.Description.Equals(other.Description) && 
     this.DatetimeCreated.Equals(other.DatetimeCreated) && 
     this.UserNameCreated.Equals(other.UserNameCreated) && 
     this.Duration.Equals(other.Duration) && 
     this.Scenarios.SequenceEqual(other.Scenarios)) return true; 
    return false; 
} 
相關問題