Maison développement back-end Tutoriel C#.Net Exemple de partage de code .NET Framework d'interruptions de référence

Exemple de partage de code .NET Framework d'interruptions de référence

Mar 18, 2017 pm 01:39 PM

Les valeurs

1 sont égales, les objets sont égaux par défaut ?
Quelles sont les règles par défaut pour déterminer l'existence d'un type référence dans un conteneur .net ? Déterminez si les valeurs du pointeur sont égales.

        private static List<int> list;        
        static void Main(string[] args)
        {            
        //新建实例instance1
            MyObject instance1 = new MyObject();
            instance1.Value = 10;            
            //新建list
            List<MyObject> list = new List<MyObject>();            
            //引用实例instance1
            list.Add(instance1);            
            //新建实例:instance2
            MyObject instance2 = new MyObject();            
            //赋值为instance1.Value
            instance2.Value = instance1.Value;       
        }
    }
Copier après la connexion

Classe Modèle utilisée :

            public class MyObject
            {
                public int Value { get; set; }
            }
Copier après la connexion

Faites un test ci-dessous :

            //即便Value相等,instance2与instance1的内存地址不相等!
            bool isExistence1 = list.Contains(instance2);            //isExistence1 : false;
Copier après la connexion

Ce résultat de test estfaux , car ils pointent vers des adresses mémoire différentes, bien que les valeurs​​sont égales, ce qui est le cas de "les valeurs sont égales, les objets ne sont pas égaux".
 
Si un type référence veut déterminer s'il est égal en fonction de la valeur de l'un des attributs, alors il doit implémenter l'interface IEquatable !
Si vous souhaitez continuer à voir si les objets sont égaux selon que les valeurs sont égales, veuillez vous référer à l'article : C#Conteneurs, classes d'interface, performances

2 Pièges de référence ?

 Un objet fait référence à un autre objet Quand l'un change, l'autre change . Par exemple, lors de la fusion de deux dictionnaires, le résultat de la fusion est correct, mais l'objet d'origine est accidentellement modifié.

Voici un exemple :

            var dict1 = new Dictionary<string, List<string>>();
            dict1.Add("qaz",new List<string>(){"100"});//含有qaz键
            dict1.Add("wsx",new List<string>(){"13"});            var dict2 = new Dictionary<string, List<string>>();
            dict2.Add("qaz", new List<string>() { "11" });//也含有qaz键
            dict2.Add("edc", new List<string>() { "17" });            //合并2个字典到dict            
            var dictCombine = new Dictionary<string, List<string>>();
            foreach (var ele in dict1) //拿到dict1
            {
               dictCombine .Add(ele.Key,ele.Value); 
            }

            foreach (var ele in dict2) //拿到dict2
            {                if(dictCombine.ContainsKey(ele.Key))//检查重复
                   dictCombine [ele.Key].AddRange(ele.Value); 
                else
                {
                    dictCombine .Add(ele.Key,ele.Value); 
                }
            }
Copier après la connexion

Le résultat de dictCombine est correct, {"qaz", "100" et "11"}, { "wsx","13"}, {"edc","17"}
Mais qu'en est-il du résultat de dict1 ? J'ai été changé ! dict1 est devenu de manière inattendue {"qaz", "100" et "11"}, {"wsx", "13"}. Fusion correcte, dict1 ne doit pas être modifié !

Analyse de la raison

dictCombine ajoute d'abord la valeur clé de dict1, c'est-à-dire que la valeur clé de dictCombine fait toutes référence à la valeur clé de dict1 ; Ensuite, lors de la fusion de dict2, déterminez d'abord si dictCombine contient la clé de dict2. Si c'est le cas, ajoutez-la à la valeur clé de dictCombine. La valeur fait référence au même objet, c'est-à-dire que cette valeur est ajoutée à la clé de dict1. Vérification si les références dictCombine[ele.Key] et dict1[ele.Key] sont égales :

bool flag = object.ReferenceEquals(dictCombine[ele.Key], dict1[ele.Key]);//true
Copier après la connexion

Solution correcte

Évitez dictCombine[ele.Key] et dict1 [ele.Key] Égalité de référence ! ! !

Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();            
//先把键都合并到dictCombine中,值都是新创建的
            foreach (var key in dict1.Keys)
            {                if (!dictCombine.ContainsKey(key))
                    dictCombine.Add(key, new List<string>());
            }            foreach (var key in dict2.Keys)
            {                if (!dictCombine.ContainsKey(key))
                    dictCombine.Add(key, new List<string>());
            }     //分别将值添加进去
            foreach (var ele in dict1)
            {
                dictCombine[ele.Key].AddRange(ele.Value);
            }            foreach (var ele in dict2)
            {
                dictCombine[ele.Key].AddRange(ele.Value);
            }
