LINQ Query - Выбор ключа на основе значения, имеющего свойство, совпадающее со строкой? - PullRequest
2 голосов
/ 16 июня 2011

У меня есть IDictionary

Мне нужно выбрать первый Foo, где Bar.Prop1 соответствует строковому значению.

public class Foo { }

public class Bar
{
    public String Prop1 { get; set; }
}

сейчас у меня так ...

foreach (var kvp in MyDictionary)
{
    if (kvp.Value.Prop1 == theString)
    {
        var key = kvp.Key;
        //Do something with it
        break;
    }
}

Но это не кажется таким чистым, как LINQ Query. ReSharper превратил это в:

foreach (var kvp in MyDictionary.Where(kvp => kvp.Value.Prop1 == theString))
{
    var key = kvp.Key;
    //Do something with it
    //break; is unnecessary because I only get one kvp back anyways.
}

Мне нужен только самый первый элемент, который соответствует, потому что я никогда не ожидаю получить более одного KVP. Это противоречит бизнес-логике, поэтому модульное тестирование позаботится об этом.

Ответы [ 3 ]

7 голосов
/ 16 июня 2011

Мне нужен только самый первый соответствующий элемент, потому что я не рассчитываю получить более одного KVP.Это идет вразрез с бизнес-логикой, поэтому модульное тестирование позаботится об этом.

Если это так, я бы сказал, что вам нужно использовать более надежную гарантию кода вашего намерения, и это будетSingle (или SingleOrDefault) метод.First собирается вернуть первый объект из произвольного числа , соответствующих данному предикату.Если много идет вразрез с вашими ожиданиями и бизнес-правилами, похоже, это ошибка.Относитесь к этому как таковой.

var key = MyDictionary.Single(pair => pair.Value.Prop1 == someValue).Key;

С Single, если в последовательности более одного совпадающего элемента, это приведет к исключению.

SingleOrDefault допускает 0 или 1, но никогда больше.Если вы используете этот подход, вам нужно захватить результат и сравнить его с нулем, прежде чем выполнять с ним дополнительные операции (методы запуска, доступ к свойствам и т. Д.).

5 голосов
/ 16 июня 2011
var key = MyDictionary.First(kvp => kvp.Value.Prop1 == theString).Key;
4 голосов
/ 16 июня 2011

@ Ответ Bala R верен, но Энтони Пегрэм делает очень хороший комментарий в своем комментарии к ОП.Если вы делаете это несколько раз с разными ключами, вместо этого вам нужно перевернуть словарь, чтобы вам не приходилось обходить всю коллекцию каждый раз, когда вы хотите получить значение.

// Do this just once: it's expensive
var reverseDict = MyDictionary.ToDictionary(kvp => kvp.Value.Prop1, kvp => kvp.Key);

...
// Do this as many times as you need: it's cheap
var key = reverseDict[someValue];
...