Destructors, Finalizers, the ‘this’ Keyword, Properties and Indexers

Destructors, Finalizers, the ‘this’ Keyword, Properties and Indexers

Destructors

A destructor is the opposite to a constructor. It performs the cleanup steps before the object is cleaned up by the garbage collector. They can be defined in classes just as constructors can.

Constructor and Destructor

You can only have one finalizer per class as the function isn’t explicitly called itself.

To define a finalizer, you must create a method with the name ~ClassName where the class name is the name of your class.


                    class Car
{
	Car()
	{
		//On Create Constructor
	}

    ~Car()
    {
        // On teardown destructor
    }
}
                

The programmer is unable to decide when the finaliser is called as this is up to the garbage collector.

In a later tutorial, we will cover what it means for a class to be disposable.

Object Initializers

Using object initializers is an alternative approach to initialising member variables without having to define a constructor.

When you create a new object from a class using the new keyword, you can provide a list of initial values for the properties of that type in curly braces. This will tell the class you which to assign x with value y where x is the name of the member variable and y is a literal that satisfies the type of x.


                  using System;

public class Car
{
	public string carName;

	public Car()
	{
		//On Create Constructor
	}
}

public class Program
{
	public static void Main()
	{
		Car car1 = new Car {carName = "Lerrari"};
		Console.WriteLine(car1.carName);
	}
}
                

The This Keyword

The ‘this’ keyword will refer to the instance of the class. This is useful when you are defining a constructor for a class and wish to use the same identifiers for the parameters and member variables being assigned to. For example.


                    using System;

public class Car
{
	public string carName;

	public Car(string carName)
	{
		this.carName = carName;
	}
}

public class Program
{
	public static void Main()
	{
		Car car1 = new Car("Fast Car");
		Console.WriteLine(car1.carName);
	}
}
                

Properties Vs. Fields

At a first glance, properties look very similar to fields, especially whilst being accessed, however, properties have their own accessors that define how the property behaves when it is accessed or assigned.

To define a property, start by using the same syntax you would define a field, however, at the end of the definition, you will add definitions for get and set.


                    using System;

public class Car
{
    public int HorsePower
    {
        get
		{
			return horsePower;
		}
        set
        {
            if (value < 0)
                throw new ArgumentException("Can not be less than 0");
            horsePower = value;
        }
    }
    private int horsePower;
}


public class Program
{
	public static void Main()
	{
		Car car1 = new Car();
		car1.HorsePower = 4;
		Console.WriteLine(car1.HorsePower);
		car1.HorsePower = -4;
	}
}
                

The above is an example of auto-properties, this means that the compiler will implement default behaviour for the get and set methods on the property.

By default, the get method will just return the value and the set method will assign a value to the property if it satisfies its type.

private string _type;

public string Type
{
    get { return _type; }
    set { _type = value; }
}

You can also define your own logic for getting and setting properties. To do this, open curly braces after the get and set keywords and write your own code block as you would with a function


                   using System;

public class Car
{
    public int HorsePower
    {
        get
		{
			return horsePower;
		}
        set
        {
            if (value < 0)
                throw new ArgumentException("Can not be less than 0");
            horsePower = value;
        }
    }
    private int horsePower;
}


public class Program
{
	public static void Main()
	{
		Car car1 = new Car();
		car1.HorsePower = 4;
		Console.WriteLine(car1.HorsePower);
		car1.HorsePower = -4;
	}
}
                

Defining your own getters and setters is a great way to perform validation on assignments.

If you wish to assign a non-default value to a property, you can add ” = yourValue ” at the end, just like you would for a normal field. These are referred to as property initialisers. Read more about property initialisers here https://docs.microsoft.com/en-us/dotnet/csharp/.

Read and Write Only Properties

If a property defines only a get accessor then it can be described as read-only, the same is true for set accessors and write-only properties.

Indexers

Indexers enable access to indexed properties in an object outside of the class, this takes the form of specifying variables followed by an index in square brackets.

Here is an example of how you would implement this in the class:


                    using System;

public class Numbers
{
	int[] digits = {2,3,4,5,6,7};

	public int this [int numNumber]
	{
	get { return digits [numNumber]; }
	set { digits [numNumber] = value; }
	}
}

public class Program
{
	public static void Main()
	{
		Numbers num = new Numbers();
		Console.WriteLine(num[3]);
	}
}
                

We have already seen this behaviour when retrieving a char from a string, we add the location of the char in the string in square brackets.

One difference between indexers and properties is that it is not always possible to auto-generate get and set for indexers whereas this is always true for properties.

Constants

Constants can be defined within objects. At compile time the call to the constant will just be replaced with its value. To define a constant just use the ‘const’ keyword when defining a field.

Static Constructors

A static constructor is a type of constructor that is triggered when instantiating an object of that type or accessing a static member within that type. To define a static constructor, add the static keyword before the name of the constructor method.


                    using System;

class ExampleClass
{
    static readonly long baseline;

    static ExampleClass()
    {
		Console.WriteLine("Will only print once");
        baseline = DateTime.Now.Ticks;
    }
}

public class Program
{
	public static void Main()
	{
		ExampleClass ec = new ExampleClass();
		ExampleClass ec2 = new ExampleClass();
		ExampleClass ec3 = new ExampleClass();

	}
}