C # Object Initializer - ссылка на новый экземпляр - PullRequest
3 голосов
/ 25 августа 2010

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

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

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

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

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

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

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

Ответы [ 4 ]

5 голосов
/ 25 августа 2010

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

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

1 голос
/ 25 августа 2010

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

var x = new TestClass {
    Id = 1
};
x.SomeProperty = SomeMethod(x);
0 голосов
/ 25 августа 2010

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

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

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

0 голосов
/ 25 августа 2010
var x = new TestClass
           {
                 Id = 1,
                 SomeProperty = SomeMethod(this)
           }

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

...