Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# IEnumerable.Select在函数调用中重复输入参数_C#_Linq_Select - Fatal编程技术网

C# IEnumerable.Select在函数调用中重复输入参数

C# IEnumerable.Select在函数调用中重复输入参数,c#,linq,select,C#,Linq,Select,我无意中发现了一种我无法预料的行为,并且找不到它的文档。我有一个有两个参数的函数,其中一个有一个默认值。当在Select内部调用该函数时,出于某种原因,它会获取调用它的值并将其应用于两个参数。例如: 具有以下功能: private static Directions PrintDir(Directions dir, int distance = 1) { Console.WriteLine($"Direction {dir}, distance {distance}"

我无意中发现了一种我无法预料的行为,并且找不到它的文档。我有一个有两个参数的函数,其中一个有一个默认值。当在Select内部调用该函数时,出于某种原因,它会获取调用它的值并将其应用于两个参数。例如:

具有以下功能:

private static Directions PrintDir(Directions dir, int distance = 1) 
{
    Console.WriteLine($"Direction {dir}, distance {distance}");
    return dir;
}
如果单独调用,则其行为符合预期:

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);
    }
}
印刷品:

Direction Left, distance 1
Direction Up, distance 1
Direction Right, distance 1
Direction Down, distance 1
但是,在LINQ表达式内部调用时:

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();
    }
}
因此,似乎方向值已正确应用为dir参数,但也已转换为int并应用为第二个距离参数,而不是默认值

为什么会发生这种情况?Select中函数的规则是什么?

有一个包含索引的。如果使用lambdas,则代码如下所示:

Select((item,index) => PrintDir(item, index))
Select(item => PrintDir(item))
如果要避免,请按如下方式调用Select:

Select((item,index) => PrintDir(item, index))
Select(item => PrintDir(item))
还有一个包含索引的。如果使用lambdas,则代码如下所示:

Select((item,index) => PrintDir(item, index))
Select(item => PrintDir(item))
如果要避免,请按如下方式调用Select:

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

对某人的答案再补充一点:如果您编写printdirections.Left,编译器将编译代码printdirections.Left,1-它接受默认值并将其插入到方法调用中

现在,如果您尝试直接从方法创建委托,例如:

var f = new Func<Directions, Directions>(PrintDir)
您实际上是在为以下内容编写速记:

.Select(new SomeDelegateType(PrintDir))
其中SomeDelegateType是合适的委托类型。编译器在Select的所有重载中搜索一个接受将要编译的委托类型的重载

Select有一个重载,它接受一个Func,因此它尝试这样做:

.Select(new Func<Direction, Direction>(PrintDir))
这是编译的,所以编译器选择它


事实上,事情稍微复杂一点,因为编译器正在推断返回类型,我假设它是上面的方向,它也试图找到最佳匹配,但这就是它的要点。

对某人的答案再补充一点:如果您编写printdirections.Left,编译器编译代码printdirections.Left,1-它接受默认值并将其插入到方法调用中

现在,如果您尝试直接从方法创建委托,例如:

var f = new Func<Directions, Directions>(PrintDir)
您实际上是在为以下内容编写速记:

.Select(new SomeDelegateType(PrintDir))
其中SomeDelegateType是合适的委托类型。编译器在Select的所有重载中搜索一个接受将要编译的委托类型的重载

Select有一个重载,它接受一个Func,因此它尝试这样做:

.Select(new Func<Direction, Direction>(PrintDir))
这是编译的,所以编译器选择它


事实上,事情稍微复杂一些,因为编译器正在推断返回类型,我假设它是上面提到的方向,它也试图找到最佳匹配,但这就是要点。

我希望您正在使用。另外,不要执行Enum.GetValuestypeofDirections.Cast-将每个枚举成员装箱,然后取消装箱。如果可以,请使用Enum.GetValues,否则请使用您预期使用的方向[]Enum.GetValuestypeofDirections。另外,请不要执行Enum.GetValuestypeofDirections.Cast-该框,然后取消每个Enum成员的框。如果可以,请使用Enum.GetValues,否则请使用Directions[]Enum.getvaluestypeofdirections我明白了,这是有道理的,我当时误解了那里的行为。带回家的信息是,如果我想使用带有默认参数的函数,我必须执行显式lambda调用。只有当第二个默认参数是整数时。我明白了,这是有道理的,我误解了那里的行为。带回家的消息是,如果我想使用带有默认参数的函数,我必须执行显式lambda调用。只有当第二个默认参数是整数时。