1

ユーザーがオブジェクト初期化子を使用できるようにするさまざまな派生オブジェクトがあります。これらのフィールドが設定されているときにtrueにしたい「Initializing」プロパティがあり、その後、Initializingプロパティをfalseに設定したいと思います。

これを実行できるようにするために、オブジェクト初期化がいつ実行されたかをどのように知ることができますか?

class Foo
{    
    Public Foo(string p1, string p2)
    {
        Initializing = true;
        Property1 = p1;
        Property2 = p2;
        Initializing = false;
    }

    bool Initializing;

    string _property1;
    string Property1 
    {
        get { return _property1; } 
        set { _property1 = value; DoSomething(); }
    }

    string Property2 { get; set; }

    public void DoSomething()
    {
        if(Initializing) return; // Don't want to continue if initializing
        // Do something here
    }
}

上記の例では、コンストラクターを使用すると正常に機能します。ただし、オブジェクト初期化子を使用して同じように機能させる方法が問題です。

編集:すべての否定論者のために、ここに私が探しているものを正確に探している他の誰かがいます-http: //blogs.clariusconsulting.net/kzu/how-to-make-object-initializers-more-useful/

残念ながら、それは不可能のように見えます。

4

6 に答える 6

4

オブジェクトの初期化を本当に追跡する必要がある場合は、そのロジックを手動で実装する必要があります。1つのアプローチは、WinFormsコードジェネレーターで使用されるものをコピーすることです。オブジェクトがプロパティをバッチで更新する必要がある場合に、オブジェクトがISupportInitializeインターフェイスを公開する場所。したがって、使用法は次のようになります...

var x = new Foo();
x.BeginInit();
x.Property1 = 1;
x.Property2 = 2;
x.EndInit();
于 2012-02-09T04:54:39.667 に答える
3

フラグを設定しても意味がありません。イニシャライザが実行されるまで、オブジェクトにアクセスすることはできません。例えば:

var object = new object() { Prop1 = "Boo" }

newから返された参照には、Prop1が設定されるまでアクセスできないため、どのプロパティにもアクセスする方法がありません。したがって、アクセスを制御したり、「完了」したかどうかを心配したりする必要はありません。

しかし、私はあなたがこのようなものをどのように持っているかを見ることができると思います:

public class Foo {
    private int _value;
    public int Bar {
        set {
            _value = value * Baz; // don't want to do this if initializing
        }
    }

    public int Baz { get; set; }
}

これが懸念事項である場合は、オブジェクトを誤って設計しています。プロパティはそのような副作用であってはなりません。すべての初期化が完了したかどうかを知る方法はありません。

于 2012-02-09T04:41:59.417 に答える
1

この質問は意味がありません。オブジェクト初期化構文は、単なる構文糖衣構文の省略形です。

これ:

var myInstance = new someClass()
{
    Prop1 = "",
    Prop2 = "",
    Prop3 = "",
    Prop4 = "",
    Prop5 = ""
}

これとまったく同じです:

var myInstance = new someClass();
myInstance.Prop1 = "";
myInstance.Prop2 = "";
myInstance.Prop3 = "";
myInstance.Prop4 = "";
myInstance.Prop5 = "";

検出される「完了」はありません。

あなたがしたいことは私たちのようなことをすることができます:

class someClass()
{
  public string AStringProperty { get; set; }
  public bool IsInitiazlied 
  {
    return string.IsNullOrWhitespace(this.AStringProperty);
  }
}

または、ctorに値の初期状態を取得させてから、セットアップを保証します。

class someClass()
{
  public string AStringProperty { get; set; }
  public someClass(string AStringPropertyInit)
  {
      this.AStringProperty = AStringPropertyInit;
  }
}

編集

class Foo
{    
    Public Foo(string p1, string p2)
    {

        _property1= p1; //set the backing store directly, 
                        //skips the side effect in the setter
        Property2 = p2;

        DoSomething(); // now cause the side effect
                       // we know everything is setup
    }



