Practical differences between classes and structures in .net (not conceptual)?

Whenever I tried to find the differences between classes and structures in C # or .net, I ended up a conceptual review of two things, such as a value type or a reference type, where variables are distributed, etc. But I need practical differences. I found some that are similar to the behavior of an assignment operator, with constructors, etc. Can someone provide some more practical differences that would be directly useful in coding? Like something that works with one, but not with another or the same operation, showing a different behavior. And some common mistakes regarding these two.

Also, please suggest to consider using a framework instead of a class. And where structures should not be used.

Edit: Do I need to call the constructor explicitly or simply declare a variable of type struct? (Should I ask a new question?)

+6
c # struct class
source share
8 answers

OK, here are a few specific practical differences:

  • A variable can be null if its class , but never null if its struct .

  • default(T) null for the class , but a value (consisting of many binary zeros) is actually created for the structure.

  • Can a struct be valid with Nullable<T> or T? . class cannot be used for T in Nullable<T> or T? .

  • A struct always has an open default constructor (a constructor with zero parameters). A programmer cannot override this constructor with a special implementation - it is basically "set in stone." the class allows the programmer to not have a default constructor (or private).

  • Fields in a class can have default values โ€‹โ€‹declared on them. In the structure they cannot.

  • A class can inherit from another class, but a struct cannot be declared to receive anything (it implicitly comes from System.ValueType ).

  • It makes sense to use the class in object.ReferenceEquals() , but using the struct variable will always give false.

  • It makes sense to use the class in the lock() statement, but using the struct variable will result in a very subtle failure. The code will not be blocked.

  • In a 32-bit system, theoretically you can allocate an array of 536,870,912 class references, but for the structure you need to take the size of the structure into account, since you select the actual instances.

+10
source share

Structures in the container can be changed only if the container is an inline array:

 struct Point { public int x, y; void Move(int dx, int dy) { x += dx; y += dy; } } ... Point[] points = getPointsArray(); points[0].Move(10, 0) = 10; // points[0].x is now 10 higher. List<Point> points = getPointsList(); points[0].Move(10, 0); // No error, but points[0].x hasn't changed. 

For this reason, I strongly advocate for immutable structures:

 Point Move(int dx, int dy) { return new Point(x + dx, y + dy); } ... points[0] = points[0].Move(10, 0); // Always works. 

General observation: classes are usually better. Structures are superior when you want to store small, conceptually atomic data structures such as Point, Complex (number), Rational, etc.

+2
source share

structs, since they are value types, are copied when assigned; if you create your own structure, you must make it immutable, see Why are volatile structures evil?

+1
source share

Sometimes you donโ€™t need what you pass in order to be volatile, and since the mutable structure can just be pure evil, I avoid creating one :) Here is an example of a situation:

class Version:

 class AccountInfo { public string OwnerName { get; set; } public string AccountNumber { get; set; } } 

struct Version:

 struct AccountInfo { public string OwnerName; public string AccountNumber; } 

