C#对象初始化器-对新实例的引用

C#对象初始化器-对新实例的引用,c#,syntax,object-initializers,C#,Syntax,Object Initializers,我是否可以通过某种方式获得对使用对象初始化器创建的实例的引用 var x = new TestClass { Id = 1, SomeProperty = SomeMethod(this) } “this”应该指向我正在创建的新TestClass实例。但它显然引用了该代码所在的类的实例 我不是问这是不是一个好方法。 我知道我可以这样做: var x = new TestClass {

我是否可以通过某种方式获得对使用对象初始化器创建的实例的引用

var x = new TestClass
           {
                 Id = 1,
                 SomeProperty = SomeMethod(this)
           }
“this”应该指向我正在创建的新TestClass实例。但它显然引用了该代码所在的类的实例

我不是问这是不是一个好方法。 我知道我可以这样做:

var x = new TestClass {Id= x};
x.SomeProperty = SomeMethod(this);
我有一个复杂的场景,在这个场景中,在对象初始化器中引用新实例会使事情变得更简单


这在任何方面都是可能的吗?

不,您不能使用对象初始值设定项将您正在创建的对象分配到其他地方-这会破坏对象初始值设定项的整个要点。
x
变量直到对象初始值设定项完成后才被赋值。您需要分配对象,然后在单独的语句中使用它

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

在评估和执行此初始化的正确部分之前,代码尚未提供对新对象的引用。这是出于安全目的,否则您可能会在代码中创建一些死锁或无休止的循环。

这是无法避免的,C#规范明确指出

至于为什么不可能,我怀疑没有好的方法来实现它。我们想要一些相当于

var temp = new TestClass();
temp.Id = 1;
temp.SomeProperty = SomeMethod(temp);
x = temp;
我们只需要一个关键字来引用初始值设定项中的
temp
,但没有一个关键字是容易获得的。我们不能使用
这个
,因为它已经意味着初始值设定项之外的内容。
SomeProperty=this.SomeMethod(this)
是否应等同于
temp.SomeProperty=this.SomeMethod(temp)
temp.SomeProperty=temp.SomeMethod(temp)
?第二个是一致的,但是如果我们需要第一个怎么办

我们可以尝试使用
x
,但我们只能在新对象立即分配给变量时选择名称。但是,我们现在不能在初始值设定项中引用
x
的旧值,执行与
temp.SomeProperty=SomeMethod(x)
等效的操作

我们可以重用属性设置器中的
value
关键字。这听起来不错,因为如果您认为属性吸收器是一个语法糖,则代码< >值>代码>已经存在,因为“代码”> StIsOffice属性(value)< /C>方法。使用它来引用对象初始值设定项中缺少的变量看起来很有希望。但是,我们可以在属性设置器中创建此对象,在这种情况下,
value
已经被使用,我们需要能够执行
temp.SomeProperty=SomeMethod(value)


看起来我们必须为此创建一个新关键字,可能是
newthis
。然而,这对语言来说是一个突破性的改变,因为任何有一个名为
newthis
的变量的代码都不再工作了。Microsoft通常需要一个很好的理由来引入破坏性更改,因此最好禁止访问正在初始化的对象。

公开或使用尚未完全构造的对象通常是一个非常糟糕的主意。考虑以下事项:

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
     }
}
这是一个极其做作的例子。事情可能会变得比这更糟。关于这个问题,以下是一个非常有趣的链接:
{x=y}是语法糖。它发生在构造函数之外。是的,但是直到初始化器被初始化之后,
x
变量才被赋值completed@thecoop:请注意,我没有使用“x”变量。我指的是一个(显然不存在)关键字。正如Andrey指出的:“{x=y}是语法糖。它发生在构造函数之外。”有趣的是,C#不支持这一点,因为VB支持。类似于带有{.Property1=“x”,.Property2=.Property1+“y”}的new MyObject()的东西确实有效。通常,语言功能非常相似,但在本例中似乎并非如此。由于这个限制,我有一个相当复杂的LINQ查询,似乎无法转换为C。
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
     }
}