开发者

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 开发者_StackOverflowstudent;

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


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.


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

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


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]);


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.


In the lambda way

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


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();


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]);


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");


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());
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