当在C#中创建List<>
基元类型时(例如List<int>
),列表中的元素是按值存储的,还是通过引用存储?
换句话说,C#List<int>
是等同于C ++ std::vector<int>
还是C ++ std::vector<shared_ptr<int>>
?
答案 0 :(得分:6)
List<int>
内部会有int[]
。通常不需要装箱 - 值直接存储在数组中。当然,如果您选择将List<T>
用作非通用IList
,其中API是根据object
定义的,则将框:< / p>
List<int> list1 = new List<int>();
// No boxing or unboxing here
list1.Add(5);
int x = list1[0];
// Perfectly valid - but best avoided
IList list2 = new List<int>();
// Boxed by the caller, then unboxed internally in the implementation
list2.Add(5);
// Boxed in the implementation, then unboxed by the caller
int y = (int) list2[0];
请注意,“通过引用存储”这一短语令人困惑 - “通过引用”这一术语通常用于参数传递的上下文中,但它有些不同。
因此,虽然List<string>
(例如)包含一个数组,其中每个元素值都是一个引用,但在List<int>
中,每个元素值只是int
。涉及的唯一引用是调用者对List<int>
的引用,以及对数组的内部引用。 (即使元素类型是值类型,数组类型本身也是始终引用类型。)
答案 1 :(得分:0)
值类型按值存储。 (例如,基元和结构)引用类型通过引用存储。 (例如课程)
答案 2 :(得分:0)
如果您编写这样的代码会发生什么:
struct MutableValueType
{
public int ChangableInt32;
}
static class Program
{
static void Main()
{
var li = new List<MutableValueType>();
li.Add(new MutableValueType());
li[0].ChangableInt32 = 42;
}
}
您是否会修改结构的副本,还是会更改List<>
内的副本?编译器会警告你吗?我想尝试一下。