Click here to Skip to main content
15,885,216 members
Home / Discussions / C#
   

C#

 
GeneralRe: Starting a new project in C# Pin
FilipJ16-Feb-14 23:46
FilipJ16-Feb-14 23:46 
GeneralRe: Starting a new project in C# Pin
V.16-Feb-14 23:52
professionalV.16-Feb-14 23:52 
GeneralRe: Starting a new project in C# Pin
FilipJ17-Feb-14 0:02
FilipJ17-Feb-14 0:02 
AnswerRe: Starting a new project in C# Pin
Ravi Bhavnani17-Feb-14 7:49
professionalRavi Bhavnani17-Feb-14 7:49 
AnswerRe: Starting a new project in C# Pin
David C# Hobbyist.17-Feb-14 12:15
professionalDavid C# Hobbyist.17-Feb-14 12:15 
QuestionStruct vs Class? PinPopular
David C# Hobbyist.16-Feb-14 12:34
professionalDavid C# Hobbyist.16-Feb-14 12:34 
AnswerRe: Struct vs Class? Pin
Peter Leow16-Feb-14 13:29
professionalPeter Leow16-Feb-14 13:29 
AnswerRe: Struct vs Class? PinPopular
OriginalGriff16-Feb-14 21:29
mveOriginalGriff16-Feb-14 21:29 
That's a lot bigger question that you probably thought - it involves a lot of background before you can make a decision to use one or the other. So, let's have a little (hah - it was quite a lot) background...

Struct and Class have one huge difference: struct is a value type, class is a reference type. What that means is simple to describe, but harder to grasp the significance of.
So let's start by defining one of each:
C#
public class MyClass
    {
    public int I;
    public int J;
    }
public struct MyStruct
    {
    public int I;
    public int J;
    }
The two objects are identical, except that one is a class and one is a struct. Which means that if you declare an instance of each in your code then you get a reference and a value, but the code can look the same:
C#
public void UseClassAndStruct()
    {
    MyClass mc = new MyClass();
    mc.I = 1;
    mc.J = 2;
    MyStruct ms = new MyStruct();
    ms.I = 1;
    ms.J = 2;
    }
Or slightly different:
C#
public void UseClassAndStruct()
    {
    MyClass mc = new MyClass();
    mc.I = 1;
    mc.J = 2;
    MyStruct ms;
    ms.I = 1;
    ms.J = 2;
    }
Because you don't have to use the new keyword with structs. If you do, then the struct constructor is called, if you don't it isn't - simple as that. Unlike a class, the name of the struct is the struct itself, it is not a "pointer" to a instance.
And that's important, because that is the whole point: a struct is the object, and class is a reference to the object.

When you create a class variable:
C#
MyClass mc;
That allocates memory on the stack to hold a reference to a MyClass instance in future, it does not create an instance of MyClass, and you will have seen that before when you try to use any property or method of a class and you get a "Object reference not set to an instance of an object" exception and your program crashes. You have to explicitly create an instance of the class by using the new keyword:
C#
mc = new MyClass();
What this does is create a new instance of MyClass on the heap, and assign the reference to it to the variable mc. This is important, because the stack and the heap are different "types" of memory: the heap is a big "lump" or memory which is sorted out by the Garbage collector and all classes, methods and threads share it. The stack on the other hand is specific to a thread, and everything on the stack is discarded when you exit the method - which means that the mc variable is lost, but the data it references is not - if you have copied the reference to a variable outside the method, then you can still access it from the rest of your program.

What happens when you create a struct variable is different: the actual struct is immediately created on the stack and is available directly for the lifetime of the method. But it will be thrown away when the method exits. So you don't need the new unless you want to use a struct constructor to initialise your fields. You've used this a lot - probably without noticing:
C#
int i;
double j;
Point p;
All create value types.

So that's it? Not quite. Remember I said that "the name of the struct is the struct itself, it is not a 'pointer' to a instance"? That has a big effect, which again you probably have used a lot, and not really noticed. Think about this:
C#
int i = 3;
int j = i;
i = 4;
Console.WriteLine("{0}:{1}", i, j);
What does that produce?
Obviously, it produces a string "4:3" - anything else would make coding very, very difficult!
But...what if we do that with reference types?
C#
MyClass i = new MyClass();
i.I = 3;
MyClass j = i;
i.I = 4;
Console.WriteLine("{0},{1}", i.I, j.I);

This time, it prints "4:4" because i and j are references to the same instance in memory, instead of being separate, self contained value types.
The same thing happens if we use our structs:
C#
MyStruct i = new MyStruct();
i.I = 3;
MyStruct j = i;
i.I = 4;
Console.WriteLine("{0},{1}", i.I, j.I);
This time, we get "4:3" again.
When you assign a reference type variable to another reference type variable, it copies the reference, not the object. When you assign a value type variable to another value type, it copies the content of the object, not the reference to the object.

So when you call a method with a reference type, a copy of the reference is passed, and any changes you make affect the one and only object.
If you call it with a value type such as a struct, a copy of the value is passed, and any changes you make will not be reflected back:
C#
public void ClassMod(MyClass mc)
    {
    mc.I += 100;
    Console.WriteLine(mc.I);
    }
public void StructMod(MyStruct ms)
    {
    ms.I += 100;
    Console.WriteLine(ms.I);
    }

