tags:

views:

914

answers:

3

I have an IEnumerable list of objects in C#. I can use a for each to loop through and examine each object fine, however in this case all I want to do is examine the first object is there a way to do this without using a foreach loop?

I've tried mylist[0] but that didnt work.

Thanks

+12  A: 

(For the sake of convenience, this answer assumes myList implements IEnumerable<string>; replace string with the appropriate type where necessary.)

If you're using .NET 3.5, use the First() extension method:

string first = myList.First();

If you're not sure whether there are any values or not, you can use the FirstOrDefault() method which will return null (or more generally, the default value of the element type) for an empty sequence.

You can still do it "the long way" without a foreach loop:

using (IEnumerator<string> iterator = myList.GetEnumerator())
{
    if (!iterator.MoveNext())
    {
        throw new WhateverException("Empty list!");
    }
    string first = iterator.Current;
}

It's pretty ugly though :)

In answer to your comment, no, the returned iterator is not positioned at the first element initially; it's positioned before the first element. You need to call MoveNext() to move it to the first element, and that's how you can tell the difference between an empty sequence and one with a single element in.

EDIT: Just thinking about it, I wonder whether this is a useful extension method:

public static bool TryFirst(this IEnumerable<T> source, out T value)
{
    using (IEnumerator<T> iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            value = default(T);
            return false;
        }
        value = iterator.Current;
        return true;
    }
}
Jon Skeet
Is mylist.GetEnumerator().Current equal to this? I'd like to know just for the sake of knowing.
Oliver N.
I'm not sure if I like the extension method as its out parameter makes it less composable. I know that's the point of the method in this case but having something non-composable on a sequence seems wrong.
dpp
The result of this isn't a sequence though - it's only ever going to be a single element and a Boolean, so it would have to be at the end of the composition chain anyway. I think if you looked at places where you'd actually want this, it wouldn't be a problem. As you say, it's the point of the method.
Jon Skeet
+1  A: 

Remember, there may be no "first element" if the sequence is empty.

        IEnumerable<int> z = new List<int>();
        int y = z.FirstOrDefault();
Yacoder
+1  A: 

If you're not on 3.5:

 using (IEnumerator<Type> ie = ((IEnumerable<Type>)myList).GetEnumerator()) {
     if (ie.MoveNext())
         value = ie.Current;
     else
         // doesn't exist...
 }

or

 Type value = null;
 foreach(Type t in myList) {
     value = t;
     break;
 }
Mehrdad Afshari