根据类型参数调用泛型方法中的不同方法

Tho*_*ser 2 .net c# generics

我有几个这样的方法:

public string GetStringValue(string field) { /* ... */ }
public int GetIntValue(string field) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

现在我想编写一个具有以下签名的通用方法:

public bool CopyValue<T>(string field, Action<T> copyAction)
Run Code Online (Sandbox Code Playgroud)

根据我想copyAction使用非泛型方法之一的返回值调用的类型参数。我的第一次尝试是

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;
}
Run Code Online (Sandbox Code Playgroud)

但这甚至无法编译。然后我尝试将我的非通用方法包装在通用方法中,例如

public string GetValue<string>(string field)
{
    return GetStringValue(field);
}
Run Code Online (Sandbox Code Playgroud)

这显然也不能编译。

这可以完成还是我必须CopyValue为每种类型明确实现?

Jon*_*eet 5

你可以让它与铸造一起工作,但它很难看:

if (typeof(T) == typeof(string))
{
    copyAction((T)(object) GetStringValue(field));
}
Run Code Online (Sandbox Code Playgroud)

(等等)

老实说,这种事情最终总是相当丑陋。一种选择是创建Dictionary<Type, Delegate>这样的:

Dictionary<Type, Delegate> fieldExtractors = new Dictionary<Type, Delegate>
{
    { typeof(string), (Func<string, string>) field => GetStringValue(field) },
    { typeof(int), (Func<string, int>) field => GetIntValue(field) },
};
Run Code Online (Sandbox Code Playgroud)

然后你可以使用:

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;
}
Run Code Online (Sandbox Code Playgroud)