2010-08-25 56 views
3

我可以以某种方式得到初始化器C#对象初始化器 - 引用新的实例

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

到我使用对象创建的实例的引用“这个”应指向新的TestClass实例我创建。但它显然是指代码所在类的实例。

我不问这是否是一个很好的方法来做到这一点。 我知道,我能做到这一点是这样的:

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

我有一个复杂的场景,其中在对象初始化器的新实例的引用将会使生活更轻松。

这有可能以任何方式吗?

回答

3

有没有办法解决它,C#的说明书中明确表示,"It is not possible for an object or collection initializer to refer to the object instance being initialized."

至于为什么这是不可能的,我怀疑存在只是为了实现它没有很好的方式。我们希望一些相当于

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

我们只需要一个关键字来引用初始化内temp语法糖,但没有一个是容易获得的。我们不能使用this,因为它已经意味着初始值之外的东西。 SomeProperty = this.SomeMethod(this)是否应该等于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的变量的代码都不再起作用。微软通常需要一个非常好的理由来介绍重大更改,所以最好禁止访问正在初始化的对象。

+0

有趣的是,C#不支持这个,因为VB。像新的MyObject()与{.Property1 =“x”,.Property2 = .Property1 +“y”}}的工作。通常语言功能非常相似,但是在这种情况下它不是。由于此限制,我有一个相当复杂的LINQ查询,我似乎无法将其转换为C#。 – 2012-06-07 13:54:59

1

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

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

{x = y}是语法糖。它发生在构造函数之外。 – Andrey 2010-08-25 09:54:48

+0

是的,但'x'变量在初始化完成后才分配 – thecoop 2010-08-25 10:00:25

+0

@thecoop:请注意,我没有使用'x'变量。我指的是(显然不存在的)关键字。 – Stephane 2010-08-25 14:18:54

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

这个初始化的右侧部分之前被评估和执行,将参照新的对象还没有提供给代码。这是为了安全目的而完成的,否则你可能会在代码中创建一些死锁或无限循环。

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 
    } 
} 

这是一个极其人为的例子。事情可能会比这更糟糕。以下是关于此问题的相当有趣的链接: Partially Constructed Objects

+0

Andrey指出:“{x = y}是语法糖,它发生在构造函数之外。” – Stephane 2010-08-25 14:19:58