Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# List Comprehensions = Pure Syntactic Sugar?

Consider the following C# code:

IEnumerable numbers = Enumerable.Range(0, 10);
var evens = from num in numbers where num % 2 == 0 select num;

Is this pure syntactic sugar to allow me to write a for or foreach loop as a one-liner? Are there any compiler optimizations under the covers that make the list comprehension above more efficient than the loop construct? How does this work under the hood?

like image 877
λ Jonas Gorauskas Avatar asked Jun 05 '09 03:06

λ Jonas Gorauskas


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

Why is C named so?

Quote from wikipedia: "A successor to the programming language B, C was originally developed at Bell Labs by Dennis Ritchie between 1972 and 1973 to construct utilities running on Unix." The creators want that everyone "see" his language. So he named it "C".


1 Answers

As Jason said, your code is equivalent to:

Enumerable.Range(0, 10).Where(n => n % 2 == 0);

Note the lambda will be transformed to a function call which is done for every element. This is probably the largest part of the overhead. I did a test, which indicates LINQ is about 3 times slower (mono gmcs version 1.2.6.0) on this exact task

    Time for 10000000 for loop reps: 00:00:17.6852560
    Time for 10000000 LINQ reps: 00:00:59.0574430

    Time for 1000000 for loop reps: 00:00:01.7671640
    Time for 1000000 LINQ reps: 00:00:05.8868350

EDIT: Gishu reports that VS2008 and framework v3.5 SP1 gives:

    Time for 1000000 loop reps: :00.3724585 
    Time for 1000000 LINQ reps: :00.5119530 

LINQ is about 1.4 times slower there.

It compares a for-loop and a list to LINQ (and whatever structure it uses internally). Either way, it converts the result to an array (necessary to force LINQ to stop being "lazy"). Both versions repeat:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

public class Evens
{
    private static readonly int[] numbers = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    private static int MAX_REPS = 1000000;

    public static void Main()
    {
        Stopwatch watch = new Stopwatch();

        watch.Start();
        for(int reps = 0; reps < MAX_REPS; reps++)
        {
            List<int> list = new List<int>(); // This could be optimized with a default size, but we'll skip that.
            for(int i = 0; i < numbers.Length; i++)
            {
                int number = numbers[i];
                if(number % 2 == 0)
                    list.Add(number);
            }
            int[] evensArray = list.ToArray();
        }
        watch.Stop();
        Console.WriteLine("Time for {0} for loop reps: {1}", MAX_REPS, watch.Elapsed);

        watch.Reset();
        watch.Start();
        for(int reps = 0; reps < MAX_REPS; reps++)
        {
            var evens = from num in numbers where num % 2 == 0 select num;
            int[] evensArray = evens.ToArray();
        }
        watch.Stop();
        Console.WriteLine("Time for {0} LINQ reps: {1}", MAX_REPS, watch.Elapsed);
    }
}

Past performance tests on similar tasks (e.g. LINQ vs Loop - A performance test) corroborate this.

like image 173
Matthew Flaschen Avatar answered Nov 11 '22 05:11

Matthew Flaschen