Análisis C# de tipos de valor y tipos de referencia, memoria de montón y memoria de pila, copia superficial y copia profunda

Resumen: Explicar el concepto, división y distinción de tipos de valor y tipos de referencia, así como los diferentes métodos de almacenamiento utilizados en ellos-memoria de pila y memoria de pila.

Lenguaje de programación: C#

Entorno de programación: Visual Studio 2019

Tabla de contenido

El concepto de tipos de valor y tipos de referencia

Tipos de valores comunes y tipos de referencia

La diferencia y la conexión entre el tipo de valor y el tipo de referencia

la diferencia

conectar

Memoria de montón y pila

concepto

la diferencia

copia superficial y copia profunda

concepto

Implementación

ejemplo

resumen 

cada mensaje


El concepto de tipos de valor y tipos de referencia

        En C#, los tipos se dividen en dos tipos: tipos de valor y tipos de referencia. Las variables de tipo de valor se refieren a variables que almacenan datos directamente. Sus instancias generalmente se asignan en la pila (asignación estática), mientras que las variables de tipo de referencia contienen referencias de datos. los datos se almacenan en el montón de datos y sus instancias se asignan en el montón (asignación dinámica).

        Solo mirar el concepto puede ser abstracto, usemos un ejemplo para ilustrarlo.

int i = 10;//定义值类型——int型
int[] ii = { 1, 2, 3 };//定义引用类型——数组

//分别输出这两个变量
Console.WriteLine(i);
Console.WriteLine(ii);

        Ejecutar el programa, salida

        Se puede ver que para los tipos de valor, su valor se emite directamente, mientras que para los tipos de referencia, solo se emite su referencia. Porque los datos del tipo de valor se almacenan directamente en la pila, y el tipo de referencia solo almacena la referencia en la pila, y sus datos se almacenan en el montón, como se muestra en la figura.

 

Tipos de valores comunes y tipos de referencia

Tipos de valores comunes y tipos de referencia
tipo de valor tipo de datos básicos int, float, double, char, bool
tipo enumerado enumeración
estructura estructura
tipo de referencia amable Clase base Objeto, cadena, clase de clase personalizada
interfaz interfaz
formación Matrices de varios tipos

   

La diferencia y la conexión entre el tipo de valor y el tipo de referencia

la diferencia

  • Los métodos de almacenamiento en la memoria son diferentes, que se han presentado en detalle anteriormente.
  • El método de recuperación de la memoria es diferente. El tipo de valor se almacena en la pila y se reciclará inmediatamente después de su uso, mientras que los datos de tipo de referencia se almacenan en el montón y esperarán la recolección de elementos no utilizados después de su uso (el recolector de elementos no utilizados de GC se recicla automáticamente).
  • El tipo de valor contiene sus siguientes datos cuando se declara, mientras que el tipo de referencia solo define un puntero en la pila cuando se declara, y debe crearse una instancia con new antes de abrir espacio de memoria en el montón. Si utiliza una variable de tipo de referencia no instanciada, se producirá una excepción de puntero nulo porque no hay espacio de memoria correspondiente. Los ejemplos son los siguientes:

  • Para la asignación de tipo de valor, es equivalente a copiar un nuevo objeto con el mismo valor, mientras que para la asignación de tipo de referencia, es equivalente a una referencia al objeto original, y cambiar su valor afectará al objeto original. (Este proceso pertenece a la copia superficial) El código de ejemplo es el siguiente:

int i = 10;
int j = i;//i赋值给j,相当于复制一个同值新对象
j = 15;
Students student1 = new Students();//实例化学生1 张三 80
student1.Name = "张三";
student1.Score = 80;
Students student2 = student1;//学生1赋值给学生2,相当于student2拥有student1的引用
student2.Name = "李四"; 
student2.Score = 90;

//分别输出值类型i,j,发现i和j互不影响
Console.WriteLine(i);
Console.WriteLine(j);

//分别输出两个学生的信息,发现student1的信息被覆盖为student2
Console.WriteLine(student1.Name);
Console.WriteLine(student1.Score);
Console.WriteLine(student2.Name);
Console.WriteLine(student2.Score);

        Ejecutando el programa, la salida es

        Se puede ver que los significados de las asignaciones de tipos de valor y tipos de referencia son diferentes.El tipo de valor es para copiar un nuevo objeto, y el tipo de referencia es para copiar una referencia al objeto original.

  • Cuando se usan como parámetros y valores de retorno de funciones, las reglas son las mismas que las anteriores, el tipo de valor es la copia de los parámetros de entrada variables o el valor de retorno, y el tipo de referencia es la referencia a los parámetros de entrada de copia variable o el retorno. valor. 
  • Los tipos de referencia pueden derivar nuevos tipos y admitir polimorfismo, mientras que los tipos de valor están sellados y no admiten polimorfismo.

