3

私は、単一の親から派生したオブジェクトの大規模なファミリーを持っています。オブジェクトはすべて変更されたかどうかを知る方法を知っていますが、オブジェクトの新しいインスタンスが既にメモリにあるものと比較して変更されているかどうかを確認できる必要もあります (他の誰かがデータベースを更新したかどうかをテストする)オブジェクトが編集されている間。)

その結果、すべての子クラスに同じメソッドを含める必要があります。

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

これは本当に私の爪に固執しますが、実際の作業は、それが含まれるクラスと同じ型のパラメーターを取る関数によって実行される必要があるため、回避する方法がわかりません。したがって、仮想にすることはできません。(確かに、親を取得して毎回キャストするように定義することもできますが、その場合、比較関数は正しいオブジェクトだけでなく、ツリー内の任意のオブジェクトを受け入れるようになり、インスタンスごとにガード コードが必要になります。これも醜いものです。)

もちろんこれは機能しますが、醜いコードは嫌いです。

更新:Changed関数に関しては、各オブジェクトは、読み込まれたときにその状態のコピーを保持します。

4

3 に答える 3

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
    }
}
于 2012-05-23T22:56:00.957 に答える
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();
    }
}

短所(読みやすさ)はありますが、問題は古典的な動物/犬/猫の意味での型保護ではなく、コード共有であるため、この場合は正しい選択になる可能性があります。

このシナリオを回避するには:

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を参照してください。その記事からインスピレーションを得ました。彼は短所と長所について議論します。

編集:コメントに従って調整されたクリーンアップ

于 2012-05-23T22:56:36.983 に答える
0

minitech と同じ答えなので、クレジットを取得する必要がありますが、この例では、SubclassA の Changed は、完全な名前のクラスにキャストすることでそのプロパティを確認できます。

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();
        }
    }
}
于 2012-05-23T23:43:49.300 に答える