简体   繁体   English

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

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

I know an int is a value type, but what are arrays of value types?我知道 int 是一种值类型,但什么是值类型数组? Reference types?引用类型? Value types?值类型? I want to pass an array to a function to check something.我想将数组传递给函数以检查某些内容。 Should I just pass the array, as it will just pass the reference of it, or should I pass it as ref?我应该只传递数组,因为它只会传递它的引用,还是应该将它作为 ref 传递?

Arrays are mechanisms that allow you to treat several items as a single collection.数组是允许您将多个项目视为单个集合的机制。 The Microsoft® .NET Common Language Runtime (CLR) supports single-dimensional arrays, multidimensional arrays, and jagged arrays (arrays of arrays). Microsoft® .NE​​T 公共语言运行时 (CLR) 支持一维数组、多维数组和交错数组(数组的数组)。 All array types are implicitly derived from System.Array, which itself is derived from System.Object.所有数组类型都是从 System.Array 隐式派生的,而 System.Array 本身又是从 System.Object 派生的。 This means that all arrays are always reference types which are allocated on the managed heap, and your app's variable contains a reference to the array and not the array itself.这意味着所有数组始终是在托管堆上分配的引用类型,并且您的应用程序的变量包含对数组的引用而不是数组本身。

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

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

Arrays (even of value types like int) are reference types in C#.数组(甚至像 int 这样的值类型)是 C# 中的引用类型。

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

In C#, arrays are actually objects.在 C# 中,数组实际上是对象。 System.Array is the abstract base type of all array types. System.Array 是所有数组类型的抽象基类型。

First I want to tell you that Array is a reference type.首先我想告诉你 Array 是一个引用类型。 Why?为什么? I explain throw one example over here.我在这里解释抛出一个例子。

Example:例子:

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.

Also reference types can be null whereas value types can't.引用类型也可以为空,而值类型不能。

value type stored in Stack and reference type stored in Heap堆栈中存储的值类型和堆中存储的引用类型

You can pass array to function using out or ref.您可以使用 out 或 ref 将数组传递给函数。 Only initialize methods are different.只有初始化方法不同。

more..更多的..

Test to verify if it's a reference or value type:测试以验证它是引用类型还是值类型:

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

You can test it online: https://dotnetfiddle.net/UWFP45你可以在线测试: https : //dotnetfiddle.net/UWFP45

The array itself is a reference type.数组本身是一种引用类型。 The values of that array are value or reference types as determined by the array data type.该数组的值是由数组数据类型确定的值或引用类型。 In your example, the array is a reference type and the values are value types.在您的示例中,数组是引用类型,值是值类型。

All single-dimension arrays implicitly implement IList<T> , where <T> is the data type of the array.所有单维数组都隐式实现IList<T> ,其中<T>是数组的数据类型。 You can use that interface as the data type of your method parameter instead.您可以使用该接口作为方法参数的数据类型。 You could also use IEnumerable<T> for the data type.您还可以使用IEnumerable<T>作为数据类型。 In either case (or even if you just use int[] ) you shouldn't need to explicitly pass it as a ref parameter.在任何一种情况下(或者即使您只使用int[] ),您都不需要将其作为ref参数显式传递。

I would like to add to the other answers that though int[] is a reference type, with the introduction of stackalloc in C# you can allocate an array in stack as a value type.我想补充其他答案,尽管 int[] 是引用类型,但随着 C# 中stackalloc的引入,您可以将堆栈中的数组分配为值类型。 This may give you performance gain since placing array to stack reduces GC pressure (by the way, talking about value types in general you may often hear that value type is allocated in stack; it is not always true: https://docs.microsoft.com/en-us/archive/blogs/ericlippert/the-truth-about-value-types ):这可能会给您带来性能提升,因为将数组放置到堆栈会减少 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 https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc

A stackalloc expression allocates a block of memory on the stack. stackalloc 表达式在堆栈上分配一块内存。 A stack allocated memory block created during the method execution is automatically discarded when that method returns.在方法执行期间创建的堆栈分配内存块在该方法返回时自动丢弃。 You cannot explicitly free the memory allocated with stackalloc.您不能显式释放用 stackalloc 分配的内存。 A stack allocated memory block is not subject to garbage collection and doesn't have to be pinned with a fixed statement.堆栈分配的内存块不受垃圾回收的影响,也不必用固定语句固定。

An example of stackalloc usage: 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);

Using this technique don't forget about the limited stack memory.使用这种技术不要忘记有限的堆栈内存。 The link https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc provides the necessary information on how to use stackalloc safely considering this limitation.链接https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc提供了有关如何考虑此限制安全使用stackalloc的必要信息。

Additionally, here is an answer that discusses the practical usage of stackalloc : Practical use of `stackalloc` keyword此外,这里有一个讨论stackalloc实际用法的stackallocPractical use of `stackalloc` 关键字

//The reference to the array is passed by value. //对数组的引用是按值传递的。 This is the source of the confusion :-) ...这是混乱的根源:-) ...

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

Arrays always are reference types.it does not matter array would contain value type like int or reference type like string.When you declare array for example数组总是引用类型。数组是否包含像 int 这样的值类型或像 string 这样的引用类型并不重要。例如,当你声明数组时

int[] integers=new int[10] ; int[] integers=new int[10] ;

integers variable itself contains only reference to the array which will reside in heap.整数变量本身只包含对将驻留在堆中的数组的引用。

Also there is many people mention that you could differ value type from reference type just depend on the fact thhat variable could be null or not.还有很多人提到你可以将值类型与引用类型不同,这取决于变量是否为空这一事实。 I would like to mention that in the c# currently value types also can be null我想提一下,在 c# 中当前值类型也可以为 null

for instance例如

int? integer=null

and it is not good way to identify the type is reference or value only depends on the fact variable could be null or not.并且这不是确定类型是引用还是值的好方法,这仅取决于变量是否为空的事实。

Just a bit of an insight:只是一点见解:

For example, int represents a single integer, int[] represents an array of integers.例如, int表示单个整数, int[]表示整数数组。

To initialize the array with specific dimensions, you can use the new keyword, giving the size in the square brackets after the type name:要初始化具有特定维度的数组,您可以使用new关键字,在类型名称后的方括号中给出大小:

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

All arrays are reference types and follow reference semantics.所有数组都是引用类型并遵循引用语义。 Hence, in this code, even though the individual elements are primitive value types, the integers array is a reference type.因此,在此代码中,即使单个元素是原始值类型, integers数组也是引用类型。 So if you later write:所以如果你以后写:

int[] copy = integers;

this will simply assign the whole variable copy to refer to the same array, it won't create a new array.这将简单地将整个变量副本分配给同一个数组,它不会创建一个新数组。

C#'s array syntax is flexible, it allows you to declare arrays without initializing them so that the array can be dynamically sized later in the program. C# 的数组语法很灵活,它允许您声明数组而无需初始化它们,以便稍后可以在程序中动态调整数组大小。 With this technique, you are basically creating a null reference and later pointing that reference at a dynamically allocated stretch of memory locations requested with a new keyword:使用这种技术,您基本上是在创建一个空引用,然后将该引用指向使用new关键字请求的动态分配的内存位置:

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

Thank You.谢谢。

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

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