字典以Func为键

10

我想知道在字典中使用这种键是否是明智的选择?我想要做的是将表达式作为字典的键,类似于:

    var map3 = new Dictionary<Func<int, bool>, int>();
    map3.Add((x) => x % 2 == 0, 1);
    map3.Add((x) => x % 10 == 0, 2);
    // ...

    var key = map3.Keys.SingleOrDefault(f => f(2));
    // key = (x) => x % 2
    // map3[key] = 1

这个想法比大量使用if-else或switch语句更加简洁。

这有意义吗?它会起作用吗?是否有更简单的方法?


1
总之,不行。虽然它通常是一个适当的值,但作为键我会避免使用它。 - Servy
2
那将会让我头疼不已,难以维护。 - Simon Whitehead
3个回答

9

考虑到您使用地图的方式,您最好使用 List<Tuple<Func<int,bool>,int>>,因为在基于哈希的字典中,检查lambda表达式的顺序将不再是随意的。这种方法还可以让您跳过查找步骤:

var map3 = new List<Tuple<Func<int,bool>,int>> {
    new Tuple<Func<int,bool>,int>((x) => x % 2 == 0, 1)
,   new Tuple<Func<int,bool>,int>((x) => x % 10 == 0, 2)
};
var t = map3.SingleOrDefault(t => t.Item1(2));
if (t != null) {
    var v = t.Item2;
}

8
不行,每当使用lambda表达式时,C#都会构造一个新的委托实例,因此您无法将它用作一致的键。例如:
        Func<int, int> f = x => x*x + 1;
        Func<int, int> g = x => x*x + 1;
        Console.WriteLine(f.Equals(g)); // prints False

如果没有其他方法始终获取相同的实例,那么使用它作为字典键会很麻烦。

编辑:

Eric Lippert在这里的回答表明编译器允许检测lambda是否相同(尽管通常不会)。无论如何,lambda /委托都不适合用作键。


1

使用最新语法重写 @dasblinkenlight 的答案:

void Main()
{
    var map3 = new List<(Func<int, bool> Key, int Value)> {
        (Key: (x) => x * 2 == 4, Value: 1),
        (Key: (x) => x * 10 == 100, Value: 2)
    };

    var result = map3.SingleOrDefault(x => x.Key(10));
    Console.WriteLine(result.Value);
}

Key 评估为一个在 List 中不存在的 Func 时,SingleOrDefault 返回一个键为 null 值为 0 的元素。
上面的 KeyValue 是为了可读性而添加的,它们可以被删除,在这种情况下,result.Intem2 将产生输出。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接