Инициализатор объектов
От: _NN_ www.nemerleweb.com
Дата: 23.11.20 17:43
Оценка: 18 (3)
Всегда думал, что код
       a q = new a(1) {
            x = 1,
            y = 2,
        };


идентичен

        a tempq = new a(1);
        tempq.x = 1;
        tempq.y = 2;
        a q = tempq;


Однако при компиляции в релиз это не так.

Это так было всегда ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Инициализатор объектов
От: ksg71 Германия  
Дата: 23.11.20 17:59
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Всегда думал, что код

_NN>
_NN>       a q = new a(1) {
_NN>            x = 1,
_NN>            y = 2,
_NN>        };
_NN>


_NN>идентичен


_NN>
_NN>        a tempq = new a(1);
_NN>        tempq.x = 1;
_NN>        tempq.y = 2;
_NN>        a q = tempq;
_NN>


_NN>Однако при компиляции в релиз это не так.


_NN>Это так было всегда ?


заверни в try catch и все будет


        a q = null;
        try{
         q = new a(1) {
            x = 1,
            y = 2,
        };
        }
        
        catch {
        }

        Console.WriteLine(q);
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re[2]: Инициализатор объектов
От: _NN_ www.nemerleweb.com
Дата: 23.11.20 18:04
Оценка:
Здравствуйте, ksg71, Вы писали:

K>заверни в try catch и все будет

Вопрос не об этом.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Инициализатор объектов
От: ksg71 Германия  
Дата: 23.11.20 18:06
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Здравствуйте, ksg71, Вы писали:


K>>заверни в try catch и все будет

_NN>Вопрос не об этом.

а в чем? создается ситуация, когда временная переменная нужна.
получаете ваш код в релизе
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Отредактировано 23.11.2020 18:10 ksg71 . Предыдущая версия . Еще …
Отредактировано 23.11.2020 18:09 ksg71 . Предыдущая версия .
Re[4]: Инициализатор объектов
От: _NN_ www.nemerleweb.com
Дата: 23.11.20 18:13
Оценка: 8 (1)
Здравствуйте, ksg71, Вы писали:

K>Здравствуйте, _NN_, Вы писали:


_NN>>Здравствуйте, ksg71, Вы писали:


K>>>заверни в try catch и все будет

_NN>>Вопрос не об этом.

K>а в чем?


О том, что компилятор не создаёт временный объект в релизе, хотя в спецификации написано, что создаёт.

https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#object-initializers

An instance of Point can be created and initialized as follows:
Point a = new Point { X = 0, Y = 1 };

which has the same effect as
Point __a = new Point();
__a.X = 0;
__a.Y = 1; 
Point a = __a;
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Инициализатор объектов
От: JohnnyJ Германия  
Дата: 23.11.20 19:02
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>О том, что компилятор не создаёт временный объект в релизе, хотя в спецификации написано, что создаёт.


а есть принципиальная разница в наличии или отсутствии этой временной переменной?

С точки зрения языка эта переменная "невидимая и недоступная" (цитата из спецификации языка).

И, как мне кажется, формулировка в спецификации приведена как пример, иллюстрирующий конструкцию с точки зрения логической, а не технической.
Зри в корень!
Re[5]: Инициализатор объектов
От: ksg71 Германия  
Дата: 23.11.20 19:06
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Здравствуйте, ksg71, Вы писали:


K>>Здравствуйте, _NN_, Вы писали:


_NN>>>Здравствуйте, ksg71, Вы писали:


K>>>>заверни в try catch и все будет

_NN>>>Вопрос не об этом.

K>>а в чем?


_NN>О том, что компилятор не создаёт временный объект в релизе, хотя в спецификации написано, что создаёт.


_NN>https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#object-initializers


_NN>An instance of Point can be created and initialized as follows:

_NN>
_NN>Point a = new Point { X = 0, Y = 1 };
_NN>

_NN>which has the same effect as
_NN>
_NN>Point __a = new Point();
_NN>__a.X = 0;
_NN>__a.Y = 1; 
_NN>Point a = __a;
_NN>


чтоб такие вещи обосновать написали
https://stackoverflow.com/questions/1679780/when-using-object-initializers-why-does-the-compiler-generate-an-extra-local-va

Липперт:

Now, in your particular case, we could write an optimizing pass that detects that the extra local is unnecessary and optimize it away.


ну и написали
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Отредактировано 23.11.2020 19:09 ksg71 . Предыдущая версия .
Re: Инициализатор объектов
От: sergeya Ниоткуда http://blogtani.ru
Дата: 23.11.20 19:15
Оценка: 88 (2)
Здравствуйте, _NN_, Вы писали:

_NN>Всегда думал, что код

_NN>
_NN>       a q = new a(1) {
_NN>            x = 1,
_NN>            y = 2,
_NN>        };
_NN>


_NN>идентичен


