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.