Copier après la connexion

Le résultat de la fusion dictCombine est correct, et ni dict1 ni dict2 n'ont changé !

Résumé
  L'utilisation de l'égalité de référence apporte de nombreux avantages, tels que les références entre fonctionspassage par valeur(par référence) . Cependant, si elle est mal utilisée, elle nous apportera également des problèmes inutiles.​

3 Une référence incorrecte détruit l'encapsulation ?
 
Si le champ privé dans la classe encapsulée est utilisé comme valeur de retour de la méthode d'interface, cette approche détruira l'encapsulation de la classe, en particulier Une question qui est facilement négligée. Si vous ignorez ce problème, des problèmes inexplicables peuvent survenir.
 
 Comme le montre le code suivant,
 

public class TestPrivateEncapsulate
{
    private List<object> _refObjs;

    public List<object> GetRefObjs()
    {
        _refObjs = new List<object>();        ...
        ...
       //其他逻辑处理计算出来的_refObjs={1,4,2};    
        return _refObjs; //返回私有字段
    }

    public object GetSumByIterRefObjs()
    {        if (_refObjs == null)            return null;
        foreach (var item in _refObjs)
        {            ...//处理逻辑
        }
    }  
}
Copier après la connexion

 Maintenant, en utilisant la classe TestPrivateEncapsulate que nous venons d'écrire, nous créons d'abord une instance,

TestPrivateEncapsulate test = new TestPrivateEncapsulate();
Copier après la connexion

Puis appelez :

List<object> wantedObjs = test.GetRefObjs();
Copier après la connexion

Les wantedObjs attendus renvoyés doivent avoir 3 éléments de type entier, 1, 4, 2.

Continuer :

List<object> sol = wantedObjs; //我们将sol指向wantedObjssol.Add(5); //加入元素5
Copier après la connexion

Lorsque nous voulons revenir en arrière et calculer, la somme originale des éléments de wantedObjs :

test.GetSum();
Copier après la connexion

Nous avons accidentellement obtenu 12, pas quoi nous nous attendions à 7 pouces. Pourquoi est-ce ?

Après une analyse minutieuse, nous avons constaté qu'après avoir appelé sol.Add(5) sur le client, nous avons indirectement modifié la variable dans TestPrivateEncapsulate : _refObjs, qui est passée de {1,4,2} à {1, 4,2,5}.

 Les variables privées ont été modifiées côté client ! C'est l'effet secondaire du retour de variables privées par l'interface !

 Solution correcte :

    // 将原来的公有变为私有
    private List<object> getRefObjs()
    {
        _refObjs = new List<object>();        ...
        ...
       //其他逻辑处理计算出来的_refObjs={1,4,2};    
        return _refObjs; //返回私有字段
    }

    //只带只读的属性
    public RefObjs
    {
        get
         {
            getRefObjs();            
            return _refObjs;
         }
    }
Copier après la connexion

Définissez un champ public avec uniquement des attributs en lecture seule et remplacez la méthode publique d'origine GetRefObjs par la méthode privée getRefObjs . De cette façon, il est impossible de modifier les champs privés côté client !

Résumé
Les valeurs d'attribut des objets sont toutes égales, mais les références d'objet ne sont pas nécessairement égales.
Deux objets ou plus font référence à un objet. Si cet objet est modifié, les valeurs d'attribut de tous les référents sont également modifiées. ;
Member return Les variables de référence encapsulées détruiront l'encapsulation.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Commandes de chat et comment les utiliser
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Comment gérer les caractères spéciaux dans la langue C Comment gérer les caractères spéciaux dans la langue C Apr 03, 2025 pm 03:18 PM

Dans le langage C, les caractères spéciaux sont traités à travers des séquences d'échappement, telles que: \ n représente les pauses de ligne. \ t signifie le caractère d'onglet. Utilisez des séquences d'échappement ou des constantes de caractères pour représenter des caractères spéciaux, tels que char c = '\ n'. Notez que l'arrière-plan doit être échappé deux fois. Différentes plates-formes et compilateurs peuvent avoir différentes séquences d'échappement, veuillez consulter la documentation.