_NN>
_NN>        a tempq = new a(1);
_NN>        tempq.x = 1;
_NN>        tempq.y = 2;
_NN>        a q = tempq;
_NN>


_NN>Однако при компиляции в релиз это не так.


_NN>Это так было всегда ?


Похоже сейчас компилятор пытается это оптимизировать, и создает временный объект, только если в коде есть верояность обращения к недоинициализированному объекту.
Пример
Мобильная версия сайта RSDN — http://rsdn.org/forum/rsdn/6938747
Автор: sergeya
Дата: 19.10.17
Re[2]: Инициализатор объектов
От: Kolesiki  
Дата: 23.11.20 19:52
Оценка:
Здравствуйте, sergeya, Вы писали:

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


Разве не пофиг, кто именно окажется "недоинициализированным" — временный объект или главный?? Иксепшн по-любому прерывает нормальный ход инициализации и ты не можешь пользоваться таким объектом.
Так что "временная переменная" как бы нафиг не нужна.
Re[5]: Инициализатор объектов
От: Kolesiki  
Дата: 23.11.20 19:55
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>О том, что компилятор не создаёт временный объект в релизе, хотя в спецификации написано, что создаёт.


_NN>which has the same effect as


В данном случае "тот же эффект" может быть попросту примером псевдокода. Т.е. для наглядности разложили присвоение на две части и расписали правую как "сложную конструкцию", выходом которой есть временный объект. В коде его генерировать не обязательно.
Re[6]: Инициализатор объектов
От: _NN_ www.nemerleweb.com
Дата: 23.11.20 19:59
Оценка:
Здравствуйте, JohnnyJ, Вы писали:

JJ>Здравствуйте, _NN_, Вы писали:


_NN>>О том, что компилятор не создаёт временный объект в релизе, хотя в спецификации написано, что создаёт.


JJ>а есть принципиальная разница в наличии или отсутствии этой временной переменной?


Есть небольшая разница .
Например у меня есть структура размером в несколько килобайт для работы с нативным кодом.
Метод вызывается часто.
С этой оптимизацией не нужно переживать за лишние копирования.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Инициализатор объектов
От: sergeya Ниоткуда http://blogtani.ru
Дата: 23.11.20 21:47
Оценка:
Здравствуйте, Kolesiki, Вы писали:

K>Здравствуйте, sergeya, Вы писали:


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


K>Разве не пофиг, кто именно окажется "недоинициализированным" — временный объект или главный?? Иксепшн по-любому прерывает нормальный ход инициализации и ты не можешь пользоваться таким объектом.

K>Так что "временная переменная" как бы нафиг не нужна.

Временный недоступен за пределами блока try. Посмотри пример, который я выложил в первом сообщении.

public class C {
    public void M() {
        a a = null;

        try {
            a = new a(1) {
                x = 1,
                y = 2,
            };
        } catch {
            a.ToString(); // если закомментировать эту строчку, то компилятор выкинет создание временного объекта
        }
    }
}
Мобильная версия сайта RSDN — http://rsdn.org/forum/rsdn/6938747
Автор: sergeya
Дата: 19.10.17
Re[2]: Инициализатор объектов
От: _NN_ www.nemerleweb.com
Дата: 24.11.20 00:35
Оценка:
Здравствуйте, sergeya, Вы писали:

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

Можно даже без try-catch.
Достаточно объявить поле класса или ref/out аргумент.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Инициализатор объектов
От: alexzzzz  
Дата: 01.12.20 16:49
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>
_NN>        a tempq = new a(1);
_NN>        tempq.x = 1;
_NN>        tempq.y = 2;
_NN>        a q = tempq;
_NN>


_NN>Однако при компиляции в релиз это не так.


При компиляции всё то же самое, просто отсутствует последняя строка: a q = tempq, потому что нафиг не нужна. А что временная локальная переменная, с которой происходят операции, называется "q", а не "temp" или как-то по-другому, это роли не играет. Локальные переменные вообще штуки эфемерные. Могут существовать или не существовать независимо от того, что ты наобъявлял в своём коде; их имена ни на что не влияют и через рефлексию недоступны.

Если финальная переменная не локальная, а какое-нибудь доступное извне поле
    public static A a;
    
    public void M()
    {
        a = new A(1)
        {
            x = 1,
            y = 2,
        };
    }

то после компиляции получается ожидаемо
    public static A a;

    public void M()
    {
        A obj = new A(1);
        obj.x = 1;
        obj.y = 2;
        a = obj;
    }
Отредактировано 01.12.2020 16:55 alexzzzz . Предыдущая версия . Еще …
Отредактировано 01.12.2020 16:54 alexzzzz . Предыдущая версия .
Отредактировано 01.12.2020 16:53 alexzzzz . Предыдущая версия .
Отредактировано 01.12.2020 16:52 alexzzzz . Предыдущая версия .
Отредактировано 01.12.2020 16:50 alexzzzz . Предыдущая версия .
Отредактировано 01.12.2020 16:49 alexzzzz . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.