为什么将原始结构添加到 List 不需要 new 关键字而将非原始结构添加到 List 需要 new 关键字? - C#

问题描述

将原始 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

虽然 intkeyvaluePair 都是结构体,但它们的行为有所不同 - 使用前不需要实例化(就用户而言)。另一个需要在使用前实例化。

为什么我们不能改为执行以下操作:

list.Add(keyvaluePair<int,20)) //omit the new keyword,as we were doing with an int

来自 C/C++ 背景,new 关键字在 C# 中究竟有什么作用? 它是否只是实例化底层数据类型(我们不确定实例化的数据类型是在堆栈上还是在堆上)。或者,我们确定使用 new 关键字会在堆上分配内存(就像在 C++ 中那样)?

解决方法

new 关键字在 C# 中有什么作用?

已全部列出 here。与这个问题最相关的是“构造函数调用”。结构和类都有构造函数,构造函数创建结构和类的实例。

当你这样做时:

new KeyValuePair<int,int>(10,20)

您正在呼叫 this constructor

intInt32 结构的别名,没有接受 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 :)

结构体的 default value 是通过将其所有值类型字段设置为其默认值,并将引用类型字段设置为 null 来定义的。

10 这样的整数文字是结构体 Int32 的一个实例的原因,是编译器的魔法。规范是这么说的,所以它是这样实现的。