Class and Struct

C# type hierarchy

Let’s spend few minute in understanding Type hierarchy. System.Object (alias object) is the base class for all types. Reference types (e.g. class, interface, string, dynamic etc) are directly inherited from object. System.ValueType is the base class for all value types (struct & enum).

So both reference and value types are internally inherited from System.Object.

Following code should compile and run.
						
  1. private static void Main ( string[] args)
  2. {
  3. int a = 3;
  4. object objA = (object)a;
  5. Console.WriteLine( "Type:{0}", objA.GetType());
  6. }
Result:
Type: System.Int32

We cannot directly inherit from System.ValueType.we need to use struct and enum to create a ValueType object. But ValueType can be used as function parameter when we want to restrict the input type to struct or enum.

					
  1. public class TestClass
  2. {
  3. public void Run()
  4. {
  5. ShowType(3); //int
  6. ShowType(3.0); //double
  7. ShowType(3.0f); //float
  8. ShowType(3L); //long
  9. ShowType(DateTime.Now); //datetime
  10. ShowType(DayOfWeek.Sunday); //enum
  11. //ShowType(string.Empty); // Won't compile
  12. }
  13. public static void ShowType(ValueType value)
  14. {
  15. Console.WriteLine(value.GetType());
  16. }
  17. }

Result:

  • System.Int32
  • System.Double
  • System.Single
  • System.Int64
  • System.DateTime
  • System.DayOfWeek

What’s Common in Class and Struct.

Classes and structs are two of the basic constructs of the common type system in the .NET Framework. Each is essentially a data structure that encapsulates a set of data and behaviors that belong together as a logical unit. The data and behaviors are the members of the class or struct, and they include its methods, properties, and events.

  1. Both class and struct can implement interfaces. Interface defines a set of rules/functionalities. Both class & struct can implement the rules/functionalities.
    1. public class TestInheritance
    2. {
    3. public static void Run()
    4. {
    5. ChildStruct cs = new ChildStruct();
    6. cs.SayHello();
    7. ChildClass cc = new ChildClass();
    8. cc.SayHello();
    9. }
    10. }
    11. interface IHello
    12. {
    13. void SayHello();
    14. }
    15. struct ChildStruct : IHello
    16. {
    17. public void SayHello()
    18. {
    19. Console.WriteLine( "Hello Struct");
    20. }
    21. }
    22. class ChildClass : IHello
    23. {
    24. public void SayHello()
    25. {
    26. Console.WriteLine( "Hello Class");
    27. }
    28. }
  2. Both can define members/fields or properties with Access Specifiers.
  3. Both supports Generic types.
    					
    1. public class TestGenerics
    2. {
    3. public static void Run()
    4. {
    5. <> stc = new<>();
    6. Console.WriteLine(stc.Type());
    7. <> sts = new<>();
    8. Console.WriteLine(sts.Type());
    9. }
    10. }
    11. public class<>
    12. {
    13. public string Type()
    14. {
    15. return typeof(T).Name;
    16. }
    17. }
    18. struct TStruct { }
    19. class TClass { }
    Result:
    • TClass
    • TStruct
  4. Both supports partial and nested types.
  5. Both supports Extension Methods.
  6. Application entry point (Main method) can be placed with in a class or struct.

How class and struct differ?

  1. Class instance holds reference to memory where data is stored. Whereas struct instance holds the data.So structs are passed by value but classes are passed by reference.
  2. Structs doesn’t support INHERITANCE. So structs cannot be declared abstract or sealed.
  3. Structs cannot be declared as static, however it can have static properties.
  4. Structs cannot declare parameter less constructor, however they can have constructor with parameters.
  5. Sturcts can be initialized without new operator. Constructor will be called only when initialized with new operator.
    					
    1. struct MyStruct
    2. {
    3. public MyStruct ( int a, string b)
    4. : this()
    5. {
    6. A = a;
    7. B = b;
    8. }
    9. public int A { get; set; }
    10. public string B { get; set; }
    11. }
    12. public class TestClass
    13. {
    14. MyStruct strt;
    15. public void AnotherTest()
    16. {
    17. strt.A = 123;
    18. strt.B = "abc";
    19. Console.WriteLine(strt.A);
    20. Console.WriteLine(strt.B);
    21. strt = new MyStruct();
    22. Console.WriteLine(strt.A);
    23. Console.WriteLine(strt.B);
    24. strt = new MyStruct(456, "pqr");
    25. Console.WriteLine(strt.A);
    26. Console.WriteLine(strt.B);
    27. }
    28. }
    Result:
    • 123
    • abc
    • 0
    • 456
    • pqr

Memory: Stack or Heap

Stack is a FILO (First In Last Out) data structure and closely managed by CPU. Heap is a free floating memory which is not managed by CPU. It is the responsibility for programmers. Fortunately .Net framework does this for us when we write managed code.Struct instances are stored in Stack memory however class instances are stored in heap memory. Using struct can give performance gains as we will work on instance instead a reference of instance.

When to use

Few points need to be considered before choosing structs over class.

  1. ValueTypes when boxed are assigned to a reference type (implicit/ explicit conversion) and when unboxed assigned to value type. So large number of boxing/unboxing adversely affect performance.
  2. Structs are passed by value. If struct is passed to a method, creates a copy of existing instance. So for large instances reference types are preferred then value types

So, structs are preferred when,

  • Instances of the type are small and commonly short-lived or are commonly embedded in other objects.
  • 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