使用谓词作为字典中的键,在尝试调用值时出错

时间:2018-05-03 21:23:52

标签: c# linq unity3d c#-4.0

我正在尝试使用字典将一个简单的if-else链变成更具功能性的东西。它工作正常,除非randomNumber不符合任何谓词。有没有更简洁的方法来防止linq空值而不必在where子句中明确地检查它?

Dictionary<Predicate<float>, Func<float, float>> _mutateDict = 
    new Dictionary<Predicate<float>, Func<float, float>>();

_mutateDict.Add((float x) => x <= 2, f => { return f *= -1f; });
_mutateDict.Add((float x) => x <= 4, f => { return Random.Range(-0.5f, 0.5f); });
_mutateDict.Add((float x) => x <= 6, f => { return f *= 2f; });

float weight = 2f;

float result = _mutateDict
[
    _mutateDict
    .Keys
    .Where(m => m(randomNumber) != null) 
    .FirstOrDefault()
](weight);

2 个答案:

答案 0 :(得分:3)

忽略评论(有效)并回答您的问题:

m => m(randomNumber) != null永远都是真的。谓词的返回值始终为truefalse,永远不会null,这就是为什么当您设置randomNumber = 8时,您回来-2:{{ 1}} - &gt; false != null - &gt; true2.0 *= -1

其次,当你没有匹配任何谓词时,你的密钥(来自-2的返回值将为空,并且你不会处理它。

要么需要使用多行(检查为null),要么像Evk建议的那样拥有一个包罗万象的条目。 Mjwills解决方案也有效,它被称为null conditional operator

此外,如果您使用FirstOrDefault()谓词,则可以完全删除.First(m => m(randomNumber))谓词,将时间复杂度降低到与迭代Where相当的位置。

答案 1 :(得分:1)

暂不考虑Dictionary是否是正确的数据结构的问题,我建议尝试:

var result = _mutateDict
[
    _mutateDict
    .Keys
    .Where(m => m(randomNumber) != null)
    .FirstOrDefault()
]?.Invoke(weight);

?.Invoke means

  

如果我要调用的函数是null

,则返回null

似乎符合你的需要。