Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

134
Views
IEnumerable.Select repeats input parameter in a function call

I stumbled upon a behaviour that I would not expect and can't find the documentation of. I have a function with 2 parameters, one of them has a default value. When the function is called inside of a Select, it for some reason takes the value it is called on and applies it for both parameters. Example:

Have the function:

private static Directions PrintDir(Directions dir, int distance = 1) 
{
    Console.WriteLine($"Direction {dir}, distance {distance}");
    return dir;
}

If called on its own, it behaves as expected:

using System;
using System.Linq;
                    
public class Program
{
    enum Directions { Left, Up, Right, Down };
    
    public static void Main()
    {
        PrintDir(Directions.Left);
        PrintDir(Directions.Up);
        PrintDir(Directions.Right);
        PrintDir(Directions.Down);
    }
}

prints:

Direction Left, distance 1
Direction Up, distance 1
Direction Right, distance 1
Direction Down, distance 1

however when called inside of LINQ expression:

using System;
using System.Linq;
                
public class Program
{
    enum Directions { Left, Up, Right, Down };
    
    public static void Main()
    {
        var dirs = Enum.GetValues(typeof(Directions))
            .Cast<Directions>()
            .Select(PrintDir)
            .ToList();
    }
}

I get:

Direction Left, distance 0
Direction Up, distance 1
Direction Right, distance 2
Direction Down, distance 3

So it appears the Directions value has been applied correctly as the dir parameter, but also converted to int and applied instead of the default value as the second distance parameter.

Why does this happen? What are the rules for functions inside Select?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

There is an overload of Select which also contains the index. If you used lambdas, your code would look like this:

Select((item,index) => PrintDir(item, index))

If you want to avoid it, call your Select like this:

Select(item => PrintDir(item))
over 4 years ago · Santiago Trujillo Report

0

To add a little more to SomeBody's answer: if you write PrintDir(Directions.Left), the compiler compiles the code PrintDir(Directions.Left, 1) -- it takes the default value and inserts it into the method call for you.

Now, if you try to create a delegate directly from the method, e.g:

var f = new Func<Directions, Directions>(PrintDir)

there's nowhere for the compiler to insert this default value, so this won't compile. The only delegate type you can assign the method to directly is one which takes all parameters, e.g. Func<Directions, int, Directions>.

However, if you write:

var f = new Func<Directions, Directions>(x => PrintDir(x))

The compiler can turn this into:

var f = new Func<Directions, Directions>(x => PrintDir(x, 1))

When you write:

.Select(PrintDir)

you're actully writing shorthand for:

.Select(new SomeDelegateType(PrintDir))

where SomeDelegateType is a suitable delegate type. The compiler searches through all of the overloads of Select looking for one which accepts a delegate type which will compile.

There's an overload of Select which accepts a Func<Direction, Direction>, so it tries this:

.Select(new Func<Direction, Direction>(PrintDir))

... but that doesn't compile, so it tries the overload which takes the int index:

.Select(new Func<Direction, int, Direction>(PrintDir))

and that does compile, so the compiler chooses it.

(In fact things are slightly more complex, as the compiler is inferring the return type (I assumed it's Direction above), and it also tries to find the best match, but that's the gist of it.)

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!