2012-05-23 17 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

相关问题