7

I got the following code and i am trying to print teenAgerStudents without the foreach i made after the LINQ line. Can i add print in the LINQ line? Can i print with another new LINQ line onstead the foreach?

class Student
{
    public int StudentID { get; set; }
    public string StudentName { get; set; }
    public int Age { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        Student[] studentArray = {
                new Student() { StudentID = 1, StudentName = "John", Age = 18 } ,
                new Student() { StudentID = 2, StudentName = "Steve",  Age = 21 } ,
                new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 } ,
                new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 } ,
                new Student() { StudentID = 5, StudentName = "Ron" , Age = 31 } ,
                new Student() { StudentID = 6, StudentName = "Chris",  Age = 17 } ,
                new Student() { StudentID = 7, StudentName = "Rob",Age = 19  } ,
    };
        Student[] teenAgerStudents = studentArray.Where(s => s.Age > 12 && s.Age < 20).ToArray();

        foreach (var item in teenAgerStudents)
        {
            Console.WriteLine(item.StudentName);
        }
};
1
  • 1
    Yes you can. And for simple cases it's fine. However, LINQ's performance is often a lot worse than writing the code. I tend to avoid it where possible unless I am absolutely sure performance is not, and will never become, a factor. Commented Mar 4, 2016 at 16:17

4 Answers 4

15

This will work:

studentArray.Where(s => s.Age > 12 && s.Age < 20)
            .ToList()
            .ForEach(s => Console.WriteLine(item.StudentName));

Array.ForEach takes an Action<T> so it doesn't have a return value. If you need the array later on, you should stick to your old code.

Of course you can also still use the ForEach in a second statement:

List<Student> teenAgerStudent = studentArray.Where(s => s.Age > 12 && s.Age < 20).ToList();
teenAgerStudent.ForEach(s => Console.WriteLine(s.StudentName));

But that makes it less readable (in my opinion) so I would stick to a good old foreach loop in that case.

Sign up to request clarification or add additional context in comments.

8 Comments

In the first case, just drop the ToArray() - it adds nothing.
@Zastai That wouldn't work, ForEach isn't defined for IEnumerable
My bad. That's what happens when I comment from my phone and can't quickly check the docs.
@user3396397 Really? So you were looking for teenAgerStudents.ForEach(s => Console.WriteLine(s.StudentName));. Could you explain then the difference from foreach (var s in teenAgerStudents) Console.WriteLine(s.StudentName)); other than being more inefficient?
@AlexanderDerck The comment wasn't addressed to you:) Your answer is fine (if you replace item with s :)
|
3

Try this:

  // There's no need in materialization, i.e. "ToArray()"
  var target = studentArray 
    .Where(student => student.Age > 12 && student.Age < 20) // teen
    .Select(student => String.Format("Id: {0} Name: {1} Age {2}", 
              student.Id, student.Name, student.Age));

  // Printing out in one line (thanks to String.Join)
  Console.Write(String.Join(Environment.NewLine, target));

4 Comments

This is a very unique method. Highlights the fact that target has not been executed and will be executed when really needed. +1.
But gathers the full set of results, wasting memory. Streaming results is much more scalable.
@Zastai: it depends on the data's size. Since the data is represented as an array (and so the entire data are in memory) I assumed that we have a sufficient memory for String.Join (if we read from, say, file, streaming would be a point)
Sample code in a question is often just a sample; I try not to base too much on it. But yes, with this array it's fine.
2

I don't like to use LINQ (a functional programming system) for side effects. I'd rather change the output foreach to something like that:

Console.WriteLine(string.Join(Environment.NewLine, 
    teenAgerStudents.Select(s => s.StudentName));

Comments

1

This line will print your teenAgerStudents names to console, one for each line.

Console.Write(string.Join(Environment.NewLine, studentArray.Where(s => s.Age > 12 && s.Age < 20).Select(s=>s.StudentName)));

It replaces both the teenAgerStudents initialization and the foreach.

If you still want to initialize your teenAgeStudents list because you need it, you could split the previous line in two

//get the teenager students in form of IEnumerable<Student>.
//cast it to array with .ToArray() after .Where() if needed.
var teenAgerStudents = studentArray.Where(s => s.Age > 12 && s.Age < 20);
//print only the students' names
Console.Write(string.Join(Environment.NewLine,teenAgerStudents.Select(s=>s.StudentName)));

Hope this helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.