C#中的原始类型的容器是使用值语义还是指针/引用语义?

时间:2012-05-11 17:47:34

标签: c#

当在C#中创建List<>基元类型时(例如List<int>),列表中的元素是按值存储的,还是通过引用存储?

换句话说,C#List<int>是等同于C ++ std::vector<int>还是C ++ std::vector<shared_ptr<int>>

3 个答案:

答案 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<>内的副本?编译器会警告你吗?我想尝试一下。