Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a concise built-in way to get a list item by index that is not going to throw an exception?

Tags:

c#

.net

list

linq

I safely search a list for an object like this:

var someResult = myList.FirstOrDefault(x=>x.SomeValue == "SomethingHere");

If there are no objects that match my criteria then someResult is going to be null.

But if I only have the index of the object I want, things are not so nice. I seem to have to so something like this:

try
{
    var someResult = myList[4];
}
catch (ArgumentOutOfRangeException)
{
    someResult = null;
}

I admit that is not terrible to have to write. But it seems to me that there should be a way to just have the list return null if the index ends up being bogus.

Is there away to have a one (or two) line look up using existing .net methods?

(I know I could easily write an extension method, but I am wondering if there is a built in way to do this.)

like image 696
Vaccano Avatar asked Jul 10 '12 21:07

Vaccano


People also ask

What does Index () return if not found?

The index() method searches for the first occurrence of the given item and returns its index. If specified item is not found, it raises 'ValueError' exception. The optional arguments start and end limit the search to a particular subsequence of the list.

How do you find the index of an element in Linq?

LINQ does not have an IndexOf method. So to find out index of a specific item we need to use FindIndex as int index = List. FindIndex(your condition); 0.


4 Answers

I think you want C.B.s suggestion of ElementAtOrDefault - go vote it up.

I have a few other points to add...

Regarding your try/catch solution:

I admit that is not terrible to have to write.

Please don't use exceptions for this. Your approach is more verbose, exceptions are slow so you will get poor performance, and exceptions should only be used for exceptional situations.


It's also fairly easy to write this without LINQ by using the conditional operator:

var someResult = myList.Count > 4 ? myList[4] : null;
like image 92
Mark Byers Avatar answered Oct 16 '22 23:10

Mark Byers


You may be able to use the LINQ extension .ElementAtOrDefault() to achieve what you want.

List<Foo> foos = new List<Foo>();
Foo element = foos.ElementAtOrDefault(4);

However, you need to be careful that your generic type to List<T> is a reference type or a string, so the "default" returned to you is actually null. The default you get back is default(T).

like image 37
C B Avatar answered Oct 17 '22 00:10

C B


Yes, you can also use LINQ when you only have the index:

var someResult = myList
            .Select((x, i) => new { X = x, Index = i })
            .FirstOrDefault(x => x.Index == 4);

Enumerable.Select Method (IEnumerable, Func)

Projects each element of a sequence into a new form by incorporating the element's index.

like image 36
Tim Schmelter Avatar answered Oct 16 '22 23:10

Tim Schmelter


C B's answer wins, but I can compete for second place, right?

var someResult = myList.Skip(4).FirstOrDefault();
like image 23
Risky Martin Avatar answered Oct 16 '22 23:10

Risky Martin