In simple terms, a struct is a value type, and an instance of a struct type is created to be allocated on the stack. Class is a reference type and creates a class type instance that is assigned to the managed heap. But the difference between struct and class is much more than simple.
In summary, the difference between struct and class is reflected in:
Class is a reference type, a struct is a value type, and all of them have distinguishing characteristics of value types and reference types, see differences between C # value types and reference types
The instance of class is created on the managed heap , and the struct instance is created on the stack
The assignment of the class instance, the assignment of the reference address, the assignment of the struct instance, and the assigned value
Class is passed as a parameter type, passing a reference address, a struct being passed as a parameter type, passing a value
The default access permission for class is private, and the default access permission for the struct is public
A struct cannot explicitly declare a parameterless constructor (the default constructor) or a destructor, which means that the constructor declared by the struct must have parameters , whereas class can explicitly declare a parameterless constructor. ( because a copy of a struct is automatically created and destroyed by the compiler, you do not need to use a default constructor and destructor.) In fact, the compiler implements the default constructor by assigning default values to all fields (see Default Values Table (C # Reference) )
If you only declare a constructor with parameters in class, you cannot create an instance with the New keyword without a parameter constructor (the default constructor), or you will get a compile error with the "XXX constructor with no 0 arguments". The meaning of this sentence means that unless there is a constructor in class, what constructors are declared, only what constructors are used.
In structs, because only constructors with parameters can be declared, when an instance is created
The class creation instance must use the New keyword, and the struct can be either new or new, except that the struct's member function has an initial value in the struct generated with new. Examples are as follows:
struct point{ float x; float y;} Point P = new Point ();p is a value type so it should be allocated space on the stack float a = p.x; Compiled by using the new statement, members in the C # struct have been initialized, and a has a value of 0Point p;foalt a = p.x; Compilation However, the compiler thinks that the field of P is not initialized and is unknown
Class supports inheritance, structs do not support inheritance, but interfaces are supported.
Class is biased toward "object-oriented" for complex, large data, structs biased towards "simple values" such as less than 16 bytes, simple structure
A member variable of class can assign an initial value at the time of Declaration, and in a struct declaration it cannot be initialized unless the field is declared const or static.
Experience the difference between struct and class from an assignment perspective
A reference type is assigned a value that assigns the address to the variable
Class program { static void Main (string[] args) { Sizeclass sizeclass = new Sizeclass () {Width = ten, lengt h = ten}; Console.WriteLine ("Pre-assignment: Width={0},length={1}", Sizeclass.width, sizeclass.length); var copyofsizeclass = Sizeclass; Copyofsizeclass.length = 5; Copyofsizeclass.width = 5; Console.WriteLine ("After Assignment: Width={0},length={1}", Sizeclass.width, sizeclass.length); Console.readkey (); } } public class Sizeclass {public int Width {get; set;} public int Length {get; set;} } public struct sizestruct {public int Width {get; set;} public int Length {get; set;} }
The results of the operation are as follows:
Above, when the Sizeclass is assigned to the copyofsize variable, the Sizeclass point to the address assigned to the copyofsize variable, 2 variables simultaneously point to the same address. Therefore, when changing the value of the Copyofsizeclass variable, it is also equivalent to changing the value of the Sizeclass.
struct type assignment, is a full copy, with an exact same variable on the stack
Class program { static void Main (string[] args) { sizestruct sizestruct = new Sizestruct () {Length = ten, W Idth = ten}; Console.WriteLine ("Pre-assignment: Width={0},length={1}", Sizestruct.width, sizestruct.length); var copyofsizestruct = sizestruct; Copyofsizestruct.length = 5; Copyofsizestruct.width = 5; Console.WriteLine ("After Assignment: Width={0},length={1}", Sizestruct.width, sizestruct.length); Console.readkey (); } }
The results of the program run are as follows:
Above, when the sizestruct is assigned to the COPYOFSIZESTRUCT variable, is a full copy, changing the value of copyofsizestruct will not affect the sizestruct.
Second, experience the difference between struct and class from the point of view of parameter value
The reference type parameter is passed the address
Class program { static void Main (string[] args) { list<string> temp = new list<string> () {" My "," God "}; Changereferencetype (temp); Temp. ForEach (t = console.write (t + "")); Console.readkey (); } public static void Changereferencetype (list<string> list) { list = new list<string> () {"Hello", " World "}; } }
Running Result: my God
Why not Hello world?
→ Temp on stack points to a collection instance on the managed heap
→ When temp is put into the Changereferencetype (temp) method, the essence is to assign the address that temp points to the variable list
→ Within the changereferencetype (list<string> list) method, the variable list is pointed to another collection instance address
→ But the pointing address of temp has not changed
Let's change the internal implementation of the Changereferencetype (list<string> List), others unchanged.
Class program { static void Main (string[] args) { list<string> temp = new list<string> () {" My "," God "}; Changereferencetype (temp); Temp. ForEach (t = console.write (t + "")); Console.readkey (); } public static void Changereferencetype (list<string> list) { list. Clear (); List. ADD ("Hello"); List. ADD ("World"); } }
Run Result: Hello World
Why not my God?
→ Temp on stack points to a collection instance on the managed heap
→ When temp is put into the Changereferencetype (temp) method, the essence is to assign the address that temp points to the variable list
→ Inside the Changereferencetype (list<string> list) method, empty the instance that the TEMP and list point together, adding "Hello" and "World" 2 elements
→ Because the list and temp point to the same instance, changing the instance that the list points to is equivalent to changing the instance that the temp points to
The above, well illustrated: the reference type parameter is passed the address.
Value type the struct parameter is passed the value
Class program { static void Main (string[] args) { size s = new Size () {Length = ten, Width = ten}; Changestructtype (s); Console.Write ("Length={0},width={1}", s.length,s.width); Console.readkey (); } public static void Changestructtype (size size) { size. Length = 0; Size. Width = 0; } } public struct Size {public int Length {get; set;} public int Width {get; set;} }
The results of the operation are as follows:
Why is length and width not 0?
→ Variable size on stack
→ When passing changestructtype (size), the s variable is assigned to the size variable in changestructtype (size size), which essentially creates a variable on the stack size,size the value is exactly the same as S.
→ Change the value of size inside Changestructtype (size size), which has nothing to do with the variable s
Third, experience the difference between struct and class from struct type attribute and struct reference type property of struct type
Suppose there is a struct that has a property of struct type
Below, the struct type has properties tablesize and tvsize of the struct type, how can we modify the property values of its struct type through the instance of the class?
Class program { static void Main (string[] args) {guest r = new () { tablesize = new Size () {Le Ngth = +, width = n}, tvsize = new Size () {Length = ten, width = 8} }; r.tablesize.length = 0; Console.WriteLine ("Table current size is: Length={0},width={1}", R.tablesize.length, r.tablesize.width); Console.readkey (); } } public struct Size {public int Length {get; set;} public int Width {get; set;} } public struct- tablesize {public Size} {get; set;} Public Size tvsize {get; set;} }
Above, r.tablesize.length = 0; There will be an error: R cannot be modified. The value of tablesize because it is not a variable. Indeed, R.tablesize is just a copy of size, and it is not assigned to other variables, so r. Tablesize is temporary and is automatically recycled, and it is meaningless to assign values.
If you want to modify R. Tablesize, just put
Change to the following:
|
r.TableSize = new Size(){Length = 0, Width = 0}; |
The results of the operation are as follows:
It can be seen that changing a property of a struct type property of a struct type is not feasible because it is like the above R. Tablesize is just a copy, it is temporary, it will be automatically recycled. To change the struct type property of a struct type, you need to give R the same as above. Tablesize assigns a complete size instance.
Suppose you have a struct that has a property of a reference type?
Below, the class of struct type has reference type properties, Tablesize and tvsize, how can I modify the property value of its reference type through a class instance? Also, we define an event in the class size that triggers an event when the property of size is assigned a value that indicates that the property value of the size class has changed.
Class program { static void Main (string[] args) { var onesize = new Size () {Length = ten, Width = ten}; var twosize = onesize; Onesize.changed + = (s, e) = = Console.Write ("size changed ~ ~"); onesize.length = 0; Console.readkey (); } } public class Size { private int _length; private int _width; public event System.EventHandler Changed; public int Length { get {return _length;} Set { _length = value; OnChanged (); } } public int Width { get {return _width;} set {_width = value; OnChanged (); } } private void OnChanged () { if (Changed! = null) { Changed (this, new EventArgs ()); }}} public struct. {public Size tablesize {get; set;} Public Size tvsize {get; set;} }
Run, display: size has changed ~ ~
The modification to onesize.length actually modifies the onesize.length to point to the instance on the managed heap.
Iv. experience the difference between struct and class from the constructor function
struct type contains implicit default parameterless constructor
Class program { static void Main (string[] args) { var size = new Sizestruct (); Console.WriteLine ("Length={0},width={1}", size. Length, size. Width); Console.readkey (); } } public struct sizestruct {public int Length {get; set;} public int Width {get; set;} }
The results of the operation are as follows:
Why didn't we define the parameterless constructor for sizestruct without an error?
--because the struct type has an implicit parameterless constructor and assigns default values to all members, the default value of the Int Type property member is 0.
If you explicitly declare the default constructor for a struct, you will get an error.
public struct sizestruct{public sizestruct () {}//compilation error, hint struct cannot contain an explicit parameterless constructor public int Length {get; set;} public int Width {get; set;}}
But you can declare a struct with a parameter constructor
public struct sizestruct{public sizestruct (int a) {} public int Length {get; set;} public int Width {get; set;}}
in general, if no constructors are declared in a class , the system creates an parameterless constructor by default, and when When you define a constructor with parameters, the system does not create an parameterless constructor, and if you want to allow an argument-less construct, you must explicitly declare a
Class program { static void Main (string[] args) { var size = new Sizeclass (); Console.WriteLine ("Length={0},width={1}", size. Length, size. Width); Console.readkey (); } } public class Sizeclass {public int Length {get; set;} public int Width {get; set;} public sizeclass (int length, int width) { length = length; width = width; } }
Run, Error: Sizeclass constructor with no 0 parameters
V. Experience the difference between struct and class from assigning initial values to type members
If you assign an initial value directly to a field.
public struct sizestruct{public int _length = 10;}
Run, Error: there cannot be an instance field initializer in the structure. Unless the defined variable is a static or const type
If you assign an initial value to a field through a constructor function.
public struct sizestruct {public int _length; Public sizestruct () { _length = ten; } }
Run, Error: an explicit parameterless constructor cannot be included in the structure
It can be seen that assigning initial values to struct type members is not easy, and assigning initial values to class members, no problem.
When to use a struct and when to use class?
In most cases, it is recommended to use the class class, because either the assignment of a class, the passing of a parameter type, or the return of an instance of a class, the actual copy of the referenced address on the managed heap, is approximately 4 bytes, which is very helpful for performance improvements.
As a struct type, whether it is an assignment, passing as a parameter type, or returning a struct type instance, is a full copy that consumes space on the stack. According to the Microsoft's Value Type recommendations, it is recommended to use a struct in the following cases:
Less than 16 bytes
Bias to value, is simple data, not biased toward "object-oriented"
Hope value is not variable
C # details the difference between struct and class