繁体   English   中英

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

[英]Is int[] a reference type or a value type?

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

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

https://msdn.microsoft.com/en-us/library/bb985948.aspx

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

数组(甚至像 int 这样的值类型)是 C# 中的引用类型。

http://msdn.microsoft.com/en-us/library/aa288453(VS.71).aspx

在 C# 中,数组实际上是对象。 System.Array 是所有数组类型的抽象基类型。

首先我想告诉你 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.

引用类型也可以为空,而值类型不能。

堆栈中存储的值类型和堆中存储的引用类型

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

更多的..

测试以验证它是引用类型还是值类型:

// 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

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

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

我想补充其他答案,尽管 int[] 是引用类型,但随着 C# 中stackalloc的引入,您可以将堆栈中的数组分配为值类型。 这可能会给您带来性能提升,因为将数组放置到堆栈会减少 GC 压力(顺便说一下,一般谈论值类型时,您可能经常听到值类型是在堆栈中分配的;但并非总是如此: https : //docs.microsoft .com/en-us/archive/blogs/ericlippert/the-truth-about-value-types ):

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc

stackalloc 表达式在堆栈上分配一块内存。 在方法执行期间创建的堆栈分配内存块在该方法返回时自动丢弃。 您不能显式释放用 stackalloc 分配的内存。 堆栈分配的内存块不受垃圾回收的影响,也不必用固定语句固定。

stackalloc用法的一个例子:

    Span<int> numbers = stackalloc int[10];
    for (int ctr = 0; ctr < numbers.Length; ctr++)
        numbers[ctr] = ctr + 1;
    foreach (int i in numbers)
        Console.WriteLine(i);

使用这种技术不要忘记有限的堆栈内存。 链接https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc提供了有关如何考虑此限制安全使用stackalloc的必要信息。

此外,这里有一个讨论stackalloc实际用法的stackallocPractical use of `stackalloc` 关键字

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

        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);
    }

数组总是引用类型。数组是否包含像 int 这样的值类型或像 string 这样的引用类型并不重要。例如,当你声明数组时

int[] integers=new int[10] ;

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

还有很多人提到你可以将值类型与引用类型不同,这取决于变量是否为空这一事实。 我想提一下,在 c# 中当前值类型也可以为 null

例如

int? integer=null

并且这不是确定类型是引用还是值的好方法,这仅取决于变量是否为空的事实。

只是一点见解:

例如, 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];

谢谢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM