Abstract functions and data types - is there an elegant way to do this?

I have a large family of objects, all of which come from a single parent. Objects all know how to determine if they have been changed, but I also need to find out if a new instance of the object has been changed from the one I already have in memory (testing to check if someone else has updated the database and the object was edited.)

As a result, each child class must contain the same method:

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

This really works in my craw, but I do not see the path around it, since the real work must be done by a function that takes a parameter of the same type as the class that it is in - so it cannot be virtual. (Of course, I could define it to take the parent and drop it every time, but the comparison function accepts any object in the tree, not just the right one, and it requires a security code in each instance, again something ugly.)

Of course this works, but I don't like the ugly code.

Update. As for the function Changed, each object saves a copy of its state at boot time.

+3
source share
3 answers

As long as your base class abstract, you can do something like this:

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
    }
}
+3

:

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), , Animal/Dog/Cat, .

:

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. . .

: ,

+2

, minitech, , Changed of 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

All Articles