¿Es int [] un tipo de referencia o un tipo de valor?

124

Sé que un int es un tipo de valor, pero ¿qué son las matrices de tipos de valor? Tipos de referencia Tipos de valor? Quiero pasar una matriz a una función para verificar algo. ¿Debo pasar la matriz, ya que solo pasará la referencia de ella, o debería pasarla como referencia?

elysium devorado
fuente
11
En el futuro, puede verificar si se pasa algo por referencia o por valor creando una variable, pasando esa variable a un método que cambie esa variable y verificando cuál es el valor de esa variable después de que se ejecuta a través del método. Si es igual, se pasa por valor, diferente, se pasa por referencia.
11
@ darkassassin93: Pasar por referencia o por valor no está relacionado con si algo es un tipo de referencia o un tipo de valor. (Los tipos de valor se pueden pasar por referencia y los tipos de referencia se pueden pasar por valor.)
LukeH
2
En la mayoría de los casos, si puede almacenar [nulo] dentro de un campo o variable, puede suponer que es un tipo de referencia. Las excepciones ciertamente son tipos anulables (Nullable <int> o int?) Así como cadenas.
Noel Widmer
3
@ NoëlWidmer Las cadenas no son una excepción: son tipos de referencia.
Arthur Castro
2
@ArthurCastro Argree al 50%: las cadenas heredan de la clase, lo que significa que son tipos de referencia. Sin embargo, su igualdad se basa en la identidad (comparación de valores) en lugar de la referencia y su comportamiento de aprobación se anula para que coincida con el comportamiento de los tipos de valor. Básicamente son tipos de referencia por definición, pero se comportan más como tipos de valor por implementación.
Noel Widmer

Respuestas:

201

Las matrices son mecanismos que le permiten tratar varios elementos como una sola colección. Microsoft® .NET Common Language Runtime (CLR) admite matrices unidimensionales, matrices multidimensionales y matrices irregulares (matrices de matrices). Todos los tipos de matriz se derivan implícitamente de System.Array, que se deriva de System.Object. Esto significa que todas las matrices son siempre tipos de referencia que se asignan en el montón administrado, y la variable de su aplicación contiene una referencia a la matriz y no a la matriz misma.

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

Yannick Motton
fuente
54
Los tipos de valor heredan de System.ValueType, que hereda de System.Object. Entonces, solo porque Array deriva de System.Object no significa que sea un tipo de referencia. Lo que hace que System.Array sea un tipo de referencia es que sus instancias se copian por referencia. IOW, concéntrate en el hecho de que System.Array es una clase. Eso es lo que lo convierte en un tipo de referencia.
P.Brian.Mackey
8
<nitpick> Sé que puede parecer que la documentación implica que System.Array derivado de System.Object lo convierte en un tipo de referencia. Aunque puede no ser cierto que cualquier tipo que se derive de System.Object sea un tipo de referencia, la única excepción a esta regla es System.ValueType, que el compilador trata de manera diferente. </nitpick>
Yannick Motton
El enlace de arriba está roto. Aquí hay otro enlace msdn que muestra la jerarquía de herencia de System.Array: msdn.microsoft.com/de-de/library/system.array(v=vs.110).aspx
MUG4N
Todo lo que se deriva de System.Object es un tipo de referencia, A MENOS que también se derive de System.ValueType. @ P.Brian.Mackey solo porque un tipo es una clase no significa que sea un tipo de referencia, porque detrás de escena, las estructuras son solo clases que derivan de System.ValueType.
David Klempfner el
31

La prueba más simple para el tipo de referencia frente al tipo de valor es que los tipos de referencia pueden ser null, pero los tipos de valores no.

Alex Reitbort
fuente
46
... excepto para los tipos de valores anulables, que son anulables (puede establecer el valor en nulo, lo que significa el valor nulo para el tipo en lugar de una referencia nula ) y todavía son tipos de valor.
Jon Skeet el
1
¡Nunca pensé en hacer eso al intentar entender si son tipos de valor o no! Gran idea.
devorado elysium
6

Primero quiero decirte que Array es un tipo de referencia. ¿Por qué? Les explico lanzar un ejemplo por aquí.

Ejemplo:

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.

También los tipos de referencia pueden ser nulos, mientras que los tipos de valores no pueden.

tipo de valor almacenado en la pila y tipo de referencia almacenado en el montón

Puede pasar la matriz a la función usando o ref. Solo los métodos de inicialización son diferentes.

más..

Devendra Gohel
fuente
3

Pruebe para verificar si es una referencia o un tipo de valor:

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

Puede probarlo en línea: https://dotnetfiddle.net/UWFP45

Marco Staffoli
fuente
2
Hubiera sido más fácil crear una matriz e intentar asignarla a nulo. La compilación fallaría si fuera un tipo de valor ...
Devorado elysium
Se prevenido. Una vez que se libera C # 8, también fallará si está utilizando la función de tipos de referencia anulables ya que los tipos de referencia no anulables tampoco pueden aceptar nulo.
Mark A. Donohoe
2

La matriz en sí es un tipo de referencia. Los valores de esa matriz son valores o tipos de referencia determinados por el tipo de datos de la matriz. En su ejemplo, la matriz es un tipo de referencia y los valores son tipos de valores.

Todos los arreglos unidimensionales implementan implícitamente IList<T> , donde <T>está el tipo de datos del arreglo. En su lugar, puede usar esa interfaz como el tipo de datos de su parámetro de método. También podría usar IEnumerable<T>para el tipo de datos. En cualquier caso (o incluso si solo lo usa int[]) no debería necesitar pasarlo explícitamente como refparámetro.

Scott Dorman
fuente
0

// La referencia a la matriz se pasa por valor. Esta es la fuente de la confusión :-) ...

        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);
    }
Domi
fuente
0

Las matrices siempre son tipos de referencia. No importa que la matriz contenga un tipo de valor como int o un tipo de referencia como una cadena. Cuando declara la matriz, por ejemplo

int[] integers=new int[10];

La variable entera en sí misma solo contiene referencias a la matriz que residirá en el montón.

También hay muchas personas que mencionan que podría diferir el tipo de valor del tipo de referencia, solo depende del hecho de que la variable podría ser nula o no. Me gustaría mencionar que en c # los tipos de valores actuales también pueden ser nulos

por ejemplo

int? integer=null

y no es una buena manera de identificar que el tipo es referencia o valor solo depende de que la variable de hecho pueda ser nula o no.

So_oP
fuente
-2

Solo un poco de una idea:

Por ejemplo, intrepresenta un solo entero, int[]representa una matriz de enteros.

Para inicializar la matriz con dimensiones específicas, puede usar la newpalabra clave, dando el tamaño entre corchetes después del nombre del tipo:

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

Todas las matrices son tipos de referencia y siguen la semántica de referencia. Por lo tanto, en este código, aunque los elementos individuales son tipos de valores primitivos, la integersmatriz es un tipo de referencia. Entonces si luego escribes:

int[] copy = integers;

esto simplemente asignará la copia variable completa para referirse a la misma matriz, no creará una nueva matriz.

La sintaxis de matriz de C # es flexible, le permite declarar matrices sin inicializarlas para que la matriz se pueda dimensionar dinámicamente más adelante en el programa. Con esta técnica, básicamente está creando una referencia nula y luego apuntando esa referencia a un tramo de ubicaciones de memoria asignadas dinámicamente solicitadas con una newpalabra clave:

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

Gracias.

Rahul Bhat
fuente