I want to convert a string to a given generic type T. It may be either basic type or string (e.g. int or string), or an array of a basic types or strings (e.g. int[] or string[]). I have the following function:
T Str2Val<T>(string str)
{
return (T)Convert.ChangeType(str, typeof(T));
}
It works well for basic types. But it fails for T being an array E[] and str being a comma-separated list of values.
I can easily check whether T is an array with typeof(T).IsArray. Then I have two solutions: parse an array in the same function with a scalar, like the following:
if (!typeof(T).IsArray)
{
return (T)Convert.ChangeType(str, typeof(T));
}
else
{
// Handle an array
}
or implement two overloaded functions: one for generic T and second for generic E[]. However, both of solutions fail. I cannot use any array-specific code in the else-clause since it must be compatible with a scalar. And C# cannot pick proper overload with E[] when T is actually an array.
What should I do?
I would create some listing of custom parsers that you register then later leverage since you seem to be wanting to use custom rules anyway:
During your application initialization, you would register the types you intend to use later in your application (I’m guessing this is known since you’re using generics):
Finally, you can call it simply:
Now, this is a pretty simple implementation. You may wish to extend it so instead of using type
Func<string, T>it might use anIStringParserinterface and you can provide deeper implementations of the parsing if necessary. Furthermore, you may wish to make it thread safe (unless you’re sure that won’t be an issue, or if you are sure your registration on startup is before any usages)EDIT: If you really, really, really want it all in one function just accounting for your comma delimited array, then you can use this:
But this feels so wrong. There must be a better way and to avoid the double generic input in Alexander’s answer, but there you go.