Добавление примитива struct
(например, int
) к List
:
int i=10;
List<int> list=new List<int>();
list.Add(i);
Против:
Добавление непримитивного struct
(например, KeyValuePair<int,int>
) в список:
List<KeyValuePair<int, int>> list = new List<KeyValuePair<int, int>>();
list.Add(new KeyValuePair<int,int>(10,20));
При добавлении int
struct
к list
нам не нужно использовать ключевое слово new
. Но при добавлении KeyValuePair
struct
в список нам нужно использовать ключевое слово new
.
Я имею в виду, что следующее утверждение неверно:
list.Add(new int(10)); //invalid statement
Хотя и int
, и KeyValuePair
являются структурами, они ведут себя по-разному — не требуется создание экземпляра перед использованием (с точки зрения пользователя). А другой требует создания экземпляра перед использованием.
Почему мы не можем сделать следующее вместо этого:
list.Add(KeyValuePair<int,int>(10,20)) //omit the new keyword, as we were doing with an int
Исходя из опыта работы с C/C++, что именно делает ключевое слово new
в C#?
Он просто создает экземпляр базового типа данных (и мы не уверены, будет ли экземпляр типа данных лежать в стеке или в куче). Или мы уверены, что использование нового ключевого слова выделит память в куче (как это делается в C++)?
«При добавлении структуры int в список нам не нужно использовать новое ключевое слово. Но при добавлении структуры KeyValuePair в список нам нужно использовать новое ключевое слово» — это совершенно неверно. В принципе, ваш вопрос сломан. Примеры, которые вы называете чем-то принципиально отличным, на самом деле ничем не отличаются. Это правда, что у System.Int32
нет конструктора с параметром. Но вы, конечно, можете написать new int()
. ...
... Более того, вы также можете назвать переменную i
, объявив ее как KeyValuePair<int, int>
, а затем добавить в список, используя точно такой же синтаксис, как в первом примере, то есть list.Add(i);
. Разницы нет, поэтому спрашивать, почему есть разница, не имеет никакого смысла.
Для получения дополнительной информации, помимо очевидного чтения документации по языку, вы также можете просмотреть вопросы о переполнениях стека stackoverflow.com/questions/9207488/… и stackoverflow.com/questions/11504910/…
И, что бы это ни стоило, когда тип имеет буквальное представление, вы можете думать о литерале как о «константной» версии new T (LiteralOfT)
. Такое выражение, как int i = 10;
, очень близко к int i = new int(10)
. Ключевое слово new
выделяет память из управляемой кучи, а затем запускает конструктор для ссылочных типов, как в C++. Ключевое слово new
для типов значений просто запускает конструктор и не выделяет память. Затем результат построенного объекта копируется в переменную.
Вопрос интересный, даже если плохо написан. Почему вы можете инициализировать определенные типы (int
, string
, ...) без использования ключевых слов new
(или default()
)? А ответ сводится к существованию литералов (и константных выражений (можно int x = (int)5.5
))
что именно делает новое ключевое слово в С#?
Все это здесь. Наиболее актуальным для этого вопроса является «вызов конструктора». Структуры и классы имеют конструкторы, а конструкторы создают экземпляры структур и классов.
Когда вы делаете:
new KeyValuePair<int,int>(10,20)
вы вызываете этот конструктор.
int
, который является псевдонимом для структуры Int32, не имеет конструктора, который принимает параметр типа int
. Вот почему вы не можете сделать:
new int(10)
Обратите внимание, что вызов конструктора — не единственный способ создать экземпляр структуры. Вы также можете сделать что-то вроде:
var defaultKVP = default(KeyValuePair<int, int>); // gets the default value of the type KeyValuePair<int, int>
// defaultKVP is an instance of KeyValuePair<int, int>! It's not null! Structs can't be null :)
Значение по умолчанию структуры определяется путем установки для всех ее полей с типом значения значения по умолчанию, а для полей ссылочного типа — значение null.
Причина, по которой целочисленный литерал вроде 10
является экземпляром структуры Int32
, кроется в магии компилятора. Спецификация так говорит, поэтому так и реализовано.
Прочитайте мой ответ на этот вопрос stackoverflow.com/questions/65418824/…. Это не дает прямого ответа на ваш вопрос, но должно сделать ответ очевидным