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[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]: Когда 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: Когда 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[4]: Ну спасибо за развёрнутый ответ..
От: Sharov Россия  
Дата: 15.10.19 23:57
Оценка: +1
Здравствуйте, Danchik, Вы писали:

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


Похоже, это первый язык.
Кодом людям нужно помогать!
Re[5]: Ну спасибо за развёрнутый ответ..
От: alexzzzz  
Дата: 16.10.19 12:30
Оценка: +1
Здравствуйте, varenikAA, Вы писали:

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

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


Возможно, я просто привык, но мне нравится, когда вызов конструктора типа визуально отличается от вызова какого-то метода. Не вижу тут каких-то особых неудобств и вопросом, нужно в конкретном месте писать new или не нужно, никогда не задавался.
Re[7]: Когда new, a koгда можно без?
От: IT Россия linq2db.com
Дата: 17.10.19 12:32
Оценка: -1
Здравствуйте, Mihas, Вы писали:

M>Так что:

M>
int a=new int();
M>a=1;


Так тоже сойдёт. Главное — не забивать себе голову ненужными деталями.
Если нам не помогут, то мы тоже никого не пощадим.
Re[11]: Ну спасибо за развёрнутый ответ..
От: alexzzzz  
Дата: 22.10.19 11:56
Оценка: +1
Здравствуйте, varenikAA, Вы писали:

A>>Передать в Proc1 можно не что угодно, а только то, что Proc1/WriteLine смогут переварить без ошибок компиляции или ошибок в рантайме. Что конкретно они могут переваривать, из объявления Proc1 не видно.

AA>Это просто, если вывод типа не справился или если передается невалидный аргумент, то компилятор выдаст подробную ошибку. В первом случае можно будет явно указать ожидаемый тип (уточнение). Но это требуется очень редко.

Игра в угадайку получается. Хорошо, когда ты функцию написал сам недавно и знаешь, что она хочет и что может. А когда берёшь чужой API, то сидишь и смотришь на него, как баран на ворота, потому что кто-то поленился типы прописать. Впрочем, питоновский синтаксис даже с типами не фонтан.
Re[12]: Ну спасибо за развёрнутый ответ..
От: varenikAA  
Дата: 23.10.19 02:28
Оценка: -1
Здравствуйте, alexzzzz, Вы писали:

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


A>>>Передать в Proc1 можно не что угодно, а только то, что Proc1/WriteLine смогут переварить без ошибок компиляции или ошибок в рантайме. Что конкретно они могут переваривать, из объявления Proc1 не видно.

AA>>Это просто, если вывод типа не справился или если передается невалидный аргумент, то компилятор выдаст подробную ошибку. В первом случае можно будет явно указать ожидаемый тип (уточнение). Но это требуется очень редко.

A>Игра в угадайку получается. Хорошо, когда ты функцию написал сам недавно и знаешь, что она хочет и что может. А когда берёшь чужой API, то сидишь и смотришь на него, как баран на ворота, потому что кто-то поленился типы прописать. Впрочем, питоновский синтаксис даже с типами не фонтан.


Если использовать ide, то типы в подсказках будут.
Если нет — подскажет компилятор(если это хороший компилятор). Вы же не пишите программу на листочке бумаге?
Ну и не знаю, вы на чем кодите? В C# обобщенное программирование и утиная типизация повсюду.

