Struct v/s Class in C# - Please explain the behavi

2020-02-06 06:44发布

Could someone please explain the behavior of this

  class testCompile
    {
       /*
        *   Sample Code For Purpose of Illustration
        */
       struct person 
       {
           public int age;
           public string name;

       }

        static void Main(string[] args)
        {
            List<person> Listperson = new List<person>();
            person myperson = new person();

            for (int i = 1; i <= 2; i++)
            { 
                //Assignment
                myperson.age = 22+i;
                myperson.name = "Person - " + i.ToString();
                Listperson.Add(myperson);
            }
            int x = 0;
            while (x < Listperson.Count)
            {
                //Output values
                Console.WriteLine("{0} - {1}", Listperson[x].name, Listperson[x].age);
                x++;
            }
        }
    }

/*  
    Output:
    Person - 1 - 23
    Person - 2 - 24
*/

Why am I not getting the same output for a class as that of a struct?

class testCompile
    {
       /*
        *   Sample Code For Purpose of Illustration
        */
       class person 
       {
           public int age;
           public string name;

       }

        static void Main(string[] args)
        {
            List<person> Listperson = new List<person>();
            person myperson = new person();

            for (int i = 1; i <= 2; i++)
            { 
                //Assignment
                myperson.age = 22+i;
                myperson.name = "Person - " + i.ToString();
                Listperson.Add(myperson);
            }
            int x = 0;
            while (x < Listperson.Count)
            {
                //Output values
                Console.WriteLine("{0} - {1}", Listperson[x].name, Listperson[x].age);
                x++;
            }
        }
    }
/*  
    Output:
    Person - 2 - 24
    Person - 2 - 24 
*/

10条回答
等我变得足够好
2楼-- · 2020-02-06 07:18

You should understand key distinctions between structs (Value Types) and classes (Reference Type). You could easily find this information in Google or at SO.

When you add struct instance to List you create another separate copy for this instance, and when you change one element you did not change another.

But in case of classes you create one instance and uses this one "shared" instance with two references (list[0] and list1) and you could change this one instance through two different references, that's why when you change list[0] item it seems that you change list1 item too.

Consider following code:

var s1 = new SampleStruct { X = 1, Y = 1 };
var s2 = s1; 
//Creating separate copy
//Lets check this
Console.WriteLine(object.ReferenceEquals(s1, s2)); //Prints False

var c1 = new SampleClass { X = 1, Y = 2 };
var c2 = c1;
//We do not create any copy
// two references c1 and c2 "pointed" to one shared object
Console.WriteLine(object.ReferenceEquals(c1, c2)); //Prints True

Similar behavior we have when we pass parameter to function (or adding element to list).

查看更多
ゆ 、 Hurt°
3楼-- · 2020-02-06 07:20

It's the difference between value type (struct) and reference type (class).

  • When you're adding the struct to Listperson the content of person is put in the list, you have two different person struct in your list.

    for (int i = 1; i <= 2; i++)
    { 
      //Assignment
      myperson.age = 22+i;
      myperson.name = "Person - " + i.ToString();
      Listperson.Add(myperson);
      /* First time: 
         Listperson contains a person struct with value { age = 23, name = 1}
         Second iteration:
         Listperson contains a person struct with value { age = 23, name = 1}
         Listperson contains another person struct with value { age = 24, name = 2} 
      */
    }
    
  • When you're adding the class the reference is put in the list, you have two references that referenced the same person object.

    for (int i = 1; i <= 2; i++)
    { 
      //Assignment
      myperson.age = 22+i;
      myperson.name = "Person - " + i.ToString();
      Listperson.Add(myperson);
      /* First time: 
         Listperson contains 1 reference to myperson object with value { age = 23, name = 1}
         Second iteration:
         Listperson contains 2 reference to myperson object with value { age = 24, name = 2} 
      */
    }
    
查看更多
老娘就宠你
4楼-- · 2020-02-06 07:22

Think of variables and parameters of class types as holding an "instance IDs". The only things one can actually do directly with an instance ID are (1) create a new one (which will be assigned to a new instance of a class), (2) assign one to another, or (3) check two IDs to see if they are equal. Doing anything else with a variable, parameter, etc. of a class type is a short hand for "do _ to the instance referred to this instance ID".

So code like:

{
  Car A,B,C; /* Car is a class */
  A = new Car;
  B = new Car;
  C = A;
  A.color = carColors.Yellow;
  B.color = C.color;
}

The first "new" statement will create an instance of Car and put its instance ID (let's say #1234) in "A". The second will create another car instance (#4321) and store its ID in B. The next statement will copy #1234 into C. It doesn't do anything with the car--it just copies the ID. Then car #1234 will be painted yellow, then in the last statement, the color of car #1234 (i.e. yellow) will be used to paint car #4321. Note that while A and C are different variables, they both hold the same instance ID (#1234) and thus refer to the same car.

查看更多
乱世女痞
5楼-- · 2020-02-06 07:29

When you add the struct to the collection, it makes a copy of it. It's a value type. You'll end up with two distinct objects in the collection, each with different values. This is probably the expected behavior.

When you add the class, the reference type, to the collection, a new object is not created. You're actually adding two different references to the same object. You'll end up with (apparently) two objects with the same value. It's actually the same object, seemingly appearing twice in the collection.

查看更多
Rolldiameter
6楼-- · 2020-02-06 07:30

Structures are value types and classes are reference types. So in your first example when you add myperson to the list your adding a copy of myperson and the myperson variable still refers to a separate copy. In you second example myperson is a reference type so your adding two pointers to the same object.

查看更多
叼着烟拽天下
7楼-- · 2020-02-06 07:34

If you want same result then bring person declaration inside of the for loop:-

           // person myperson = new person();
           //Move the upper line inside the for loop
            for (int i = 1; i <= 2; i++)
            { 
               person myperson = new person();
                //Assignment
                myperson.age = 22+i;
                myperson.name = "Person - " + i.ToString();
                Listperson.Add(myperson);
            }

In struct you adding a value type hence separate values are stored, whereas in class you are adding reference to the object hence gettng same value.

查看更多
登录 后发表回答