C#-定义通用函数字典

时间:2019-03-30 09:47:50

标签: c# generics functional-programming

我如何定义将类型映射到以该类型作为输入的函数的字典

类似的东西:

var stringifiers = new Dictionary<Type, Func<T, string>> {
        { typeof(string), s => s},
        { typeof(float), f => f.ToString()},
        { typeof(bool), b => b.ToString()},
    };

用法:

stringifiers[bar.getType()](bar)

上面的词典定义编译不明显

  

找不到命名空间“ T”上的类型

2 个答案:

答案 0 :(得分:3)

如果您不喜欢字典,并且希望类型和函数之间存在一对一的关系,则可以使用通用静态变量来存储和检索函数,并在此过程中提高类型安全性。

“魔术”出现在StringInternal<T>中。由于StringInternal<string>.Stringify是不同于StringInternal<float>.Stringify的变量,因此您可以将Func存储在该静态变量中,并使用该类型进行访问。

Stringifier类是具有泛型函数的非泛型类,因此我们可以使用类型推断,从而简化调用语法。

public static class Stringifier
{
    public static void Set<T>(Func<T, string> func)
    {
        StringifierInternal<T>.Stringify = func;
    }

    public static string Stringify<T>(T value)
    {
        return StringifierInternal<T>.Stringify(value);
    }

    private static class StringifierInternal<T>
    {
        public static Func<T, string> Stringify { get; set; }
    }
}

用法:

Stringifier.Set<string>(v => v + "stringified");
Stringifier.Set<float>(v => v.ToString() + "floatstringified");
Stringifier.Set<bool>(v => v ? "it's twoo" : "not twoo");

Console.WriteLine(Stringifier.Stringify("X"));
Console.WriteLine(Stringifier.Stringify((float)17));
Console.WriteLine(Stringifier.Stringify(true));

输出:

Xstringified
17floatstringified
it's twoo

答案 1 :(得分:2)

尝试这个课程:

public class Stringifier
{
    private Dictionary<Type, Delegate> _store
        = new Dictionary<Type, Delegate>();

    public void Store<T>(Func<T, string> value)
    {
        _store[typeof(T)] = value;
    }

    public Func<T, string> Fetch<T>()
    {
        return (Func<T, string>)_store[typeof(T)];
    }

    public string Fetch<T>(T value)
    {
        return this.Fetch<T>().Invoke(value);
    }

    public string Fetch(Type type, object value)
    {
        return (string)
        (
            typeof(Stringifier)
                .GetMethods()
                .Where(x => x.Name == "Fetch")
                .Where(x => x.IsGenericMethod)
                .Where(x => x.ReturnType == typeof(string))
                .Select(x => x.MakeGenericMethod(type))
                .First()
                .Invoke(this, new [] { value })
        );
    }       
}

然后您可以执行以下操作:

var stringifier = new Stringifier();

stringifier.Store<string>(s => $"!{s}!");
stringifier.Store<float>(f => f.ToString());
stringifier.Store<bool>(b => b.ToString());

var bar = "XXX";

var value = stringifier.Fetch(bar.GetType(), bar);

Console.WriteLine(value);   

我得到的输出是!XXX!