Generics vs. nullable value types
Tento problém sa mi vybavil Pri vlkovej správičke Čo Vás srdí na .NET .Povedzme teda, že máme zápis funkcie, ktorú chceme urobiť univerzálnou pre všetky nullable value types.
public static Func<int?, int?, bool> func1 = (x, y) => (x != null && y != null && x > y);
resp.
public delegate bool DelFunc<T>(T x, T y);
public static DelFunc<int?> funct11 = (x, y) => (x != null && y != null && x > y);
Tieto dva nápady samozrejme nie sú cestou:
public static bool func2<T>(T x, T y)
where T: Nullable<T>()
{
}
public static bool func3<T>(T x, T y)
where T: IComparable
{
return (x != null && y != null && x.CompareTo(y) > 0);
}
Prvý nepôjde skompilovať. Vynútiť si len nullable typy sa nedá. Druhý nezafunguje preto, že nullable typy neimplementujú IComparable - len ich ne-nullable verzie. Je to by design rozhodnutie. Porovnanie väčší/menší medzi null a hodnotou pri value types je z logického hľadiska nezmyslom - nemôžete porovnávať niečo, čo hodnotu nemá s niečim, čo ju má. Samozrejme v praxi pristupujeme aj ku tomuto "nezmyslu" a pre to porovnanie máme vlastnú interpretáciu. Čiže - musíme to vždy obkódovať.(niektoré jazyky umožňujú definovať logiku týchto porovnaní)
Existuje cesta? Povedzme že ...
public static bool func5<T>(T x, T y)
{
return (x != null && y != null && ((IComparable)x).CompareTo(y) > 0);
}
...ale je to naozaj dobrá cesta a prínos? Strácame type safety pre našu funkciu, čo malo byť zmyslom použitia genericsov, snáď len typová kontrola medzi oboma parametrami je malým prínosom. (IComparable) valueType boxuje a volanie CompareTo znova. Pri funkciách podobného typu nad value typeami je toto správanie maximálne nevhodné a podľa mňa čistejším ekvivalentom je potom táto verzia:
public static bool func6(IComparable x, IComparable y)
{
return (x != null && y != null && x.CompareTo(y) > 0);
}
Používateľovi funkcie je jasné, že ku boxovaniu príde(urobí ho on) a žiadna hlávka pri rozširovaní výrazov vo funkcii nezabudne na to, že boxing sa udeje pri každom pretypovaní na IComparable a teda nebude všade v jej tele robiť inline pretypovanie.