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 语句更清洁的方法。

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

4

3 回答 3

9

Considering the way that you use your map, you will be better off with a List<Tuple<Func<int,bool>,int>>, because the order of checking the lambdas will no longer be arbitrary, as in a hash-based dictionary. This approach also lets you skip the lookup step:

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;
}
于 2012-11-16T02:28:15.120 回答
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's answer here表明允许编译器检测 lambdas 是否相同(尽管通常不会)。无论哪种方式,lambda/delegate 都是一个糟糕的选择。

于 2012-11-16T02:27:13.713 回答
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计算出一个不存在的 Func 时,List SingleOrDefault返回一个键为 null 且值为 0 的元素。

Key以上Value是为了可读性,它们可以被删除,在这种情况下result.Intem2会产生输出

于 2019-08-22T04:12:15.530 回答