0

Is there any way to emulate C++ template specialization using C# generics and/or rtti?

Consider following functions, implementation details do not matter:

public void DrawShape(Shape sh, Brush brush1, ...) { ... }
public void DrawShape(Shape sh, Func<Brush> brushGetter1, ...) { ... }

The shape can use many brushes, and any combination between getter delegate and raw parameter. It would be unwise to create a separate function for each combination, so my first solution was to unify getter/raw param to a single structure/class that could handle both. However, this obscures the API as now I have to wrap every param with a new Wrapper(...) or a static factory method Wrp.Static(...)/.Dynamic(...). Note that there is a single, finite amount of brushes, so writing code for each is fine, however writing code for 2^N params is not preferable.

In C++ I would use the implicit constructor Wrapper(const T& t) to automatically wrap arguments to a single wrapper interface. Is there any way to solve this using generics perhaps? I know there is a fundamental difference between templates (code generation on demand) and generics (code able to handle many types), but wouldn't I be able to catch different argument types at runtime using reflection/rtti? My issue here is that I'd prefer some compile type checking and not passing object's, hoping that they actually match one of two types I expect in implementation of the wrapper.

I am looking for something that would behave like:

public void DrawShape<TBrush1, ...>(Shape sh, TBrush1 brush1, ...) 
    : where TBrush1 : Brush|Func<Brush>, ... { ... }

The main assumption here is that automatic type deduction would take place and allow me to skip the generic params. Please note that this is not a valid C# code and the imaginary | operator is the feature I'm looking for - matching two types to a single argument, possibly without any explicit user input.

noisy cat
  • 2,865
  • 5
  • 33
  • 51
  • Can you show the original/equivalent code in C++? – Thomas Weller Apr 23 '21 at 15:46
  • a pair of constructors like: ```Wrapper(const Brush& b);``` and ```Wrapper(const BrushGetter& bg);``` Then I can have ```DrawShape(const Shape& s, Wrapper w1, ...);``` – noisy cat Apr 23 '21 at 15:55
  • 2
    The equivalent to an implicit constructor is `operator implicit`. C# has no equivalent to template specialization. Generics are nowhere near as powerful as templates (although the fact that generics can be composed at runtime enables some very cool uses as well as much faster compilation, that just isn't the same as having non-type template arguments and specializations) – Ben Voigt Apr 23 '21 at 16:50
  • @BenVoigt I have no idea how could I miss this feature. I was pretty sure this can be only done explicitly, and the other way around (so Brush would implement conversion, which is not quite same as it really is). Okay, this pretty much solves my issue - if you could post this as an answer I might accept it so the question is closed. Thanks. – noisy cat Apr 24 '21 at 00:19
  • @noisycat: It might be an answer to your problem but it isn't an answer to the question you actually asked. You might change the title and reword the beginning of your question to have both alternatives (generics and wrappers) and then lead into the existing content on what you tried with generics. And then I can write the answer that the implicit conversion to wrapper is simple and works. – Ben Voigt Apr 26 '21 at 18:52

0 Answers0