简体   繁体   中英

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

I know an int is a value type, but what are arrays of value types? 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?

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). All array types are implicitly derived from System.Array, which itself is derived from 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

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

Arrays (even of value types like int) are reference types in C#.

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

In C#, arrays are actually objects. System.Array is the abstract base type of all array types.

First I want to tell you that Array is a reference type. 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. 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

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. You can use that interface as the data type of your method parameter instead. You could also use IEnumerable<T> for the data type. In either case (or even if you just use int[] ) you shouldn't need to explicitly pass it as a ref parameter.

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. 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 ):

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

A stackalloc expression allocates a block of memory on the stack. 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. 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:

    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.

Additionally, here is an answer that discusses the practical usage of stackalloc : Practical use of `stackalloc` keyword

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

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.

To initialize the array with specific dimensions, you can use the new keyword, giving the size in the square brackets after the type name:

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

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

Thank You.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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