C# Object Initializer - ссылка на новый экземпляр

Можно ли как-то получить ссылку на экземпляр, который я создаю с помощью инициализатора объекта?

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

"this" должно указывать на новый экземпляр TestClass, который я создаю. Но это, очевидно, относится к экземпляру класса, в котором находится этот код.

Я не спрашиваю, является ли это хорошим способом сделать это. Я знаю, что я могу сделать это так:

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

У меня сложный сценарий, в котором ссылка на новый экземпляр в инициализаторе объекта облегчит жизнь.

Возможно ли это каким-либо образом?

4 ответа

Решение

Нет никакого способа обойти это, спецификация C# прямо говорит, что "инициализатор объекта или коллекции не может ссылаться на инициализируемый экземпляр объекта".

Что касается того, почему это невозможно, я подозреваю, что просто нет хорошего способа реализовать это. Нам нужен синтаксический сахар, эквивалентный

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 уже заменяет отсутствующий параметр, если вы считаете, что свойство get является синтаксическим сахаром для set_SomeProperty(value) метод. Использование его для ссылки на отсутствующую переменную в инициализаторе объекта выглядит многообещающе. Тем не менее, мы могли бы создать этот объект внутри установщика свойств, в этом случае value уже используется, и мы должны быть в состоянии сделать temp.SomeProperty = SomeMethod(value),

Похоже, нам нужно создать новое ключевое слово только для этой цели, может быть, newthis, Тем не менее, это серьезное изменение в языке, потому что любой код, который имеет переменную с именем newthis больше не работает Microsoft, как правило, нужна действительно веская причина для внесения критических изменений, поэтому лучше запретить доступ к инициализируемому объекту.

Нет, вы не можете использовать инициализатор объекта, чтобы назначить объект, который вы создаете где-то еще, - который побеждает весь смысл инициализатора объекта. x Переменная не присваивается, пока не завершится инициализация объекта. Вам нужно будет присвоить объект, а затем использовать его в отдельной инструкции.

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

Экспонировать или использовать объект, который не был полностью построен, обычно очень плохая идея. Учтите следующее:

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

Это чрезвычайно надуманный пример. Все может стать намного хуже, чем это. Следующее было довольно интересной ссылкой относительно этой проблемы: Частично построенные объекты

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

До того, как правая часть этой инициализации будет оценена и выполнена, ссылка на новый объект еще не сделана доступной для кода. Это делается в целях безопасности, в противном случае вы можете создать некоторый тупик или бесконечный цикл с вашим кодом.

Другие вопросы по тегам