1

There are several functions which are almost the same (or the different part can easily to be implemented using type parameters). However, one difference each functions call different TryParse() functions.

void Fun1<T>(T p) where T : IBase // simplified
{ ...... 
    int x;
    if(int.TryParse(p.S, out x)) { .... }
}

void Fun1<T>(T p) where T : IBase
{ ...... 
    decimal x;
    if(decimal.TryParse(p.S, out x)) { .... }
}
......

How to create a generic method with a type parameter for int, decimal, double, short, ... (any type with method TryParse) for these functions?

ca9163d9
  • 27,283
  • 64
  • 210
  • 413

1 Answers1

3

This is one of those painful realities about constraint based generics in C#, you want to say that you will support any type that has a method TryParse of the desired signature but there is no such interface on the types you are using and no way to add such an interface onto them. You also have the added pain of needing to generically refer to a static method so to speak (since TryParse is a static method on the type) which is unfortunate.

What you really need here are C++ style templates which are available as managed templates in C++\CLI, but even that is slightly complicated because of making the static method call "generic". C++ template wizardry would get you there, but to save the drama, you can just use a good old T4 template to mimic what C++ would have had to do minus any extra template metaprogramming.

I created the following T4 template:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>

<#
    List<string> types = new List<string>() { "decimal", "int" };
    foreach (string t in types)
    {
#>
void Fun1(<#=t#> p) // simplified
{ //...... 
    <#=t#> x;
    if(<#=t#>.TryParse(p.S, out x)) { /*....*/ }
}

<#
}
#>

And that gave me the following output:

void Fun1(decimal p) // simplified
{ //...... 
    decimal x;
    if(decimal.TryParse(p.S, out x)) { /*....*/ }
}

void Fun1(int p) // simplified
{ //...... 
    int x;
    if(int.TryParse(p.S, out x)) { /*....*/ }
}

Which I think is roughly what you are looking for. I think in your case this is the simplest solution to avoid all of the reflection drama or dropping down into managed templates (still with likely a splash of reflection for the static method call) or even further down into C++. The T4 approach outputs a .cs file so the compiler will warn you about problems just like it would for any other .cs file in your project.

Chiune Sugihara
  • 1,179
  • 1
  • 7
  • 14