2012-05-23 20 views
3

我有一個大家族的所有後代單親。這些對象都知道如何判斷它們是否已被修改,但是我還需要能夠查看一個對象的新實例是否已經被修改,與我已經在內存中創建的對象相比(測試是否有其他人更新了數據庫。當對象正在編輯)抽象函數和數據類型 - 是否有任何優雅的方式來做到這一點?

結果是每個子類必須包含同樣的方法:

public new bool Changed() 
{ 
    return Changed(this); 
} 

這真使我無法忍受,但我看到沒有辦法解決它的實際工作需要通過一個函數來完成,該函數的參數類型與它在—中的類相同,因此它不能是虛擬的。 (當然,我可以將它定義爲每次都接受父對象並進行投射,但這會使得比較函數接受樹中的任何對象,而不僅僅是正確的對象,並且它需要每個實例中的守衛代碼,而且還有些不好。)

當然這可以工作,但我不喜歡醜陋的代碼。

更新:至於Changed函數,每個對象在加載時都保留其狀態的副本。

+0

也許你可以詳細說明你的'Changed()',分享一些具體的例子。我可以根據那個 – skarmats

+0

調整我的例子'Changed(SomeDerivedType o)'是在每個派生類中實現的嗎?用你的基類和一個派生類的例子的幾行真的可以幫助:-)我現在就叫它一個晚上 – skarmats

+0

@skarmats:你說得對,每個派生類實現了Changed(<它自己的類型> o )。每個檢查它自己的字段並調用基地來檢查任何父字段。 –

回答

3

只要你的基類是abstract,你可以做這樣的事情:

abstract class Base 
{ 
    public abstract bool Changed<T>(T obj) where T : Base; 

    public bool Changed() 
    { 
     return Changed(this); 
    } 
} 

class Subclass : Base 
{ 
    public override bool Changed<Subclass>(Subclass obj) 
    { 
     // Do stuff here 
    } 
} 
+0

它*看起來像我想要的 - 但它不能編譯。我不確定發生了什麼,但該參數僅包含父項的字段,而不包含我需要查看的當前類的字段。 –

+0

我唯一可能改變的是讓T的Changed被保護。我想你會希望總是把這個基礎改爲外部的類。 – user957902

+0

我剛剛試過一個測試用例,並得到相同的結果。由於對從基類衍生而來的通用類的限制,該方法只能看到基類的成員。 – user957902

2

的基本結構:

public abstract class Base<T> where T : Base<T> 
{ 
    public T Original { get; private set; } 

    public abstract bool Changed(T o); 

    public bool Changed() 
    { 
     return this.Changed(Original); 
    } 
} 

public class DerivedA : Base<DerivedA> 
{ 
    public override bool Changed(DerivedA o) 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class DerivedB : Base<DerivedB> 
{ 
    public override bool Changed(DerivedB o) 
    { 
     throw new NotImplementedException(); 
    } 
} 

雖然它有它的缺點(readiblity),也可能是在這種情況下是正確的選擇,因爲你的問題不是古典動物/狗/貓的意義上的類型保護,而是代碼共享。

爲了避免這種情況:

public class DerivedC : DerivedB 
{ 
} 
new DerivedB().Changed(new DerivedC()); // compiles 

你可以封DerivedB

或者你可以繼續瘋狂(我不會低於這個水平推薦這絕對不是進一步。):

public abstract class DerivedE<T> : Base<DerivedE<T>> where T : DerivedE<T> 
{ 
} 

public class DerivedF : DerivedE<DerivedF> 
{ 
} 

public class DerivedG : DerivedE<DerivedG> 
{ 
} 

new DerivedF().Changed(new DerivedG()); // does not compile 
new DerivedF().Changed(new DerivedF()); // does compile 

看到這個http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx。我從那篇文章中得到了靈感。他討論了利弊。

編輯:整理後,根據意見

+0

另一個不能編譯的答案:它抱怨類型不是泛型的,不能用作類型參數。 –

+0

我的基本示例沒有編譯。請分享一些關於你的代碼的內容,我很樂意看看它。看到我對OP – skarmats

+0

的評論我沒有說派生類沒有被繼承,有些是。無論如何,錯誤是「非泛型類型不能與類型參數一起使用」,它會拋出類行。 –

0

相同的答案MiniTech移動調整,所以他應該得到的功勞,但在這個例子中,改變SubclassA可以通過鑄造全名爲類查看其屬性。

namespace ConsoleApplication1 
{ 

    abstract class Base 
    {  
     protected abstract bool Changed<T>(T obj) where T : Base;  
     public bool Changed()  
     {   
      return Changed(this);  
     } 

     public String PropBase { get; set; } 
    } 

    class SubclassA : Base 
    { 
     public String PropA { get; set; } 

     protected override bool Changed<SubclassA>(SubclassA obj)  
     { 
      ConsoleApplication1.SubclassA myInstance = obj as ConsoleApplication1.SubclassA; 
      // Now can see PropA 
      myInstance.PropA = "A"; 
      return true; 
     } 


    } 

    class SubclassB : Base 
    { 
     protected override bool Changed<SubclassB>(SubclassB obj) 
     { 
      // can't see prop B here 
      // obj.PropB = "B"; 
      return true; 
     } 

     public String PropB { get; set; } 
    } 


    class Program 
    { 
     static void Main(string[] args) 
     { 

      SubclassB x = new SubclassB(); 

      x.Changed(); 

      Base y = new SubclassA(); 

      y.Changed(); 
     } 
    } 
} 
+0

我真的很困惑 - 即使演員也不會看到它! –

+0

你使用什麼版本的.Net?這適用於.NET 4.0 – user957902

+0

測試用例適用於.net 3.5和.Net 4.0。請注意,我的SP1已安裝.Net 4.0和VS2010。 – user957902

相關問題