字典与Func作为关键

时间:2012-11-16 02:15:58

标签: c# dictionary func

我想知道这是否是词典的关键词的理智选择?我想要做的是使用表达式作为字典中的键,如:

    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语句更简洁。

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

3 个答案:

答案 0 :(得分:7)

不,只要使用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的回答here表示编译器允许检测lambda是否相同(尽管通常不会)。无论哪种方式,lambda / delegate都是一个糟糕的选择。

答案 1 :(得分:6)

考虑到你使用地图的方式,你最好使用List<Tuple<Func<int,bool>,int>>,因为检查lambdas的顺序将不再是任意的,就像在基于散列的字典中一样。此方法还允许您跳过查找步骤:

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;
}

答案 2 :(得分:0)

使用最新语法重写@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 SingleOrDefault上不存在的Func时,将返回键值为null且值为0的元素。

上面的

KeyValue出于可读性考虑,可以将它们删除,在这种情况下,result.Intem2将产生输出