    string _property1;
    string Property1 
    {
        get { return _property1; } 
        set { _property1 = value; DoSomething(); }
    }

    string Property2 { get; set; }

    public void DoSomething()
    {
        // Do something here
    }
}
于 2012-02-09T04:37:58.893 に答える
1

オブジェクトの初期化は単なる構文糖衣であるため、通常のプロパティセットとの違いはわかりません。また、それらを別の方法で扱いたいという合理的なケースも考えられません。

とはいえ、x個のプロパティの少なくとも1つを設定する必要があると言っている場合(ロングハンドまたはショートハンドの構文)、ctorで初期化をtrueに設定し、すべてのプロパティセットでfalseに設定できます。

于 2012-02-09T04:39:40.437 に答える
1

オブジェクトが初期化されたときに通知する明示的なプロパティに依存するのではなく、DoSomethingメソッドに、そのジョブを実行するために必要な情報があることを検証させることができます。あなたの例はかなり粗雑で、実際の実装はもっと複雑だと思うので、それを仮定してProperty1何かProperty2に割り当てる必要があります(続行する前に空の文字列ではないことを意味します):

class Foo
{    
    public Foo(string p1, string p2)
    {
        Property1 = p1;
        Property2 = p2;
    }

    string Property1 { get; set; } 
    string Property2 { get; set; }

    public void DoSomething()
    {
        // *** Replace this with something valid to your real code
        if(!string.IsNullOrEmpty(Property1) || !string.IsNullOrEmpty(Property2)) 
            return; // Don't want to continue if not initialized
        // Do something here
    }
}

アップデート

実際に使用しているオブジェクトモデルについての知識がない場合、フレームワーク全体で広く使用されているモデルに基づいた代替案を次に示します。

class Foo
{
    public void DoSomething(FooConfig config)
    {
    }
}

また

class Foo
{
    private FooConfig config_;

    public Foo(FooConfig config)
    {
        config_ = config;
    }

    public void DoSomething()
    {
    }
}

FooConfig定義されている場所:

class FooConfig
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

そしてDoSomething、以下を使用して呼び出されます。

(new Foo()).DoSomething(new FooConfig() { Property1 = "abc"; Property2 = "def"; });

また

(new Foo(new FooConfig() { Property1 = "abc"; Property2 = "def"; })).DoSomething();

Fooこれは、またはのいずれかでのコンストラクターの使用に対応するように簡単に変更できますFooConfig

于 2012-02-09T05:17:38.343 に答える
0

オブジェクト初期化子は、オブジェクトを作成し、それに一連のプロパティを設定するための単なる省略形です。「いつ完了するのか」と尋ねるのは、あまり意味がありません。

オブジェクトの状態を、初期化される特定のプロパティセットに依存させたい場合は、各プロパティのセッターにコードを追加して、内部で追跡できます。しかし、それはあなたが何を達成しようとしているのかによります。

アップデート

@asawyerの回答に対するコメントを読んでください。プロパティがイニシャライザーに設定されているかどうかを判断する方法はありません。説明のために、これはまったく同じことを行う3つのコードですが、それぞれに異なる動作が必要なようです。

var someVar1 = new SomeClass()
               {
                    Prop1 = "value1";
                    Prop2 = "value2";
               };

var someVar2 = new SomeClass()
               {
                    Prop1 = "value1";
               };
someVar2.Prop2 = "value2";

var someVar3 = new SomeClass();
someVar3.Prop1 = "value1";
someVar3.Prop2 = "value2";

個々のプロパティセッターの実行を追跡し、最初の実行を除くすべてで何らかの副作用をトリガーすることは難しくありませんが、クライアントが初期オブジェクト構成を変更した場合にのみ副作用をトリガーしたいのは意味がありませんctorが終了した後。

于 2012-02-09T04:38:42.447 に答える