Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

142
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda