views:

160

answers:

2

Title kind of says it all. I just can't seem to find a DictionaryOrDefault \ ListOrDefault \ CollectionOrDefault option.

Is there such a method? If not how do I do this:

MyClass myObject = MyDictionary
    .SingleOrDefault(x =>
                        {
                            if (x.Value != null)
                                return (x.Value.Id == sourceField.SrcField.Id);
                            else
                                return false;
                        }).Key;

if there is more than one match? (I am getting an execption because SingleOrDefault is only meant for single results (imagine that!).)


Guess I needed to be clearer (though the where answers looks good).

I have the above statement. I changed my program so that it does not always return 1 (there can be several values that match one key). That fails so I am looking for a collection to be returned (rather than just one item).

+2  A: 

You can use IEnumerable<T>.FirstOrDefault(Func<T, bool> predicate) if your intention is to return the first one matching the predicate.

Otherwise you're simply looking at the IEnumerable<T>.Where(Func<T, bool> predicate) linq extension, which will return all elements that match the predicate passed. That will return an empty IEnumerable<T> if no elements match the predicate, at which point if you really need the value to be null, you can just look if anything is in it.

var res = MyDictionary.Where(x => 
                        { 
                            if (x.Value != null)  
                                return (x.Value.Id == sourceField.SrcField.Id);  

                            return false;  
                        });
if (!res.Any())
    res = null;

Then if you absolutly need to have it as a list, you can just call

res.ToList();

Note that if you're actually manipulating a Dictionary<TKey, TValue>, res will contain KeyValuePair<TKey, TValue>'s.

Dynami Le Savard
I feel quite dumb for not thinking of Where. I just got twisted around.
Vaccano
+1  A: 

if you do something like

var mylist = obj.Where(x=>x.attr1 == 4);

you can then check if anything was returned using the .Any() method

mylist.Any()
John Boker
Don't call .ToList() until you need it. Even if you know you need it right away, at least save it for the next line.
Joel Coehoorn
I'll remember that for next time, thanks for the info.
John Boker
@Joel - Is there drawbacks calling ToList? (I have assumed so, but never knew...)
Vaccano
Yes, there are drawbacks. ToList() forces immediate iteration of the enumerable. It breaks any advantage you might get from lazy evaluation. By not calling ToList() you don't do _any_ real work until you actually use the enumerable somewhere like in a foreach.
Joel Coehoorn
A good example is John's code above. ToList() forces you to iterate over the entire collection, even though the Any() method only cares if there's one and can stop after the first item in the sequence.
Joel Coehoorn