3

この質問は私の質問と非常に似ているかもしれませんが、必要な答えがわかりません。という名前のクラスCASMがあり、List<Action>. このクラスをシリアライズしたい (BinaryFormatterまたは同様のものを使用して)。このクラスと で参照されているすべてのクラスは、Action正しい属性[Serializable]を持っています。[NonSerializable]

シリアル化が試行されたときに問題が発生します-次のエラーが発生します:

Type 'CASM.CASM+<>c__DisplayClass2c' in Assembly 'CASM, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null' is not marked as serializable.

これ<>c__DisplayClass2cは、アプリケーションで使用しているさまざまな種類の匿名デリゲートを保持する、自動生成された内部クラスです。ただし、下の画像からわかるように、そうではありません[Serializable]

代替テキスト http://bayimg.com/image/maebbaacj.jpg

これが機能するようにアプリケーションを変更する最良の方法は何ですか? 独自の<>c__DisplayClass2c型クラスを作成し、シリアライズ可能にしますか? それとももっと良い方法がありますか?


編集:最後に、自動生成されたクラスではなく、独自のクラスを作成しました。デバッグにも役立ちます。実際には、単にb__12().

4

1 に答える 1

4

通常、デリゲートをシリアル化することはほとんど意味がありません。通常、デリゲート フィールドを としてマーク[NonSerialized]し、必要に応じて再作成することを選択します。デリゲートを格納することが主な目的である場合は、率直に言って、まったく別のアプローチを検討することをお勧めします。

さらに、BinaryFormatterデータを長期間保持することを計画している場合は脆弱であることに注意してください (ただし、一時的なデータには許容されます)。

さらに詳しく調べるには、再現可能なコードを調べる必要があると思います。


更新: 実際には、(コンパイラによって生成されたものではなく) 独自の明示的なキャプチャ クラスを作成することでシリアル化できると思われます。しかし、私はまだそのコンセプトに根本的な欠陥があると考えています。また、キャプチャ クラスを手動で記述するのは楽しくありません。


コメントのポイントに対処するには; 長期保管について -非常に脆いので- 以下から変更するのと同じくらい簡単です:

public int Value {get;set;}

private int value;
public int Value {
    get {return value;}
    set {
        if(value < 0) throw new ArgumentOutOfRangeException();
        this.value = value;
    }
}

シリアル化を破棄します。アセンブリの変更、型名の変更、「見た目がおかしい」などです。

代議員について。手動キャプチャの例を挙げます。それ以外の:

int i = ...
Predicate<Foo> test = delegate (Foo x) { return x.Bar == i;}

あなたがするかもしれません:

int i = ...
MyCapture cpt = new MyCapture(i);
Predicate<Foo> test = cpt.MyMethod;

[Serializable]
class MyCapture {
    private int i;
    public MyCapture(int i) {this.i = i;}
    public bool MyMethod(Foo x) {return x.Bar == i;}
}

ご覧のとおり、必ずしも簡単ではありません (これは最も単純な例です)。

于 2009-10-24T17:53:12.453 に答える