C#Object Initialiser - 对新实例的引用

时间:2010-08-25 09:51:15

标签: c# syntax object-initializers

我可以以某种方式获取对我使用对象初始化器创建的实例的引用

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

“this”应该指向我正在创建的新TestClass实例。但它显然是指代码所在的类的实例。

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

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

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

这有可能吗?

4 个答案:

答案 0 :(得分:5)

没有办法绕过它,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已经代表缺少的参数,如果你认为属性getter是set_SomeProperty(value)方法的语法糖。使用它来引用对象初始化程序中缺少的变量看起来很有希望。但是,我们可以在属性设置器中创建此对象,在这种情况下value已被使用,我们需要能够temp.SomeProperty = SomeMethod(value)

看起来我们必须为此目的创建一个新关键字,可能是newthis。但是,这是对语言的重大更改,因为任何具有名为newthis的变量的代码都不再起作用。 Microsoft通常需要一个非常好的理由来引入重大更改,因此最好禁止访问正在初始化的对象。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

在评估和执行此初始化的右侧部分之前,对新代码的引用尚未可用于代码。这样做是为了安全起见,否则你可能会用代码创建一些死锁或无限循环。

答案 3 :(得分: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