Reputation: 50120
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
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