4

オブジェクト初期化子を使用して作成中のインスタンスへの参照を取得できますか

var x = new TestClass
           {
                 Id = 1,
                 SomeProperty = SomeMethod(this)
           }

「this」は、作成中の新しい TestClass インスタンスを指す必要があります。しかし、それは明らかに、このコードが存在するクラスのインスタンスを参照しています。

これがこれを行う良い方法かどうかは尋ねていません。私はこれを次のようにできることを知っています:

var x = new TestClass {Id= x};
x.SomeProperty = SomeMethod(this);

オブジェクト初期化子で新しいインスタンスを参照すると、作業が楽になるという複雑なシナリオがあります。

これは何らかの方法で可能ですか?

4

4 に答える 4

6

これを回避する方法はありません。C# の仕様では、 「オブジェクトまたはコレクション初期化子が初期化中のオブジェクト インスタンスを参照することはできません」と明示的に述べられています。

なぜそれが不可能なのかというと、それを実装する良い方法がないだけだと思います。と同等の構文糖衣が必要です

var temp = new TestClass();
temp.Id = 1;
temp.SomeProperty = SomeMethod(temp);
x = temp;

tempイニシャライザ内で参照するキーワードが必要なだけですが、簡単に利用できるものはありません。thisすでにイニシャライザの外にあるものを意味しているため、使用できません。または?SomeProperty = this.SomeMethod(this)と同等である必要があります。2 番目は一貫性がありますが、1 番目が必要な場合はどうなるでしょうか。temp.SomeProperty = this.SomeMethod(temp)temp.SomeProperty = temp.SomeMethod(temp)

を使用することxもできますが、新しいオブジェクトがすぐに変数に割り当てられる場合にのみ名前を選択できます。xただし、イニシャライザ内での古い値を参照することはできなくなり、 と同等の処理が行われtemp.SomeProperty = SomeMethod(x)ます。

valueプロパティ セッターのキーワードを再利用できます。valueプロパティ ゲッターがメソッドのシンタックス シュガーであると考える場合、欠落しているパラメーターの代役をすでに果たしているため、これは良さそうですset_SomeProperty(value)。それを使用して、オブジェクト初期化子で欠落している変数も参照することは有望に見えます。ただし、プロパティ セッター内でこのオブジェクトを作成することもできます。その場合、valueは既に使用されており、できるようにする必要がありますtemp.SomeProperty = SomeMethod(value)

この目的のためだけに、新しいキーワードを作成する必要があるようnewthisです。newthisただし、変数が呼び出されたコードは機能しなくなるため、これは言語に対する重大な変更です。Microsoft は通常、互換性を破る変更を導入する正当な理由を必要とするため、初期化中のオブジェクトへのアクセスを禁止することをお勧めします。

于 2010-08-25T10:37:36.637 に答える
1

いいえ、オブジェクト初期化子を使用して、作成しているオブジェクトを別の場所に割り当てることはできません。これは、オブジェクト初期化子のポイント全体を無効にします。オブジェクト初期化子が完了するまで、x変数は割り当てられません。オブジェクトを割り当ててから、別のステートメントで使用する必要があります。

var x = new TestClass {
    Id = 1
};
x.SomeProperty = SomeMethod(x);
于 2010-08-25T09:53:54.900 に答える
0

完全に構築されていないオブジェクトを公開または使用することは、通常、非常に悪い考えです。次の点を考慮してください。

class Connection
{
    internal string connectionString;
    public Connection(ConnectionPool pool, string connectionString) {
        this.pool = pool;
        //this.connectionString = connectionString; // I moved it because I could.
        this.pool.Register(this);
        this.connectionString = connectionString;
        this.Init();        
    }

    private void Init() { //blah }
}

class ConnectionPool
{
     public void Register(Connection c)
     {
         if ( this.connStrings.Contains( c.connectionString ) ) // BOOM
     }
}

これは非常に不自然な例です。事態はこれよりもずっと悪くなる可能性があります。以下は、この問題に関する非常に興味深いリンクでした: 部分的に構築されたオブジェクト

于 2010-08-25T12:08:49.357 に答える
-1
var x = new TestClass
           {
                 Id = 1,
                 SomeProperty = SomeMethod(this)
           }

この初期化の正しい部分が評価されて実行される前に、新しいオブジェクトへの参照はまだコードで利用可能にされていません。これはセキュリティの目的で行われます。そうしないと、コードでデッドロックまたは無限ループが発生する可能性があります。

于 2010-08-25T09:57:11.213 に答える