The automatic mechanism cannot be deterministic, because it must rely on on the GC to discover whether the object is referenced or not. At times this behaviour is a show stopper. because temporary “resource leaks” or holding a shared resource locked for slightly longer than necessary might be unacceptable in an application. At others, it’s perfectly acceptable. I will focus on the scenarios where it is.
Any type can override protected Finilize method defined by System.Object to indicate that it required automatic finalisation. However the C# syntax for requesting automatic finalisation on a class A is to implement method ~A(). This method is called finiliser a must be invoked when the object is destroyed.
Incidentally any type can have a finalizer, even the value types. However the finalizer on the value type object will never be invoked.