Вспоминаю старый слоган: "настоящий хакер кодит в notepad".
☭ ✊ В мире нет ничего, кроме движущейся материи.
Когда 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[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[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[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[6]: Ну спасибо за развёрнутый ответ..
От: varenikAA  
Дата: 17.10.19 06:51
Оценка:
Здравствуйте, Jack128, Вы писали:

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


J>В С++ new использует не для создания объекта, а для выделения динамической памяти. А так как сборщиков мусора там нема, то и отдельные ключ слова для выделения/освобождения памяти там очень кстати были.

J>А во всякие шарпы потащили new — чтоб было похоже на плюсы.

Да, создание любого объекта начинается с выделения памяти(не только в си), но так как в управляемом коде все это делает виртуальная машина,
конечно, было бы логично использовать new только в unsafe-коде.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[6]: Ну спасибо за развёрнутый ответ..
От: varenikAA  
Дата: 17.10.19 06:55
Оценка:
Здравствуйте, Sharov, Вы писали:

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


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


newPerson — функция. new Person — по смыслу тоже самое, но синтаксически отличается. Даже затрудняюсь сказать, new это оператор, выражение или инструкция...

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


S>А почему не различать создание объекта здесь и сейчас и делегацию создания -- builder, fabric?

В управляемом коде это совершенно излишне. Даже с++ рекомендуют использовать библиотеки по управлению памятью(временем жизни объектов).
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[6]: Ну спасибо за развёрнутый ответ..
От: varenikAA  
Дата: 17.10.19 07:08
Оценка:
Здравствуйте, alexzzzz, Вы писали:

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


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

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


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


Для сравнения:

            void Proc1(Func<DateTime> r)
            {
                WriteLine(r());
            };

            Proc1(() => new DateTime());
            _ = ReadLine();
            return;

— близко, но не так хорошо как:

        def Proc1(a) {
            WriteLine(a());
        };
        
        Proc1(DateTime);
 
        _ = ReadLine();


Такое решение также позволяет использовать конструктор там, где требуется функция (или делегат).

И да, в C кажется нет new.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[6]: Когда new, a koгда можно без?
От: Mihas  
Дата: 17.10.19 07:25
Оценка:
Здравствуйте, IT, Вы писали:

IT>
int a=new int(1);

Вот, и у меня в голове такая же формула сидела. Сунулся проверить — хвать, а нет у Инта конструкторов с параметрами (.Net 4.0, старее не установлены).
Так что:
int a=new int();
a=1;
Re[7]: Ну спасибо за развёрнутый ответ..
От: alexzzzz  
Дата: 21.10.19 00:37
Оценка:
Здравствуйте, varenikAA, Вы писали:

AA>- близко, но не так хорошо как:

AA> def Proc1(a) {
AA> WriteLine(a());
AA> };
AA> Proc1(DateTime);
AA> _ = ReadLine();

Не люблю питоноподобный синтаксис. Функция неизвестно что принимает и неизвестно что возвращает, если вообще возвращает. Вместо полезных типов имеем ключевое слова def, которое по сути бесполезно.

Вызов выглядит так, будто мы передаём в функцию Proc1 переменную или константу DateTime.
Отредактировано 21.10.2019 0:38 alexzzzz . Предыдущая версия .
Re[8]: Ну спасибо за развёрнутый ответ..
От: varenikAA  
Дата: 21.10.19 14:16
Оценка:
Здравствуйте, alexzzzz, Вы писали:

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


AA>>- близко, но не так хорошо как:

AA>> def Proc1(a) {
AA>> WriteLine(a());
AA>> };
AA>> Proc1(DateTime);
AA>> _ = ReadLine();

A>Не люблю питоноподобный синтаксис. Функция неизвестно что принимает и неизвестно что возвращает, если вообще возвращает. Вместо полезных типов имеем ключевое слова def, которое по сути бесполезно.


A>Вызов выглядит так, будто мы передаём в функцию Proc1 переменную или константу DateTime.

В том-то и дело, что передать можно все что угодно: от выражения до константы т.к. функции в ФП обощенные по умолчанию и специализируются
в момент использования.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[9]: Ну спасибо за развёрнутый ответ..
От: alexzzzz  
Дата: 21.10.19 14:46
Оценка:
Здравствуйте, varenikAA, Вы писали:

AA>>>- близко, но не так хорошо как:

AA>>> def Proc1(a) {
AA>>> WriteLine(a());
AA>>> };
AA>>> Proc1(DateTime);
AA>>> _ = ReadLine();

A>>Не люблю питоноподобный синтаксис. Функция неизвестно что принимает и неизвестно что возвращает, если вообще возвращает. Вместо полезных типов имеем ключевое слова def, которое по сути бесполезно.


A>>Вызов выглядит так, будто мы передаём в функцию Proc1 переменную или константу DateTime.

AA>В том-то и дело, что передать можно все что угодно: от выражения до константы т.к. функции в ФП обощенные по умолчанию и специализируются
AA>в момент использования.

Передать в Proc1 можно не что угодно, а только то, что Proc1/WriteLine смогут переварить без ошибок компиляции или ошибок в рантайме. Что конкретно они могут переваривать, из объявления Proc1 не видно.
Re[10]: Ну спасибо за развёрнутый ответ..
От: varenikAA  
Дата: 22.10.19 08:13
Оценка:
Здравствуйте, alexzzzz, Вы писали:

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


AA>>>>- близко, но не так хорошо как:

AA>>>> def Proc1(a) {
AA>>>> WriteLine(a());
AA>>>> };
AA>>>> Proc1(DateTime);
AA>>>> _ = ReadLine();

A>>>Не люблю питоноподобный синтаксис. Функция неизвестно что принимает и неизвестно что возвращает, если вообще возвращает. Вместо полезных типов имеем ключевое слова def, которое по сути бесполезно.


A>>>Вызов выглядит так, будто мы передаём в функцию Proc1 переменную или константу DateTime.

AA>>В том-то и дело, что передать можно все что угодно: от выражения до константы т.к. функции в ФП обощенные по умолчанию и специализируются
AA>>в момент использования.

A>Передать в Proc1 можно не что угодно, а только то, что Proc1/WriteLine смогут переварить без ошибок компиляции или ошибок в рантайме. Что конкретно они могут переваривать, из объявления Proc1 не видно.

Это просто, если вывод типа не справился или если передается невалидный аргумент, то компилятор выдаст подробную ошибку. В первом случае можно будет явно указать ожидаемый тип (уточнение). Но это требуется очень редко.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[13]: Ну спасибо за развёрнутый ответ..
От: alexzzzz  
Дата: 23.10.19 12:52
Оценка:
Здравствуйте, varenikAA, Вы писали:

AA>Если использовать ide, то типы в подсказках будут.

AA>Если нет — подскажет компилятор(если это хороший компилятор). Вы же не пишите программу на листочке бумаге?
AA>Ну и не знаю, вы на чем кодите? В C# обобщенное программирование и утиная типизация повсюду.

В C# если метод принимает T, значит он принимает любые T, чем бы они ни были. Если на T есть ограничения, то они явно заданы в виде type constraints.

int Foo<T>(T item) where T : struct, IComparable<T>

Метод принимает только те T, которые value-типы и реализуют интерфейс IComparable<T>. С такими T он работать точно умеет. Что-то другое в него хрен запихнёшь.
Re[14]: Ну спасибо за развёрнутый ответ..
От: varenikAA  
Дата: 24.10.19 01:19
Оценка:
Здравствуйте, alexzzzz, Вы писали:

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


AA>>Если использовать ide, то типы в подсказках будут.

AA>>Если нет — подскажет компилятор(если это хороший компилятор). Вы же не пишите программу на листочке бумаге?
AA>>Ну и не знаю, вы на чем кодите? В C# обобщенное программирование и утиная типизация повсюду.

A>В C# если метод принимает T, значит он принимает любые T, чем бы они ни были. Если на T есть ограничения, то они явно заданы в виде type constraints.


A>
int Foo<T>(T item) where T : struct, IComparable<T>

A>Метод принимает только те T, которые value-типы и реализуют интерфейс IComparable<T>. С такими T он работать точно умеет. Что-то другое в него хрен запихнёшь.

И что? Вы описали интерфейс. Языки с выводом типов автоматически сгенерят нужную версию функции, в отличии от C# 2-й версии, где надо было писать int x = Foo<Person>(null);
В последних можно так: var x = Foo((Person)null);
Вы до сих пор указываете параметр обобщенных методов?
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[15]: Ну спасибо за развёрнутый ответ..
От: alexzzzz  
Дата: 24.10.19 14:11
Оценка:
Здравствуйте, varenikAA, Вы писали:

A>>
int Foo<T>(T item) where T : struct, IComparable<T>

A>>Метод принимает только те T, которые value-типы и реализуют интерфейс IComparable<T>. С такими T он работать точно умеет. Что-то другое в него хрен запихнёшь.
AA>И что? Вы описали интерфейс.

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

AA>в отличии от C# 2-й версии, где надо было писать int x = Foo<Person>(null);

AA>В последних можно так: var x = Foo((Person)null);

Не понял. В режиме C# 2.0 компилятор принимает оба варианта. Они равнозначны по смыслу и результату. У литералов null и default нет типа. Если вывести его неоткуда, надо указать вручную. Иначе какая из перегрузок WriteLine должна быть вызвана и что должен вернуть подобный метод, если передать в него null без типа:
T Recreate<T>(T x) where T : new() // любые типы с конструктором без параметров
{
    Console.WriteLine(x);
    return new T();
}
?
Отредактировано 24.10.2019 14:13 alexzzzz . Предыдущая версия .
Re[16]: Ну спасибо за развёрнутый ответ..
От: varenikAA  
Дата: 25.10.19 08:07
Оценка:
Здравствуйте, alexzzzz, Вы писали:

A>Не понял. В режиме C# 2.0 компилятор принимает оба варианта. Они равнозначны по смыслу и результату. У литералов null и default ]?


Я не совсем об этом.
Вот например, вы пишете метод:
bool Test<T>(T a, T b)
{
    return a>b;
}
WriteLine(Test(1,2));

Что получится?
Или в d:
bool Test(T)(T a, T b)
{
  return a>b;
}
writeln(Test(1,2));
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[17]: Ну спасибо за развёрнутый ответ..
От: alexzzzz  
Дата: 28.10.19 12:26
Оценка:
Здравствуйте, varenikAA, Вы писали:

A>>Не понял. В режиме C# 2.0 компилятор принимает оба варианта. Они равнозначны по смыслу и результату. У литералов null и default ]?

AA>Я не совсем об этом.
AA>Вот например, вы пишете метод:
AA>
AA>bool Test<T>(T a, T b)
AA>{
AA>    return a>b;
AA>}

AA>Что получится?

Ничего не получится. C# не даст написать код, принимающий любые T, который не валиден для любых T.
Отредактировано 28.10.2019 12:30 alexzzzz . Предыдущая версия .
Re[18]: Ну спасибо за развёрнутый ответ..
От: varenikAA  
Дата: 29.10.19 05:16
Оценка:
Здравствуйте, alexzzzz, Вы писали:

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


A>>>Не понял. В режиме C# 2.0 компилятор принимает оба варианта. Они равнозначны по смыслу и результату. У литералов null и default ]?

AA>>Я не совсем об этом.
AA>>Вот например, вы пишете метод:
AA>>
AA>>bool Test<T>(T a, T b)
AA>>{
AA>>    return a>b;
AA>>}

AA>>Что получится?

A>Ничего не получится. C# не даст написать код, принимающий любые T, который не валиден для любых T.


вот я и спрашиваю:
var x  = Test(1,2);
— это валидное выражение?
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[19]: Ну спасибо за развёрнутый ответ..
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.10.19 06:36
Оценка:
Здравствуйте, varenikAA, Вы писали:
A>>Ничего не получится. C# не даст написать код, принимающий любые T, который не валиден для любых T.

AA>вот я и спрашиваю:
var x  = Test(1,2);
— это валидное выражение?

Это выражение валидно, но до его компиляции дело не дойдёт.
Компиляция упадёт ещё на bool Test<T>(T a, T b) => a>b;, т.к. компилятору неизвестно, есть ли для T operator>().
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[20]: Ну спасибо за развёрнутый ответ..
От: varenikAA  
Дата: 29.10.19 08:02
Оценка:
Здравствуйте, Sinclair, Вы писали:

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

A>>>Ничего не получится. C# не даст написать код, принимающий любые T, который не валиден для любых T.

AA>>вот я и спрашиваю:
var x  = Test(1,2);
— это валидное выражение?

S>Это выражение валидно, но до его компиляции дело не дойдёт.
S>Компиляция упадёт ещё на bool Test<T>(T a, T b) => a>b;, т.к. компилятору неизвестно, есть ли для T operator>().

Согласен, но в случае если в контексте вызова только int комплятор вполне мог бы сообразить.
Забавно, что и Nemerle не справился с выводом типов, если подряд вызвать сначала с числами, а затем со строками.
Еще забавней выглядит Ди:
bool Test(T)(T a, T b) 
{
    return a > b;
}
void main()
{
    import std.stdio ;
    auto r1 = Test(10,20);
    auto r2 = Test("10","20");
    writeln(r1, r2);
}


Ну, а хитрее всех F#
let f a b = a > b //=> val f : a:'a -> b:'a -> bool when 'a : comparison
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[21]: Ну спасибо за развёрнутый ответ..
От: alexzzzz  
Дата: 29.10.19 09:37
Оценка:
Здравствуйте, varenikAA, Вы писали:

S>>Компиляция упадёт ещё на bool Test<T>(T a, T b) => a>b;, т.к. компилятору неизвестно, есть ли для T operator>().

AA>Согласен, но в случае если в контексте вызова только int комплятор вполне мог бы сообразить.

Во время компиляции Test<T> у компилятора нет этого контекста. Он не знает, с какими аргументами Test будет вызываться. Объявление Test<T> может находиться в одной сборке, а десяток его вызовов с десятком разных типов аргументов ― в десятке других сборок (возможно, даже пока не существующих).
Re[21]: Ну спасибо за развёрнутый ответ..
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.10.19 10:01
Оценка:
Здравствуйте, varenikAA, Вы писали:
AA>Согласен, но в случае если в контексте вызова только int комплятор вполне мог бы сообразить.
Не мог бы. Код Test и код Main могут быть в разных сборках. К моменту вызова в main компилятор уже отработал, и соображать некому. Статический код проходит верификацию при загрузке; рантайму запрещено поднимать в память код, который может вызвать ошибку типизации.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.