On the effect of dictionary storing different types of variables

Time:2021-4-19

Recently, I’m writing a small tool, which uses a custom class and needs to instantiate the class.

Because we need to get different instances according to the requirements, we decided to put them into a dictionary for easy access.

In addition, because the content of instantiation may be changed later, we prepare to encapsulate the concrete instantiation code into a separate subroutine for change.

 

So we write the following code:

namespace Example
 {
     public partial class MainWindow : Window
     {
         //Because it will be referenced in other places, it is defined in the outermost layer
         public static MyClass staff1; 
         public static MyClass staff2;
         public static Dictionary staffDic = new Dictionary()
         {
             {"aaa",staff1},
             {"bbb",staff2}
         };
 
         private void Window_Loaded(object sender, RoutedEventArgs e)
         {
             InitializationStaff();
             System.Console.WriteLine(staffDic["aaa"]);
         }
 
         Private void initializationstaff() // add instance to variable
         {
             staff1=new MyClass(){a=1,b=2,c=3};
             staff2=new MyClass(){a=3,b=2,a=1};
         }
     }
 
     Class MyClass 
     {
         public int a;
         public int b;
         public int c;
     }
 }

The result shows that an error is reported in the output, indicating that the corresponding content of the item in the dictionary is null.

If you modify the code, instantiate it outside

namespace Example
{
    public partial class MainWindow : Window
    {
        //Because it will be referenced in other places, it is defined in the outermost layer
        //Instantiate when you define a variable
        public static MyClass staff1 = new MyClass(); 
        public static MyClass staff2 = new MyClass();
        public static Dictionary staffDic = new Dictionary()
        {
            {"aaa",staff1},
            {"bbb",staff2}
        };

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            InitializationStaff();
            System.Console.WriteLine(staffDic["aaa"]);
        }

        Private void initializationstaff() // modify variables
        {
            staff1.a = 1;
            staff1.b = 2;
            staff1.c = 3;

            staff2.a = 3;
            staff2.b = 2;
            staff2.a = 1;
        }
    }

    Class MyClass 
    {
        public int a;
        public int b;
        public int c;
    }
}

At this point, the output content is normal.

So what’s going on behind this?

 

After consulting a friend, I learned that in c#, when you add the value corresponding to the key to the dictionary, the actual effect is to add the target content to the dictionarycopyTo the dictionary, andIt’s not a citation

People who know about variables and memory should know that when we write a line of code:

int a = 123;

What happens at this time is that the system first finds a memory space, stores the value 123 in it, and records the address a of the memory space.

In variable a, the actual storage is address a.

 

When we add a variable to the dictionary:

Dictionary Dic = new Dictionary() { { "number1", a } };

The dictionary first finds the variable a and gets the address a where the data is stored.

Then copy the content of address a and paste it into another memory space opened up by the dictionary. The address of this memory space is address B.

At this point, no matter how we assign a value to the variable a, a in the dictionary will not change.

When assigning a value to variable a, the data in the memory space with address a is actually modified, while a in the dictionary is stored in the memory space with address B.

 

However, according to this conclusion, the second method I used at the beginning of this article should be to modify the data of the members of the class externally, and the contents of the dictionary will not change?

Why did the contents of the dictionary change when it was modified externally?

 

When we write the following code:

 namespace Example
 {
     public partial class MainWindow : Window
     {
         private void Window_Loaded(object sender, RoutedEventArgs e)
         {
             public static MyClass staff = new MyClass(); 
         }
     }
 
     Class MyClass 
     {
         public int a;
         public int b;
         public int c;
     }
 }

In the variable staff, an address a is stored, and a type such as MyClass is stored at address a, that is, three variables a, B and C.

The three variables a, B and C actually store address a, address B and address C respectively.

Where these three addresses point to is the memory space in which the data is stored.

 

When we add staff to the dictionary, the dictionary reads address a and copies the contents stored at address a to its newly opened memory space at address B.

When copying, the addresses of a, B and C are copied to address B.

 

At this time, the external variable staff and the staff in the dictionary will point to the same three memory spaces.

When the content is modified by the external variable staff, because the staff in the dictionary actually accesses the same address, the content in the dictionary will also change.

 

It may be a bit confusing to say so. It should be clearer to express it with a graph.

 

The above is my understanding, if there are omissions, please give me more advice.