Bastien Vandamme
Bastien Vandamme

Reputation: 18485

Question about Linq

After reading the example of Microsoft here

        var query = from Student student in arrList
                    where student.Scores[0] > 95
                    select student;

        foreach (Student s in query)
            Console.WriteLine(s.LastName + ": " + s.Scores[0]);

I have a question :

Is it possible to avoid the loop ?

    foreach (Student s in query)
        Console.WriteLine(s.LastName + ": " + s.Scores[0]);

What if i rewrite the query and assume my query will always return one result.

    var query = from Student student in arrList
                where student.FirstName == "Cesar"
                select student;

I dont need to do a loop... I know that my query return only one element.

Upvotes: 0

Views: 109

Answers (9)

Snowbear
Snowbear

Reputation: 17274

It will still be an IEnumerable, but with one item. If you want to extract it you can use First() or even better Single():

var query = from Student student in arrList
            where student.FirstName == "Cesar"
            select student;

var student = query.Single();

Also you can replace the entire where clause by using Single/First overloaded methods:

var emperor = arrList.Single(s => s.FirstName == "Cesar");

Single is more strict than First since it will also check that there is exactly one item returned.

Upvotes: 4

Mike Christian
Mike Christian

Reputation: 1536

Assuming only one result will be returned can be dangerous. What is more than one student scores over 95?

You can use a lambda expression, to compress your code:

arrList.ForEach(s => Console.WriteLine(s.LastName + ": " + s.Scores.First());

Upvotes: 0

cllpse
cllpse

Reputation: 21727

You can use the FirstOrDefault() method.

Here's your query, re-written...

var student = (from Student student in arrList
               where student.FirstName == "Cesar"
               select student).FirstOrDefault();

Your query can also be written, chaining methods. In my opinion, it's easier on the eyes...

arrList.Where(student => student.FirstName == "Cesar").FirstOrDefault();

Or even more condensed...

arrList.FirstOrDefault(student => student.FirstName == "Cesar");

Upvotes: 0

Russ Cam
Russ Cam

Reputation: 125538

query will be an IEnumerable<Student> in this instance.

IEnumerable<T> itself does not have an extension method that allows you to perform an action on each enumerated T, like for example, List<T> does with ForEach<T>(Action<T>). You can certainly write the extension method to do this and I am sure many people have, but it was a design decision to not have it (an article by Eric Lippert that discusses this).

If you know that your expression will always return one result then you can call .First() on the projected collection (assuming you know there will always be at least one result).

var query = (from Student student in arrList
             where student.Scores[0] > 95
             select student).First();

Console.WriteLine(query.LastName + ": " + query.Scores[0]);

Upvotes: 0

Winger
Winger

Reputation: 676

For part 2 of your question, you can explicitly return a single Student object:

var student = (from Student s in arrList where s.FirstName == "Cesar" select student).FirstOrDefault();

Upvotes: 0

WorldIsRound
WorldIsRound

Reputation: 1554

In the lambda way

 arrList.SingleOrDefault(q => q.Scores[0] > 95);

Upvotes: 0

Alastair Pitts
Alastair Pitts

Reputation: 19601

You can absolutely avoid calling the loop, if you know that there is only going to be 1 record/object returned.

Have a look at the .First(), .FirstOrDefault(), .Single(), SingleOrDefault() extension methods.

Upvotes: 0

Jake Kalstad
Jake Kalstad

Reputation: 2065

FirstOrDefault, I prefer the method chain syntax, such as,

arrList.FirstOrDefault(s => s.FirstName == "Cesar");

Upvotes: 3

Russell Steen
Russell Steen

Reputation: 6612

var query = from Student student in arrList
        where student.FirstName == "Cesar"
        select student;

use this query.First().LastName

if (query.Count() > 0)
    Console.WriteLine(query.First().LastName + ": " + query.First().Scores[0]);

Upvotes: 0

Related Questions