Botton line: this can be done but requires disproportionate amounts of overhead. So it's completely impractical.
In the end, I resolved this by adding two overloaded methods without either argument.
According to C# specification v.3.0, §B.2.7, type constraints can be put on single methods as well. But, these methods need to have the types the constraints are put on as their own type parameters. So, I was able to do the trick like this:
protected void Dissociate<KP,LP>(KP? primaryKey, LP? subKey)
where KP:struct,K where LP:struct,L
{
primaryToSubkeyMapping.Remove(primaryKey??subDictionary[subKey.Value]);
subDictionary.Remove(subKey??primaryToSubkeyMapping[primaryKey.Value]);
}
But, now, I need to make four implementations for each combination of class
and struct
! And when I try to call them inside typeof(K).IsValueType
-like checks, the compiler fails to get it as a hint for overload resolution and yields the corresponding error. Naming them differently only goes one step further: the compiler is not convinced that only one of them will ever be called in any concrete implementation and still fails argument type checks. Now, there are two choices:
Call the related implementation through reflection. Getting the generic type parameter objects for GetMethod()
, then making a concrete method is gonna be a PINA - even if I simplify the former step by naming the four implementations differently;
Make four derived classes, each with a different name. This would screw up the class hierarchy.
- To resolve the hierarchy schism (at the cost of Liskov's principle), I can make another class that would delegate to one of them. In the corresponding code, I'll face the same type check problems again and will have to resolve them in the same manner as the previous item.
In brief, this way is completely unusable.