pm100
pm100

Reputation: 50120

Invoking method depending on type in generic method

Generic function that gets a string and parses it to the type given in T. I can make it all work except the returns. I have a bool and want to make it into a T? where T is bool.

public T? F<T>() where T : struct
{
   var s= GetAString();
   if(s==null) return null;
   if(typeof(T) == typeof(bool))
   {
      var b = bool.Parse(s);
      return ??
   } 
   if(typeof(T) == typeof(int))
   {
      var i = int.Parse(s);
      return ??
   } 
    ...
}

return b doesn't work

return (T?)b doesn't work

return new T?(b)

Upvotes: 2

Views: 94

Answers (1)

p.s.w.g
p.s.w.g

Reputation: 149010

It's certainly not pretty, but double-casting to object then to T? (or in this case triple-casting, since b is actually a bool and not a bool?) would work:

if(typeof(T) == typeof(bool))
{
  var b = bool.Parse(s);
  return (T?)(object)(bool?)b;
} 
if(typeof(T) == typeof(int))
{
  var i = int.Parse(s);
  return (T?)(object)(int?)i;
} 

However, I would generally avoid writing this kind of code. It kind of defeats the purpose of using generics in the first place. After all, if you have to write different strategies for every type parameter you might accept, it's not a generic solution.


An alternative solution would be to create 'parser' classes like this:

public interface IParser {
    object Parse(string s);
}

public class BoolParser : IParser {
    public object Parse(string s) {
        return bool.Parse(s);
    }
}

public class IntParser : IParser {
    public object Parse(string s) {
        return int.Parse(s);
    }
}

And register them statically in a dictionary like this:

private static Dictionary<Type, IParser> parsers = new Dictionary<Type, IParser>();
public static void Register<TResult, TParser>() 
    where TResult : struct 
    where TParser : IParser, new() 
{
    parsers.Add(typeof(TResult), new TParser());
}

...

Register<bool, BoolParser>();
Register<int, IntParser>();

And now you can write your F method like this:

public T? F<T>() where T : struct
{
   var s = GetAString();
   if (s == null) 
       return null;
   var t = typeof(T);
   if (parsers.ContainsKey(t))
       return (T)parsers[t].Parse(s);
   else
       throw new Exception("Specified type is not supported");
}

Upvotes: 3

Related Questions