Now you can call this method:

 public bool TransferMoney(AccountInfo from, AccountInfo to, decimal amount) { if(!IsAuthorized(from)) return false; //Transfer money } 

A struct is a type value , that is, a copy is passed to the method. The version of the class means that the link is passed to this method, you do not want, for example, the account number to be changed after the authorization transfer, you do not want anything to change in this operation ... you want the type of the immutable value, This raises another question about why volatile structures are evil ... any operation in which you do not want something affected by a change in the reference object to be a practical place where the struct can fit better.

The above example may be a little silly, but the point is any sensitive operation in which the data transmitted in the data should not change in another thread or in any way would actually be the place where you look at the transmission by value.

+1
source share

If they are allocated (heap versus stack), you donโ€™t really need it when you use them (not that you do not pay attention to it - you must study the differences and understand them by all means).

But the most important practical difference that you will encounter the first time you decide to replace your class with a structure is that the structures are passed by value and the instances of the instances are passed by reference.

This means that when you pass the structure to the method, a copy of its properties is created (a shallow copy), and your method actually gets a different copy than the one you had outside the method. When you pass an instance of a class, only a reference to the same place in memory is passed to the method, and your method then processes the exact same data.

For example, if you have a structure named MyStruct and a class named MyClass , and you pass them to this method:

  void DoSomething(MyStruct str, MyClass cls) { // this will change the copy of str, but changes // will not be made to the outside struct str.Something = str.Something + 1; // this will change the actual class outside // the method, because cls points to the // same instance in memory cls.Something = cls.Something + 1; } 

when the method ends, the property of your class will be increased, but your struct property will remain unchanged, because the str variable inside the DoSomething method does not have a point value in the same place in memory.

0
source share

A particularly important practical difference is that structures are value types, while classes are reference types. This has several consequences.

First of all, structures are copied at assignment. These two blocks of code will have different results (note that usually you should not use public fields or mutable structures, I only do this for demo purposes):

 struct X { public int ID; public string Name; } X x1 = new X { ID = 1, Name = "Foo" }; X x2 = x1; x2.Name = "Bar"; Console.WriteLine(x1.Name); // Will print "Foo" class Y { public int ID; public string Name; } Y y1 = new Y { ID = 2, Name = "Bar" }; Y y2 = y1; y2.Name = "Baz"; Console.WriteLine(y1.Name); // Will print "Baz" 

X and Y are exactly the same, except that X is a struct . The results of this are different, because every time we assign X , a copy is made, and if we change the copy, we do not change the original. On the other hand, when we assign contents from y1 to y2 , all we have done is copy the link; both y1 and y2 are physically the same object in memory.

The second consequence of structures that are value types is a common limitation. If you want to pass value types, the name of the constraint will be literally "struct" or "class":

 public class MyGeneric<T> where T : struct { ... } 

The above will allow you to create MyGeneric<int> or MyGeneric<X> , but not MyGeneric<Y> . On the other hand, if we change it to where T : struct , we are no longer allowed to create either of the first two, but MyGeneric<Y> is fine.

Last but not least, you need to use structures when writing interop, because with structures you can guarantee a specific layout in memory.

0
source share

The provided Tejs link ( http://www.jaggersoft.com/pubs/StructsVsClasses.htm ) is a good explanation (although it is a bit outdated, especially for explaining the events).

The most important practical difference is that the struct is a value type, that is, it is passed by value, not by reference. This really means that when a struct is passed as an argument, it is actually passed in as a copy. As a result, operations on one instance of a structure do not affect other instances.

Consider the following code:

 struct NumberStruct { public int Value; } class NumberClass { public int Value = 0; } class Test { static void Main() { NumberStruct ns1 = new NumberStruct(); NumberStruct ns2 = ns1; ns2.Value = 42; NumberClass nc1 = new NumberClass(); NumberClass nc2 = nc1; nc2.Value = 42; Console.WriteLine("Struct: {0}, {1}", ns1.Value, ns2.Value); Console.WriteLine("Class: {0}, {1}", nc1.Value, nc2.Value); } } 

Since both ns1 and ns2 are of type NumberStruct , each of them has its own storage, so assigning ns2.Number does not affect the value of ns1.Number . However, since nc1 and nc2 are reference types, the purpose of nc2.Number affects the value of nc1.Number because they both contain the same reference.

[Disclaimer: the above code and text taken from Sams Teach Yourself Visual C # 2010 at 24 hours ]

In addition, as others have already indicated, structures must always be unchanged. (Yes, in this example, the structure is mutable, but it was supposed to illustrate the point.) Part of this means that structures should not contain public fields.

Since structs are value types, you cannot inherit a structure. You also cannot get the structure from the base class. (However, a structure can implement interfaces.)

The structure is also not allowed to have an explicitly declared open (without parameters) counter-constructor. Any additional constructors that you declare must fully initialize all the fields of the structure. Structures also cannot have an explicitly declared destructor.

Since structs are value types, they should not implement IDisposable and should not contain unmanaged code.

0
source share

Here's an interesting link: http://www.jaggersoft.com/pubs/StructsVsClasses.htm

For the most part, however, there is no reason to use structures when classes offer the developer much more.

-one
source share

All Articles