C#
MyClass mc = new MyClass();
mc.I = 3;
ClassMod(mc);
MyStruct ms = new MyStruct();
ms.I = 3;
StructMod(ms);
Console.WriteLine("{0},{1}", mc.I, ms.I);
What do we get?
103
103
103,3
Within the method, everything works the same.
But outside...the changes we made to the struct inside the method affect the copy, not the original.

So what does this do for us in practice? What are the advantages of a struct over a class?

Speed, under certain conditions. they can be a lot slower to use if you aren't careful: if you have a large struct, just calling a method and passing it as a parameter means it must be copied which takes time. But...if they are small (16 bytes or less) and you use a lot of them then they can be a lot faster than a reference type, because the Heap is not involved. Every time you create a reference type instance, the heap must be looked at, a suitable size bit of memory found and allocated and a reference to that returned. This takes time - quite a lot of it! A value type in contrast takes almost no work to allocate: copy the stack pointer, add the size of the struct to it for next time is pretty much all you have to do (and you have to do that for reference types as well so you have somewhere to store the reference to the heap memory!)

There is one bit I missed out here: boxing. This was deliberate, because it's a bit difficult to explain...

What happens when you have a value type and you want to store it with other types in a mixed List (for example)?
C#
List<object> mixedList = new List<object>();

You can add any object perfectly happily:
C#
mixedList.Add("Hello there");
mixedList.Add(Form1);
because object is a class that all reference types derive from. But...what happens here:
C#
mixedList.Add(12);
Um...12 is an int which is a value type, and so isn't derived from object...is it?
Yes, it is: all value types derive from a special class called System.ValueType, which derives from object and what happens is that the value is "boxed" - a reference is created on the heap to hold the value type and it is copied there, and the reference to the boxed value is added to the list. When you cast it back to the original struct it is "unboxed" and you have a value type again. This is not a fast process and is one of the reasons you don't use structs for everything!

So, to copy from MSDN[^]:

"CONSIDER defining a struct instead of a class if instances of the type are small and commonly short-lived or are commonly embedded in other objects.

AVOID defining a struct unless the type has all of the following characteristics:
It logically represents a single value, similar to primitive types (int, double, etc.).
It has an instance size under 16 bytes.
It is immutable.
It will not have to be boxed frequently."


The immutable bit is not enforced - it is just a recommendation, otherwise integers, doubles, and so forth wouldn't work! Laugh | :laugh:
But...it's a very good idea to make structs immutable: it causes a lot less confusion.
The Point struct does it by making the X and Y Setters private, so that it is obvious that all Points are different instances and that you don't move the original when you change a copy.

Phew! I need a coffee!
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)

GeneralRe: Struct vs Class? Pin
Nicholas Marty16-Feb-14 21:55
professionalNicholas Marty16-Feb-14 21:55 
GeneralRe: Struct vs Class? Pin
harold aptroot16-Feb-14 22:02
harold aptroot16-Feb-14 22:02 
GeneralRe: Struct vs Class? Pin
OriginalGriff16-Feb-14 22:17
mveOriginalGriff16-Feb-14 22:17 
GeneralRe: Struct vs Class? Pin
OriginalGriff16-Feb-14 22:26
mveOriginalGriff16-Feb-14 22:26 
GeneralRe: Struct vs Class? Pin
harold aptroot16-Feb-14 22:59
harold aptroot16-Feb-14 22:59 
GeneralRe: Struct vs Class? Pin
OriginalGriff17-Feb-14 0:06
mveOriginalGriff17-Feb-14 0:06 
GeneralRe: Struct vs Class? Pin
harold aptroot17-Feb-14 0:16
harold aptroot17-Feb-14 0:16 
GeneralRe: Struct vs Class? Pin
jschell17-Feb-14 12:07
jschell17-Feb-14 12:07 
GeneralRe: Struct vs Class? Pin
BillWoodruff17-Feb-14 1:41
professionalBillWoodruff17-Feb-14 1:41 
AnswerStruct vs Class? (Off Topic) Pin
OriginalGriff17-Feb-14 0:41
mveOriginalGriff17-Feb-14 0:41 
GeneralRe: Struct vs Class? (Off Topic) Pin
David C# Hobbyist.17-Feb-14 11:12
professionalDavid C# Hobbyist.17-Feb-14 11:12 
GeneralRe: Struct vs Class? (Off Topic) Pin
OriginalGriff17-Feb-14 11:24
mveOriginalGriff17-Feb-14 11:24 
GeneralRe: Struct vs Class? (Off Topic) Pin
OriginalGriff23-Feb-14 0:29
mveOriginalGriff23-Feb-14 0:29 
GeneralRe: Struct vs Class? (Off Topic) Pin
David C# Hobbyist.23-Feb-14 4:42
professionalDavid C# Hobbyist.23-Feb-14 4:42 
GeneralRe: Struct vs Class? (Off Topic) Pin
OriginalGriff23-Feb-14 4:57
mveOriginalGriff23-Feb-14 4:57 
QuestionInterface for Authorization Custom Inteface c# Winforms .net 4.0 Pin
Member 1050351416-Feb-14 12:10
Member 1050351416-Feb-14 12:10 
AnswerRe: Interface for Authorization Custom Inteface c# Winforms .net 4.0 Pin
Eddy Vluggen17-Feb-14 0:29
professionalEddy Vluggen17-Feb-14 0:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.