Imagine when you have a generic type, such as the following class, and you need to get the hash for K, so that it can be mapped to V.
TMapEntry<K, V>
Since K is not constrained to a class, you can't do much.
However, if you look at the System.Generics.Defaults unit, you'll see that there is a way to do so. In there, an interface is declared:
IEqualityComparer = interface function Equals(const Left, Right: T): Boolean; function GetHashCode(const Value: T):Integer; end;
So, all you have to do is either implement, or get the IEqualityComparer for K. To do so, looking into the System.Generics.Defaults unit, one finds the TEqualityComparer<T> class, which can construct a default instance of IEqualityComparer<T> by calling the Default method.
So, to obtain the hash code for K, first, construct IEqualityComparer<K>. Here's how:
var LComparer: IEqualityComparer<K>; LHashCode: Integer; ... ... LComparer := TEqualityComparer<K>.Default; LHashCode := LComparer.GetHashCode(K);
There's no need to dispose LComparer, since it's an interface, and the class backing it will be disposed of automatically, when the scope of the declaration is exited.
In 2017, with the release of Delphi 10.2 Tokyo, Embarcadero introduced a specialized implementation of the Observer pattern into the System.Classes unit. While it has been in the wild for 9 years, it remains a "hidden" architecture for many, primarily because it serves as the invisible engine behind LiveBindings. Other than live bindings, you can also use the Observer pattern as a way to update component settings to the Windows registry, an .ini file, or persist it elsewhere.
System.Classes