Quel est le rôle de char dans les chaînes C Quel est le rôle de char dans les chaînes C Apr 03, 2025 pm 03:15 PM

En C, le type de char est utilisé dans les chaînes: 1. Stockez un seul caractère; 2. Utilisez un tableau pour représenter une chaîne et se terminer avec un terminateur nul; 3. Faire fonctionner via une fonction de fonctionnement de chaîne; 4. Lisez ou sortant une chaîne du clavier.

Comment utiliser divers symboles dans le langage C Comment utiliser divers symboles dans le langage C Apr 03, 2025 pm 04:48 PM

Les méthodes d'utilisation des symboles dans la couverture du langage C Couverture arithmétique, l'affectation, les conditions, la logique, les opérateurs de bits, etc. Les opérateurs arithmétiques sont utilisés pour les opérations mathématiques de base, les opérateurs d'affectation sont utilisés pour les opérations et les opérations de la soustraction, la multiplication et les opérations de division, les opérations BIT sont utilisé pointeurs nuls, marqueurs de fin de fichier et valeurs non nucères.

La différence entre char et wchar_t dans le langage C La différence entre char et wchar_t dans le langage C Apr 03, 2025 pm 03:09 PM

Dans le langage C, la principale différence entre Char et WCHAR_T est le codage des caractères: Char utilise ASCII ou étend ASCII, WCHAR_T utilise Unicode; Char prend 1 à 2 octets, WCHAR_T occupe 2-4 octets; Char convient au texte anglais, WCHAR_T convient au texte multilingue; Le char est largement pris en charge, WCHAR_T dépend de la prise en charge du compilateur et du système d'exploitation Unicode; Le char est limité dans la gamme de caractères, WCHAR_T a une gamme de caractères plus grande et des fonctions spéciales sont utilisées pour les opérations arithmétiques.

La différence entre le multithreading et le C # asynchrone La différence entre le multithreading et le C # asynchrone Apr 03, 2025 pm 02:57 PM

La différence entre le multithreading et l'asynchrone est que le multithreading exécute plusieurs threads en même temps, tandis que les opérations effectuent de manière asynchrone sans bloquer le thread actuel. Le multithreading est utilisé pour les tâches à forte intensité de calcul, tandis que de manière asynchrone est utilisée pour l'interaction utilisateur. L'avantage du multi-threading est d'améliorer les performances informatiques, tandis que l'avantage des asynchrones est de ne pas bloquer les threads d'interface utilisateur. Le choix du multithreading ou asynchrone dépend de la nature de la tâche: les tâches à forte intensité de calcul utilisent le multithreading, les tâches qui interagissent avec les ressources externes et doivent maintenir la réactivité de l'interface utilisateur à utiliser asynchrone.

Comment convertir le charbon dans la langue C Comment convertir le charbon dans la langue C Apr 03, 2025 pm 03:21 PM

Dans le langage C, la conversion de type char peut être directement convertie en un autre type par: Casting: Utilisation de caractères de casting. Conversion de type automatique: Lorsqu'un type de données peut accueillir un autre type de valeur, le compilateur le convertit automatiquement.

Comment utiliser Char Array dans la langue C Comment utiliser Char Array dans la langue C Apr 03, 2025 pm 03:24 PM

Le Array Char stocke des séquences de caractères en C et est déclaré Char Array_name [Taille]. L'élément d'accès est passé par l'opérateur d'indice, et l'élément se termine par le terminateur nul «\ 0», qui représente le point final de la chaîne. Le langage C fournit une variété de fonctions de manipulation de cordes, telles que strlen (), strcpy (), strcat () et strcmp ().

Quelle est la fonction de la somme du langage C? Quelle est la fonction de la somme du langage C? Apr 03, 2025 pm 02:21 PM

Il n'y a pas de fonction de somme intégrée dans le langage C, il doit donc être écrit par vous-même. La somme peut être obtenue en traversant le tableau et en accumulant des éléments: Version de boucle: la somme est calculée à l'aide de la longueur de boucle et du tableau. Version du pointeur: Utilisez des pointeurs pour pointer des éléments de tableau, et un résumé efficace est réalisé grâce à des pointeurs d'auto-incitation. Allouer dynamiquement la version du tableau: allouer dynamiquement les tableaux et gérer la mémoire vous-même, en veillant à ce que la mémoire allouée soit libérée pour empêcher les fuites de mémoire.

See all articles