conectar

  • Los tipos de referencia pueden implementar interfaces y los tipos de valor pueden implementar interfaces con estructuras.
  • El tipo de referencia se hereda directamente de la clase System.Object y el tipo de valor se hereda directamente de la clase System.ValueTpye, una subclase de Syetem.Object.

Memoria de montón y pila

concepto

        Cuando un programa C# se ejecuta en Common Language Runtime (CLR), la memoria se divide lógicamente en dos bloques, la pila y el montón. El montón también se denomina montón administrado y la pila también se denomina pila.

la diferencia

  • El espacio de pila sigue el principio de último en entrar, primero en salir. Cuando el elemento superior de la pila se agota, se libera inmediatamente; el espacio de almacenamiento dinámico es como un almacén, que será buscado y llamado por sí mismo cuando sea necesario, y necesita ser limpiado por GC.
  • El espacio de pila es relativamente pequeño, pero la lectura de datos es rápida; el espacio de almacenamiento dinámico es relativamente grande, pero la lectura de datos es lenta.

copia superficial y copia profunda

concepto

        Al hacer una copia superficial de un objeto, si es un miembro de tipo valor, se copiará un nuevo objeto equivalente a sí mismo, si es un miembro de tipo referencia, solo se copiará su referencia; cuando se copia un objeto en profundidad, el El miembro de tipo de referencia apuntará a que los objetos también se copian. Cuando queremos copiar completamente un objeto de tipo referencia que no tiene nada que ver con el objeto original, y los dos están completamente separados, tenemos que usar la copia profunda.

Implementación

        Para una copia superficial, asignar un objeto directamente a un nuevo objeto es una copia superficial, o usar el método MemberwiseClone() del objeto para implementar una copia superficial. Para la copia profunda, Xiaobian presenta un método más conveniente: el método de deserialización para realizar una copia profunda, el código es el siguiente: (Nota: T que llama a este método debe agregar [Serializable] al frente para indicar que se puede serializar)

//反序列化深拷贝方法,T表示拷贝对象类,调用此方法需在T前加[Serializable]
public static T DeepCopyByBinary<T>(T obj)
{
    object retval;
    using (MemoryStream ms = new MemoryStream())
    {
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(ms, obj);
        ms.Seek(0, SeekOrigin.Begin);
        retval = bf.Deserialize(ms);
        ms.Close();
    }
    return (T)retval;
}

ejemplo

        Vaya directamente al código, donde estudiante2 es una copia superficial de estudiante1 y estudiante3 es una copia profunda de estudiante1.

Students student1 = new Students();//实例化学生1 张三 80
student1.Name = "张三";
student1.Score = 80;
Students student2 = student1;//学生1赋值给学生2,相当于浅拷贝
student2.Name = "李四"; 
student2.Score = 90;
Students student3 = DeepCopyByBinary(student1);//对学生1深拷贝,赋值给学生3
student3.Name = "王麻子";
student3.Score = 100;

//分别输出三个学生的信息
Console.WriteLine(student1.Name);
Console.WriteLine(student1.Score);
Console.WriteLine(student2.Name);
Console.WriteLine(student2.Score);
Console.WriteLine(student3.Name);
Console.WriteLine(student3.Score);

        La salida es:

        Se puede ver que después de la copia superficial, estudiante2 es solo una referencia a estudiante1; después de la copia profunda, estudiante3 y estudiante1 son dos objetos independientes.

resumen 

        Es muy importante comprender el tipo de valor y el tipo de referencia en la programación de C#, lo que evitará la aparición de muchos errores, comprender el montón y la pila en .Copy y deep copy nos permiten elegir correctamente el método de copia apropiado de acuerdo con las necesidades de copia. .

cada mensaje

        Una actitud seria puede hacer que las cosas sucedan y nosotros podemos mejorarlas, ese es el secreto que no podemos descartar en el camino del crecimiento.

Supongo que te gusta

Origin blog.csdn.net/lucgh/article/details/130362522
Recomendado
Clasificación