Когда new, a koгда можно без?
От: nt2000  
Дата: 15.10.19 10:05
Оценка:
Как определяете при объявлении переменных? Есть признаки или надо просто запомнить?
Re: Когда new, a koгда можно без?
От: Mihas  
Дата: 15.10.19 10:16
Оценка:
Здравствуйте, nt2000, Вы писали:

N>Как определяете при объявлении переменных? Есть признаки или надо просто запомнить?

А можно примеры? Так-то, тут такое разнообразие..
Re[2]: Когда new, a koгда можно без?
От: nt2000  
Дата: 15.10.19 10:26
Оценка:
Здравствуйте, Mihas, Вы писали:

M>А можно примеры? Так-то, тут такое разнообразие..


DateTime d1 = new DateTime(DateTime.Today.Year,   int.Parse(d[0]),   int.Parse(d[1]));


Я вот тут и не сообразил, что надо нев, пока висуалстудио не подсказало..
Re[3]: Когда new, a koгда можно без?
От: Ночной Смотрящий Россия  
Дата: 15.10.19 10:44
Оценка:
Здравствуйте, nt2000, Вы писали:

N>Я вот тут и не сообразил, что надо нев, пока висуалстудио не подсказало..


А когда не надо?
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[4]: Когда new, a koгда можно без?
От: Sharov Россия  
Дата: 15.10.19 10:47
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>А когда не надо?


Через какой-нибудь Buidler или фабрику.
Кодом людям нужно помогать!
Re[4]: Когда new, a koгда можно без?
От: nt2000  
Дата: 15.10.19 11:41
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>А когда не надо?


int a=1;
a=2;
a=3;
Re[5]: Когда new, a koгда можно без?
От: Ночной Смотрящий Россия  
Дата: 15.10.19 11:46
Оценка: 3 (1)
Здравствуйте, nt2000, Вы писали:

N>
int a=1;
N>a=2;
N>a=3;


Ну вот ты и ответил на свой вопрос. Константы без new, остальное с new. Список типов констант есть в описании языка, он совсем небольшой. И есть еще одна форма array initializer без new.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[6]: Cпасобо, понятно. Вроде.
От: nt2000  
Дата: 15.10.19 13:22
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Здравствуйте, nt2000, Вы писали:


N>>
int a=1;
N>>a=2;
N>>a=3;


НС>Ну вот ты и ответил на свой вопрос. Константы без new, остальное с new. Список типов констант есть в описании языка, он совсем небольшой. И есть еще одна форма array initializer без new.
Re: Когда new, a koгда можно без?
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.10.19 13:27
Оценка: 3 (1)
Здравствуйте, nt2000, Вы писали:

N>Как определяете при объявлении переменных? Есть признаки или надо просто запомнить?

Когда имя класса структуры, тогда new.

var a = 1; //Численный литерал, не имя класса
var b = "str"; //строковый литерал, не имя класса
var c = f(a); //выражение, не имя класса
var d = new DateTime(...); // Имя структуры, нужно new
var e = DateTime.Now; // Выражение, не имя класса
var e = new int[10]; // специальный случай для массивов, но  целом то же самое, ибо int[] - имя класса массива интов
Re: Когда new, a koгда можно без?
От: alexzzzz  
Дата: 15.10.19 14:07
Оценка: 3 (1) +3
Здравствуйте, nt2000, Вы писали:

N>Как определяете при объявлении переменных? Есть признаки или надо просто запомнить?


Объявление переменной и new — вещи перпендикулярные. Чтобы объявить переменную, достаточно написать её тип, её имя и всё — переменная объявлена:
int x;
DateTime d;
MyClass instance;


Дальше мы, вероятно, хотим этой переменной что-нибудь присвоить. Вопрос, что именно? Если какое-то уже существующее значение (константу, литерал, результат выражения, значение другой переменной...), то берём и присваиваем без всяких new:
x = 5;
x = y + 10;
dateTime = default;
dateTime = DateTime.Now;
instance = null;
instance = someOtherInstance;


Оператор new требуется, когда нужно создать новый объект ссылочного типа (по-другому новые объекты ссылочных типов не создаются, экзотику не рассматриваю):
MyClass instance1 = new MyClass();
MyClass instance2 = new MyClass(...);


или нужно получить новое значение value-типа, через конструктор этого типа:
DateTime dateTime = new DateTime(...);


