Analyse C # des types de valeur et des types de référence, mémoire de tas et mémoire de pile, copie superficielle et copie profonde

Résumé : Expliquer le concept, la division et la distinction des types de valeur et des types de référence, ainsi que les différentes méthodes de stockage utilisées dans les mémoires de tas et de pile.

Langage de programmation : C#

Environnement de programmation : Visual Studio 2019

Table des matières

Le concept de types valeur et de types référence

Types de valeur et types de référence courants

La différence et la connexion entre le type de valeur et le type de référence

la différence

connecter

Mémoire de tas et de pile

concept

la différence

copie superficielle et copie profonde

concept

Mise en œuvre

exemple

résumé 

chaque message


Le concept de types valeur et de types référence

        En C#, les types sont divisés en deux types : les types valeur et les types référence. Les variables de type valeur font référence à des variables qui stockent directement des données. Ses instances sont généralement allouées sur la pile (allocation statique), tandis que les variables de type référence contiennent des références de données. , ses les données sont stockées dans le tas de données et ses instances sont allouées sur le tas (allouées dynamiquement).

        Le simple fait de regarder le concept peut être abstrait, utilisons un exemple pour illustrer.

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

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

        Exécuter le programme, sortie

        On peut voir que pour les types valeur, sa valeur est directement sortie, tandis que pour les types référence, seule sa référence est sortie. Parce que les données de type valeur sont directement stockées sur la pile et que le type référence ne stocke que la référence sur la pile, et ses données sont stockées dans le tas, comme illustré dans la figure.

 

Types de valeur et types de référence courants

Types de valeur et types de référence courants
type de valeur type de données de base int、float、double、char、bool等
type énuméré énumération
structure structure
Type de référence type Classe de base Objet, chaîne, classe de classe personnalisée
interface interface
déployer Tableaux de différents types

   

La différence et la connexion entre le type de valeur et le type de référence

la différence

  • Les méthodes de stockage en mémoire sont différentes, qui ont été présentées en détail ci-dessus.
  • La méthode de récupération de la mémoire est différente. Le type valeur est stocké sur la pile et sera recyclé immédiatement après utilisation, tandis que les données de type référence sont stockées dans le tas et attendront la récupération de place après utilisation (GC garbage collector recycle automatiquement).
  • Le type valeur contient ses données suivantes lorsqu'il est déclaré, tandis que le type référence définit uniquement un pointeur sur la pile lorsqu'il est déclaré, et il doit être instancié avec new avant d'ouvrir de l'espace mémoire dans le tas. Si vous utilisez une variable de type référence non instanciée, une exception de pointeur nul se produira car il n'y a pas d'espace mémoire correspondant. Les exemples sont les suivants :

  • Pour l'affectation de type valeur, cela équivaut à copier un nouvel objet avec la même valeur, tandis que pour l'affectation de type référence, cela équivaut à une référence à l'objet d'origine, et la modification de sa valeur affectera l'objet d'origine. (Ce processus appartient à la copie superficielle) L'exemple de code est le suivant :

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

        En exécutant le programme, la sortie est

        On peut voir que les significations des affectations des types valeur et des types référence sont différentes. Le type valeur consiste à copier un nouvel objet et le type référence consiste à copier une référence à l'objet d'origine.

  • Lorsqu'elles sont utilisées comme paramètres et valeurs de retour de fonctions, les règles sont les mêmes que ci-dessus, le type de valeur est la copie des paramètres d'entrée variables ou la valeur de retour, et le type de référence est la référence aux paramètres d'entrée de copie variable ou retour valeur. 
  • Les types de référence peuvent dériver de nouveaux types et prendre en charge le polymorphisme, tandis que les types de valeur sont scellés et ne prennent pas en charge le polymorphisme.

connecter

  • Les types référence peuvent implémenter des interfaces et les types valeur peuvent implémenter des interfaces avec des structures.
  • Le type référence hérite directement de la classe System.Object et le type valeur hérite directement de la classe System.ValueTpye, une sous-classe de Syetem.Object.

Mémoire de tas et de pile

concept

        Lorsqu'un programme C# s'exécute dans le Common Language Runtime (CLR), la mémoire est logiquement divisée en deux blocs, la pile et le tas. Le tas est également appelé le tas géré et la pile est également appelée la pile.

la différence

  • L'espace de la pile suit le principe du dernier entré, premier sorti. Lorsque l'élément supérieur de la pile est épuisé, il est libéré immédiatement ; l'espace du tas est comme un entrepôt, qui sera recherché et appelé par lui-même en cas de besoin, et doit être nettoyé par GC.
  • L'espace de la pile est relativement petit, mais la lecture des données est rapide ; l'espace du tas est relativement grand, mais la lecture des données est lente.

copie superficielle et copie profonde

concept

        Lors de la copie superficielle d'un objet, s'il s'agit d'un membre de type valeur, un nouvel objet équivalent à lui-même sera copié, s'il s'agit d'un membre de type référence, seule sa référence sera copiée ; lorsqu'un objet est copié en profondeur, le le membre de type référence pointera vers les objets sont également copiés. Lorsque nous voulons copier complètement un objet de type référence qui n'a rien à voir avec l'objet d'origine et que les deux sont complètement séparés, nous devons utiliser une copie en profondeur.

Mise en œuvre

        Pour une copie superficielle, l'affectation d'un objet directement à un nouvel objet est une copie superficielle ou l'utilisation de la méthode MemberwiseClone() de l'objet pour implémenter une copie superficielle. Pour la copie en profondeur, Xiaobian introduit une méthode plus pratique - la méthode de désérialisation pour réaliser une copie en profondeur, le code est le suivant : (Remarque : T qui appelle cette méthode doit ajouter [Serializable] devant pour indiquer qu'elle peut être sérialisée)

//反序列化深拷贝方法,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;
}

exemple

        Accédez directement au code, où étudiant2 est une copie superficielle de étudiant1 et étudiant3 est une copie complète de étudiant1.

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 sortie est :

        On peut voir qu'après copie superficielle, étudiant2 n'est qu'une référence à étudiant1 ; après copie profonde, étudiant3 et étudiant1 sont deux objets indépendants.

résumé 

        Il est très important de comprendre le type de valeur et le type de référence dans la programmation C#, ce qui évitera l'apparition de nombreux bugs ; comprendre le tas et la pile sous . La copie et la copie profonde nous permettent de choisir correctement la méthode de copie appropriée en fonction des besoins de copie .

chaque message

        Une attitude sérieuse peut faire avancer les choses, et nous pouvons améliorer les choses.C'est le secret que nous ne pouvons pas écarter sur la voie de la croissance.

Je suppose que tu aimes

Origine blog.csdn.net/lucgh/article/details/130362522
conseillé
Classement