I have a few methods like this:
public string GetStringValue(string field) { /* ... */ }
public int GetIntValue(string field) { /* ... */ }
Now I want to write a generic method which has the following signature:
public bool CopyValue<T>(string field, Action<T> copyAction)
Depending on the type parameter I want to invoke copyAction
with the return value of one of the non-generic methods. My first try was
public bool CopyValue<T>(string field, Action<T> copyAction)
{
if (typeof(T) == typeof(string))
copyAction((GetStringValue(field));
else if (typeof(T) == typof(int))
copyAction(GetIntValue(field));
else
return false;
return true;
}
But this doesn't even compile. I then tried to wrap my non-generic metods in generic ones like
public string GetValue<string>(string field)
{
return GetStringValue(field);
}
which obviously doesn't compile either.
Can this be done or do i have to explicitly implement CopyValue
for each type?
You can get it to work with casting, but it's ugly:
if (typeof(T) == typeof(string))
{
copyAction((T)(object) GetStringValue(field));
}
(etc)
This sort of thing always ends up being fairly ugly, to be honest. One option would be to create a Dictionary<Type, Delegate>
like this:
Dictionary<Type, Delegate> fieldExtractors = new Dictionary<Type, Delegate>
{
{ typeof(string), (Func<string, string>) field => GetStringValue(field) },
{ typeof(int), (Func<string, int>) field => GetIntValue(field) },
};
Then you can use:
public bool CopyValue<T>(string field, Action<T> copyAction)
{
Delegate fieldExtractor;
if (fieldExtractors.TryGetValue(typeof(T), out fieldExtractor))
{
var extractor = (Func<string, T>) fieldExtractor;
copyAction(extractor(field));
return true;
}
return false;
}
See more on this question at Stackoverflow