3

オブジェクト「A」と「B」の 2 つのシーケンスがあります。シーケンスを比較すると、次のことを示す要素の 3 番目のシーケンス「C」が生成されます。

  • オブジェクトが「A」から「削除」された、または
  • 「B」から「挿入」。

残りの要素はすべて「一致」したと見なされます。

私がしたいこと:

基本クラスからすべてのプロパティを継承する、、、およびジェネリック クラスをInserted<T>宣言Deleted<T>します。ジェネリック クラスは、継承するオブジェクトから自身をインスタンス化できる必要があります。Matched<T>T

コード:

public interface IInstantiable<T>
{
    void CopyFrom(T o);
}

[Serializable]
public class Inserted<T> : T
    where T : IInstantiable<T>
{
    public Inserted() { }
    public Inserted(T t)
    {
        this.CopyFrom(t);
    }
}

エラー:

'MyNamespace.Inserted<T>' does not contain a definition for 'CopyFrom' and no 
extension method 'CopyFrom' accepting a first argument of type 'MyNamespace.Inserted<T>' 
could be found (are you missing a using directive or an assembly reference?)

さらなる議論:

IInstantiableメソッドの存在を強制する独自のインターフェイスを定義しますCopyFrom。標準ICloneableインターフェイスは、オブジェクトを新しいインスタンスにコピーするメソッドしか定義していないため、使用できませんが、コンストラクターでメンバーをコピーするにはオブジェクトが必要です。

CopyFromジェネリックがメソッドの独自の実装を定義すると、エラーはなくなります。CopyFromただし、これでは、基本クラスの特定のニーズを処理するためにメソッドを特殊化するという望ましい目標は達成されません。どのプロパティをコピーする必要があるかを知ることができるのは、基本クラスだけです。(または、何かが足りないのですか?)

: オブジェクトはシリアル化できる必要があるため、最終的なオブジェクトには、その基本クラスと同じパブリック メンバーが必要です。

これは .NET で可能ですか?

答え:

ジェネリック クラスがテンプレート基本クラスの拡張になることはできないため、私がやろうとしていることは不可能です。Visual Studio は、「'T' は型パラメーターであるため、'T' から派生できません」と不平を言います。CopyFrom(ジェネリック クラスにメソッドをまだ実装していないため、このエラーにはまだ気付きませんでした。)

インターフェイスをクラスに変更し、そのクラスにスタブ実装を提供する場合、以下に提案するようにそれを継承できます。ただし、これにより、継承階層に新しい基本クラスが導入されます。

public class IInstantiable<T>
{
    public virtual void CopyFrom(T o) { }
}

[Serializable]
public class Inserted<T> : IInstantiable<T>
    where T : IInstantiable<T>
{
    public Inserted() { }
    public Inserted(T t)
    {
        base.CopyFrom(t);
    }
}

残念ながら、継承階層のルートに導入する必要があるため、この新しい基本クラスをテンプレート化された形式で使用することはできません。テンプレートを削除して、できるだけ汎用的にした場合にのみ機能します。

public class IInstantiable
{
    public virtual void CopyFrom(Object o) { }
}

ただし、これでもInserted<T>ジェネリックは初期化元のオブジェクトのようには見えず、型パラメーターと同じ型から継承できないため、当初の目的には合いません。

型システムに基づく「派手なジェネリック」から離れて、より一般的な注釈付き構造に移行することが、最善の解決策であることが証明される可能性があります。ただし、選択したシリアル化アプローチ (XmlSerialization) の既定の動作には、この構成を実行可能なソリューションにする自動サポートがありません。ジェネリックは機能しません。代わりに、ハードコーディングされたクラス定義を使用してください。

4

2 に答える 2

3

これは、上記のコードで間接的に宣言しようとしていることです。

[Serializable]
public class Inserted<T> : IInstantiable<T>
    where T : IInstantiable<T>
{
    public Inserted() { }
    public Inserted(T t)
    {
        this.CopyFrom(t);
    }
}

これは意味がありますか?

.NETでは、ジェネリックパラメータから継承することはできません。どうしてそれができますか?ジェネリックスは実行時に評価されますが、コンパイル時にクラスがどのタイプであるかを知る必要があります。

于 2013-02-28T21:58:12.910 に答える
1

私の理解が正しければ、一連のオブジェクトに、それらの状態 (挿入、削除、または一致) の概念で注釈を付けたいと考えています。

これには派手なジェネリックは必要ありません。どうしたの:

enum ChangeState { Inserted, Deleted, Matched }
struct<T> Annotated { 
    public T Obj; 
    public ChangeState;
}

必要に応じてこれをシリアル化するようにマークできます (Annotatedオブジェクトは、同じプロパティ/フィールドがなくても問題なくシリアル化できます)。

型システムでより多くの情報をエンコードできますが、ここでどのような利点があるかは私にはわかりません。よろしいですか?

于 2013-02-28T22:27:02.313 に答える