Использование предикатов в качестве ключа в словаре, ошибка при попытке вызвать значение - PullRequest
0 голосов
/ 04 мая 2018

Я экспериментировал с превращением простой цепочки 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 голосов
/ 04 мая 2018

Игнорирование комментариев (которые действительны) и ответ на ваш вопрос:

m => m(randomNumber) != null всегда будет правдой. Возврат от вашего предиката всегда будет true или false, а не null, поэтому, когда вы установите randomNumber = 8, вы получите -2: false != null -> true -> 2.0 *= -1 is -2.

Во-вторых, когда вы не соответствуете ни одному из ваших предикатов, ваш ключ (возвращаемый результат FirstOrDefault() будет нулевым, и вы не обрабатываете это.

Вы либо должны использовать несколько строк (проверка на ноль), либо иметь универсальную запись, как подсказывает Эвк. Решение Mjwills тоже работает, оно называется условным оператором null .

Кроме того, если вы используете предикат .First(m => m(randomNumber)), вы можете полностью удалить предикат Where, уменьшив сложность по времени до уровня, сравнимого с повторяющимся List<>.

0 голосов
/ 04 мая 2018

Оставляя в стороне вопрос о том, является ли Dictionary правильной структурой данных для этого, я бы предложил попробовать:

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

?.Invoke означает :

return null если функция, которую я собираюсь вызвать - null

который, кажется, соответствует тому, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...