·
Structs
are value types and classes are reference types.
·
Value
type instances are allocated on the stack. Reference type instances are
allocated on the heap.
·
In
.Net the struct and class declarations differentiate between reference types and
value types.
·
When
you pass around a reference type there is only one actually stored. All the code
that accesses the instance is accessing the same
one.
· When
you pass around a value type each one is a copy. All the code is working on its
own copy.
This
can be shown with an example:
struct
MyStruct
{
string MyProperty { get; set;
}
}
void
ChangeMyStruct(MyStruct input)
{
input.MyProperty = "new
value";
}
//
Create value type
MyStruct
testStruct = new MyStruct { MyProperty = "initial value" };
ChangeMyStruct(testStruct);
//
Value of testStruct.MyProperty is still "initial
value"
//
the method changed a new copy of the
structure.
For
a class this would be different:
class
MyClass
{
string MyProperty { get; set;
}
}
void
ChangeMyClass(MyClass input)
{
input.MyProperty = "new
value";
}
//
Create reference type
MyClass
testClass = new MyClass { MyProperty = "initial value"
};
ChangeMyClass(testClass);
//
Value of testClass.MyProperty is now "new value"
//
the method changed the instance passed.
·
Classes
can be nothing - the reference can point to a
null.
·
Structs
are the actual value - they can be empty but never null. For this reason structs
always have a default constructor with no
parameters.
·
The
struct can't use the protected or protected internal modifier. The class can use
all the access modifiers.
·
A
struct always has a built-in public default constructor. This means that a
struct is always instantiable whereas a class might not be since all its
constructors could be private.
class
NonInstantiable
{
private NonInstantiable() //
ok
{
}
}
struct
Direct
{
private Direct() // compile-time
error
{
}
}
·
A
structs static constructor is not triggered by calling the structs default
constructor. It is for a class.
struct
Direct
{
//static
constructor not called when new instance is created by //statement i.e. new Direct()
static
Direct()
{
Console.WriteLine("This is not
written");
}
}
static void
Main()
{
//static constructor not called when new
instance is created
Direct local = new
Direct();
}
class
Direct
{
//static
constructor called when new instance is created by statement i.e. new Direct()
static Direct()
{
Console.WriteLine("This is
written");
}
}
static void
Main()
{
//static constructor called when new instance
is created
Direct local = new
Direct();
}
·
A
struct instance cannot be null. A class instance can be
null.
·
A
struct type cannot use the as operator. A class can use as
operator.
SampleStruct
obj2 = obj1 as SampleStruct; //compile time error
SampleClass obj2 = obj1 as SampleClass;
//Compiles OK
·
A
struct cannot have a destructor but a class can have a destructor. A destructor
is just an override of object.Finalize in disguise, and structs, being value
types, are not subject to garabge collection.
~SampleStruct()
//compile time error
~SampleClass() //Compiles
OK
·
You
can initialize fields in a class at their point of declaration. For
example:
class
Indirect
{
//...
private int field = 42;
}
You
can't do this for fields in a struct. For
example:
struct
Direct
{
//...
private int field = 42; // compile-time
error
}
· Classes
inherit Object.Equals which implements identity equality whereas structs inherit
ValueType.Equals which implements value equality.
· A struct is implicitly sealed, a class isn't.
· A struct can't be abstract, a class can.
· A struct can't extend another class, a class can.
· A struct can't declare protected members (e.g. fields, nested types) a class
can.
· A struct can't declare abstract function members, an abstract class
can.
· A struct can't declare virtual function members, a class
can.
· A struct can't declare sealed function members, a class
can.
· A struct can't declare override function members, a class can. The one exception
to this rule is that a struct can override the virtual methods of
System.Object, Equals(), and
GetHashCode(), and ToString().