8

検証、変更追跡などを行うために、プロパティのバッキング フィールドにアクセスする方法はありますか?

次のようなことは可能ですか?そうでない場合、.NET 4 / C# 4 で使用する予定はありますか?

public string Name
{
    get;
    set
    {
        if (value != <Keyword>)
        {
            RaiseEvent();
        }
        <Keyword> = value;
    }
}

私が抱えている主な問題は、自動プロパティを使用すると、明示的なバッキングフィールドを持つプロパティと同じように検証などの柔軟性が得られないことです。ただし、明示的なバッキング フィールドには、アクセスしている可能性のある他のクラスと同様に、プロパティの検証、変更追跡などにアクセスして再利用する必要があるときに、それが含まれているクラスがバッキング フィールドにアクセスできるようにするという欠点があります。プロパティを外部に。

上記の例では、バッキング フィールドへのアクセスのスコープがプロパティに限定されるため、プロパティの検証や変更の追跡などの回避が防止されます。

編集: < Backing Field > を < Keyword > に変更しました。価値に似た新しいキーワードを提案します。フィールドはうまく機能しますが、多くの既存のコードで使用されていると確信しています。

4

6 に答える 6

13

いいえ、ありません。バッキング フィールドにアクセスする場合は、自動プロパティを使用せず、独自のロールを作成してください。

クラスの他のメンバーではなく、プロパティのみがアクセスできるフィールドがあれば素晴らしいと思います。私はいつもそれを使用します。

于 2009-03-15T22:42:10.477 に答える
6

MSDNが述べているように:

「C# 3.0 以降では、プロパティ アクセサーに追加のロジックが必要ない場合、自動実装プロパティによりプロパティ宣言がより簡潔になります。また、クライアント コードでオブジェクトを作成できるようになります。次の例に示すようにプロパティを宣言すると、コンパイラはプロパティの get アクセサーと set アクセサーを介してのみアクセスできる、プライベートで匿名のバッキング フィールドを作成します。」

アクセサーに追加のロジックがあるため、シナリオでは自動実装プロパティの使用は適切ではありません。

バッキング フィールドは存在しますが、簡単に参照できないようにマングルされた名前が付けられています。つまり、フィールドを直接参照することはありません。興味のために、Reflector を使用してコードを逆アセンブルし、フィールド名を見つけることができますが、この名前は実際には揮発性である可能性があるため、フィールドを直接使用しないことをお勧めします。そのため、コードはいつでも壊れる可能性があります。

于 2009-03-15T23:06:13.133 に答える
3

Mehrdad の回答であなたのコメントを読んだので、私はあなたの問題をもう少しよく理解していると思います。

開発者が作成しているクラスのプライベート状態にアクセスしたり、検証ロジックをバイパスしたりする能力について懸念しているようです。これは、状態をクラスにまったく含めるべきではないことを示唆しています。

次の戦略を提案します。ValidatedValue を表すジェネリック クラスを記述します。このクラスはバッキング値のみを保持し、get および set メソッドを介したアクセス/ミューテーションのみを許可します。検証ロジックを表すデリゲートが ValidatedValue に渡されます。

public class ValidatedValue< T >
{
    private T m_val;
    public ValidationFn m_validationFn;

    public delegate bool ValidationFn( T fn );

    public ValidatedValue( ValidationFn validationFn )
    {
        m_validationFn = validationFn;
    }

    public T get()
    {
        return m_val;
    }

    public void set(T v)
    {
        if (m_validationFn(v))
        {
            m_val = v;
        }
    }
}

もちろん、必要に応じてデリゲートを追加することもできます (たとえば、変更前後の通知をサポートするため)。

クラスは、プロパティのバッキング ストアの代わりに ValidatedValue を使用します。

次の例は、100 未満であることが検証された整数を持つクラス MyClass を示しています。例外をスローするロジックは、ValidatedValue ではなく、MyClass にあることに注意してください。これにより、MyClass に含まれる他の状態に依存する複雑な検証ルールを実行できます。ラムダ表記を使用して検証デリゲートを構築しました。代わりに、メンバー関数にバインドすることもできました。

public partial class MyClass
{
    private ValidatedValue<int> m_foo;

    public MyClass()
    {
        m_foo = new ValidatedValue<int>(
            v => 
            {
                if (v >= 100) RaiseError();
                return true;
            }
        );
    }

    private void RaiseError()
    {
        // Put your logic here....
        throw new NotImplementedException();
    }

    public int Foo
    {
        get { return m_foo.get(); }
        set { m_foo.set(value); }
    }
}

それが役立つことを願っています-元のトピックから多少外れていますが、実際の懸念とより一致していると思います. 私たちが行ったことは、検証ロジックをプロパティから取り除き、それをデータに配置することです。これはまさにあなたが望んでいた場所です。

于 2009-03-16T00:49:37.270 に答える
2

いいえ。ただし、サブクラスでは次のことができます。

public class Base
{
    public string Name
    {
        get;
        virtual set;
    }
}

public class Subclass : Base
{
    // FIXME Unsure as to the exact syntax.
    public string Name
    {
        override set
        {
            if (value != base.Name)
            {
                RaiseEvent();
            }

            base.Name = value;
        }
    }
}
于 2009-03-16T01:35:36.787 に答える
1

そうするつもりなら、なぜ自動プロパティを使用しているのですか?!

単純なプロパティは、1.0 にさかのぼります。特殊なケースごとに言語を複雑にすることは意味がないと思います。単純なストア/取得モデルを実行するためのプロパティが必要か、それ以上のものが必要です。後者の場合、通常のプロパティで十分です。

于 2009-03-15T22:40:26.537 に答える
1

あなたはこれを行うことはできません。これが、自動プロパティを Notify プロパティに変換する機能を提供するためにMoXAML Power Toysを書き始めた理由の 1 つです。

于 2009-03-15T22:44:56.807 に答える