Для value-типов альтернативой вызову конструктора может быть ручная инициализация всех имеющихся полей. Например:
struct Vector3
{
    public float x, y, z;
    public Vector3(float x, float y, float z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
    public Vector3(float value)
    {
        this.x = value;
        this.y = value;
        this.z = value;
    }
}


Можно так:
Vector3 v1 = new Vector3(1, 2, 3); // объявили переменную и вызвали конструктор типа для "конструирования" нового значения этого типа
Vector3 v2 = new Vector3(1); // аналогично

а можно так:
Vector3 v; // объявили переменную value-типа,
v.x = 1; // вручную инициализировали все-
v.y = 2; // -все-
v.z = 3; // -все её поля
Отредактировано 15.10.2019 14:24 alexzzzz . Предыдущая версия . Еще …
Отредактировано 15.10.2019 14:24 alexzzzz . Предыдущая версия .
Отредактировано 15.10.2019 14:19 alexzzzz . Предыдущая версия .
Отредактировано 15.10.2019 14:11 alexzzzz . Предыдущая версия .
Re[2]: Ну спасибо за развёрнутый ответ..
От: nt2000  
Дата: 15.10.19 20:36
Оценка:
Здравствуйте, alexzzzz, Вы писали:

A>или нужно получить новое значение value-типа, через конструктор этого типа:

A>
DateTime dateTime = new DateTime(...);


Интересно чисто для самообразования..
Если переменные ради значений порождают огромные махины — классы, потом после получения желанных значений куда деваются эти классы? болтаются как бедные родственники никому не нужные? а если переменная захочет получить другие значения, то надо рожать опять новый экземпляр?
Re[3]: Ну спасибо за развёрнутый ответ..
От: Danchik Украина  
Дата: 15.10.19 21:11
Оценка:
Здравствуйте, nt2000, Вы писали:

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


A>>или нужно получить новое значение value-типа, через конструктор этого типа:

A>>
DateTime dateTime = new DateTime(...);


N>Интересно чисто для самообразования..

N>Если переменные ради значений порождают огромные махины — классы, потом после получения желанных значений куда деваются эти классы? болтаются как бедные родственники никому не нужные? а если переменная захочет получить другие значения, то надо рожать опять новый экземпляр?

Так, для ясности из какого языка вы на C# перешли?
Re[3]: Ну спасибо за развёрнутый ответ..
От: GarryIV  
Дата: 15.10.19 21:26
Оценка:
Здравствуйте, nt2000, Вы писали:

N>Если переменные ради значений порождают огромные махины — классы

Перменные не порождают классы.
WBR, Igor Evgrafov
Re[4]: Ну спасибо за развёрнутый ответ..
От: Sharov Россия  
Дата: 15.10.19 23:57
Оценка: +1
Здравствуйте, Danchik, Вы писали:

D>Так, для ясности из какого языка вы на C# перешли?


Похоже, это первый язык.
Кодом людям нужно помогать!
Re[5]: Когда new, a koгда можно без?
От: IT Россия linq2db.com
Дата: 16.10.19 02:57
Оценка:
Здравствуйте, nt2000, Вы писали:

НС>>А когда не надо?


N>
int a=1;
N>a=2;
N>a=3;


Если не видишь разницы, то лепи везде. Не ошибёшься.

int a=new int(1);
a=new int(2);
a=new int(3);
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: Ну спасибо за развёрнутый ответ..
От: varenikAA  
Дата: 16.10.19 06:00
Оценка:
Здравствуйте, Danchik, Вы писали:

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


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


A>>>или нужно получить новое значение value-типа, через конструктор этого типа:

A>>>
DateTime dateTime = new DateTime(...);


И все-таки, интересно, почему в некоторых языках используется new?
Ведь он усложняет анализ кода.
На память в делфи Class.Create(), в nim — newPerson(), в немерле Class().
C, C#, и, внезапно, F# — new!
т.е. чтобы пользоваться в F# функциональщиной, нужно делать фабричную функцию:
let date () = new DateTime() 
let d = date()


Чисто визуально даже, приятней было бы:
let d = DateTime()


В ди например, это имеет особый смысл, там выражение new(uint size,...)
определяет где будет создан объект(по умолчанию в куче), если же new для локальной переменной функции класса, то на стэке.
можно явно указать new(размер выделяемой памяти), естественно, можно расширять поведение инициализации, явно реализуя метод класса вида: new(uint size,int a, string b).
Но в C# по-моему, нужно было разрешить вызывать конструкторы как статические методы. Это логичнее.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[5]: Ну спасибо за развёрнутый ответ..
От: Jack128  
Дата: 16.10.19 09:50
Оценка:
Здравствуйте, varenikAA, Вы писали:

В С++ new использует не для создания объекта, а для выделения динамической памяти. А так как сборщиков мусора там нема, то и отдельные ключ слова для выделения/освобождения памяти там очень кстати были.
А во всякие шарпы потащили new — чтоб было похоже на плюсы.
Re[5]: Ну спасибо за развёрнутый ответ..
От: Sharov Россия  
Дата: 16.10.19 10:09
Оценка:
Здравствуйте, varenikAA, Вы писали:

AA>И все-таки, интересно, почему в некоторых языках используется new?

AA>Ведь он усложняет анализ кода.

Я считю наоборот, упрощает. Хотя в это дело привычки, если человек начал с питона, то неудобно.

AA>На память в делфи Class.Create(), в nim — newPerson(), в немерле Class().

AA>C, C#, и, внезапно, F# — new!

Чем newPerson лучше new Person?


AA>Но в C# по-моему, нужно было разрешить вызывать конструкторы как статические методы. Это логичнее.


А почему не различать создание объекта здесь и сейчас и делегацию создания -- builder, fabric?
Кодом людям нужно помогать!
Re[3]: Ну спасибо за развёрнутый ответ..
От: alexzzzz  
Дата: 16.10.19 12:24
Оценка: 3 (1) +1
Здравствуйте, nt2000, Вы писали:

A>>или нужно получить новое значение value-типа, через конструктор этого типа:

A>>
DateTime dateTime = new DateTime(...);


N>Интересно чисто для самообразования..

N>Если переменные ради значений порождают огромные махины — классы, потом после получения желанных значений куда деваются эти классы? болтаются как бедные родственники никому не нужные? а если переменная захочет получить другие значения, то надо рожать опять новый экземпляр?

Сначала немножко про терминологию.

Есть ссылочные типы: классы, интерфейсы, делегаты, строки, массивы. Переменная ссылочного типа хранит ссылку (грубо говоря, указатель) на объект (по-другому экземпляр) этого типа, расположенный в куче (обычно). А объект/экземпляр в свою очередь хранит в себе полезные и некоторые служебные данные. Т.е. слово класс обозначает какой-то ссылочный тип, а объект или экземпляр класса ― это та штука, в которой хранятся данные этого типа.

Есть value-типы: структуры, перечисления (enum) и все встроенные числовые и логические типы (int, float, bool...). Переменная value-типа хранит непосредственно данные.

Есть ещё отдельно указатели, но хрен с ними.

Согласно спецификации, значением переменной ссылочного типа является ссылка на объект (который где-то там лежит и что-то хранит) или null, значением переменной value-типа являются непосредственно сами данные этого типа.

--
DateTime dateTime = new DateTime(...);

Оператор new нестрашный. В случае value-типов, а DateTime — это структура, value-тип, new просто обозначает вызов конструктора. Никакого объекта где-то в куче не создаётся, просто под переменную выделяется место на стеке (если переменная локальная) и вызывается конструктор, который заполняет это место правильными данными. Если переменная сильно временная и помещается в регистр процессора, то и место в стеке может не выделяться — это на усмотрение jit-компилятора.

struct Vector2
{
    public float x, y;

