int []是引用类型还是值类型?


124

我知道一个int是一个值类型,但是什么是值类型数组?参考类型?值类型?我想将数组传递给函数以检查某些内容。我应该只传递数组,因为它将只传递它的引用,还是应该将它作为ref传递?


11
将来,您可以通过创建变量,将变量传递到更改该变量的方法中,并检查该变量在通过该方法运行后的值,来检查是通过引用还是通过值传递某些内容。如果相同,则按值传递,不同,按引用传递。

11
@ darkassassin93:按引用或按值传递与某东西是引用类型还是值类型无关。(值类型可以通过引用传递,引用类型可以通过值传递。)
LukeH,2009年

2
在大多数情况下,如果可以在字段或变量中存储[null],则可以假定它是ref类型。当然,例外是可空类型(Nullable <int>或int?)以及字符串。
Noel Widmer

3
@NoëlWidmer字符串也不例外:它们是引用类型。
亚瑟·卡斯特罗

2
@ArthurCastro同意50%:字符串从类继承,这意味着它们是引用类型。但是,它们的相等性基于标识(值比较)而不是引用,并且它们的传递行为被覆盖以匹配值类型的行为。从定义上讲,它们基本上是引用类型,但按实现方式,其行为更类似于值类型。
Noel Widmer

Answers:


201

数组是使您可以将多个项目视为单个集合的机制。Microsoft®.NET公共语言运行时(CLR)支持一维数组,多维数组和锯齿状数组(数组的数组)。所有数组类型都隐式派生自System.Array,而System.Array本身派生自System.Object。这意味着 所有数组始终 是在托管堆上分配的引用类型,并且您的应用程序的变量包含对数组的引用,而不是数组本身。

https://msdn.microsoft.com/zh-CN/library/bb985948.aspx


54
值类型从System.ValueType继承,而System.ValueType本身从System.Object继承。因此,仅因为Array是从System.Object派生的,并不意味着它是引用类型。使System.Array成为引用类型的原因是它的实例是通过引用复制的。IOW,专注于System.Array是一个类的事实。这就是使其成为引用类型的原因。
P.Brian.Mackey

8
<nitpick>我知道文档看起来似乎暗示从System.Object派生的System.Array使其成为引用类型。尽管从System.Object派生的任何类型可能都不是引用类型,但该规则的唯一例外是System.ValueType,编译器将其区别对待。</ nitpick>
Yannick Motton

上面的链接已断开。这是另一个msdn链接,它显示System.Array的继承层次结构:msdn.microsoft.com/de-de/library/system.array
v=vs.110).aspx

从System.Object派生的任何内容都是引用类型,除非它也从System.ValueType派生。@ P.Brian.Mackey只是因为类型是类并不意味着它是引用类型,因为在幕后,结构只是从System.ValueType派生的类。
David Klempfner '17

31

引用类型与值类型的最简单测试是引用类型可以是null,而值类型则不能。


46
...除了可为空的值类型之外,它们都是可为空的(可以将值设置为null,这意味着该类型为null值,而不是null 引用),并且仍然是值类型。
乔恩·斯基特

1
尝试了解它们是否为值类型时,从未想过这样做!好想法。
09年


6

首先,我想告诉您Array是引用类型。为什么?我在这里解释一个例子。

例:

int val = 0; // this is a value type ok
int[] val1 = new int[20] // this is a reference type because space required to store 20 integer value that make array allocated on the heap.

同样,引用类型可以为null,而值类型不能为null。

值类型存储在堆栈中,引用类型存储在堆中

您可以使用out或ref将数组传递给函数。只有初始化方法不同。

更多..


3

测试以确认它是引用还是值类型:

// we create a simple array of int
var a1 = new int[]{1,2,3};
// copy the array a1 to a2
var a2 = a1;
// modify the first element of a1
a1[0]=2;
// output the first element of a1 and a2
Console.WriteLine("a1:"+a1[0]); // 2
Console.WriteLine("a2:"+a2[0]); // 2
//**************************
// all the two variable point to the same array
// it's reference type!
//**************************

您可以在线对其进行测试:https : //dotnetfiddle.net/UWFP45


2
创建一个数组并尝试将其分配为null会更加容易。如果它是一个值类型编纂会失败..
吞噬极乐世界

被警告。C#8发布后,如果您使用可为空的引用类型功能,它也将失败,因为不可为空的引用类型也不能接受null。
Mark A. Donohoe

2

数组本身是引用类型。该数组的值是由数组数据类型确定的值或引用类型。在您的示例中,数组是引用类型,而值是值类型。

所有一维数组都隐式实现IList<T>,其中<T>是数组的数据类型。您可以使用该接口作为方法参数的数据类型。您也可以使用IEnumerable<T>数据类型。在任何一种情况下(或什至只是使用int[]),都不需要显式地将其作为ref参数传递。


0

//对数组的引用按值传递。这就是混乱的根源:-) ...

        int[] test = { 1, 2, 3, 4 };

        modifContenuSansRef(test);
        Console.WriteLine(test[0]); // OK --> 99 le contenu du tableau est modifié

        modifTailleSansRef(test);
        Console.WriteLine(test.Length); // KO --> 4 La taille n'est pas modifiée

    }

    static void modifContenuSansRef(int[] t)
    {
        t[0] = 99;
    }

    static void modifTailleSansRef(int[] t)
    {
        Array.Resize(ref t, 8);
    }

0

数组总是引用类型,没关系,数组包含int之类的值类型还是字符串之类的引用类型。

int[] integers=new int[10];

整数变量本身仅包含对将驻留在堆中的数组的引用。

还有很多人提到,您可以将值类型与引用类型不同,仅取决于变量可能为null或不为null的事实。我想提一下,在C#中,当前值类型也可以为null

例如

int? integer=null

并不是确定类型是引用还是值仅取决于事实变量可能为null还是不是的好方法。


-2

只是一点见识:

例如,int代表一个整数,int[]代表一个整数数组。

要使用特定尺寸初始化数组,可以使用new关键字,在类型名称后的方括号中给出大小:

//create a new array of 32 ints.
int[] integers = new int[32];

所有数组都是引用类型,并遵循引用语义。因此,在此代码中,即使各个元素都是原始值类型,但integers数组还是引用类型。因此,如果您以后再写:

int[] copy = integers;

这将简单地分配整个变量副本以引用同一数组,而不会创建新数组。

C#的数组语法很灵活,它允许您在不初始化数组的情况下声明数组,以便稍后可以在程序中动态调整数组的大小。使用这种技术,您基本上是在创建一个空引用,然后将该引用指向使用new关键字请求的动态分配的内存位置段:

int[] integers;
integers = new int[32];

谢谢。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.