    public Vector2(float x, float y)
    {
        this.x = x;
        this.y = y;
    }

    public void Initialize(float x, float y)
    {
        this.x = x;
        this.y = y;
    }
}


Что мы напишем
var v = new Vector2(1, 2);

что
var v = new Vector2();
v.Initialize(1, 2);
что
Vector2 v = default;
v.Initialize(1, 2);

что
Vector2 v;
v.x = 1;
v.y = 2;

никакой разницы не будет. Разве что конкретный JIT-компилятор в конкретных условиях может заинлайнить вызов функции, а может не заинлайнить. Разницы по потреблению памяти точно не будет.

Если тип ссылочный, например строка:
var s = new string('X', 3);

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

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

Если переменной s позже изменить значение ― присвоить null или ссылку на другой объект, то наш первый объект, если на него больше никто не ссылается, будет сожран сборщиком мусора, если сборщик мусора этого захочет.
Отредактировано 16.10.2019 13:44 alexzzzz . Предыдущая версия . Еще …
Отредактировано 16.10.2019 13:41 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 13:40 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 13:39 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 13:33 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 13:31 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 13:29 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 12:46 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 12:41 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 12:40 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 12:40 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 12:37 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 12:36 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 12:36 alexzzzz . Предыдущая версия .
Отредактировано 16.10.2019 12:36 alexzzzz . Предыдущая версия .
Re[5]: Ну спасибо за развёрнутый ответ..
От: alexzzzz  
Дата: 16.10.19 12:30
Оценка: +1
Здравствуйте, varenikAA, Вы писали:

AA>Чисто визуально даже, приятней было бы:

AA>
AA>let d = DateTime()
AA>


Возможно, я просто привык, но мне нравится, когда вызов конструктора типа визуально отличается от вызова какого-то метода. Не вижу тут каких-то особых неудобств и вопросом, нужно в конкретном месте писать new или не нужно, никогда не задавался.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.