我见过有人写下Func<>图案。我正在尝试使用Funcs和Lambdas来理解这些概念。
所以ExperimentalSelect返回一个Func(带有2个args和bool返回值)。
但是我不明白所有3个返回语句是如何有效的(每次1个)。
public static Func<BinaryTreeNode<int>, int, bool> nodeSelector = (x, y) =>
{
return x.Value > y;
};
public static Func<int, int, bool> intSelector = (x, y) =>
{
return x > y;
};
public static Func<BinaryTreeNode<int>, int, bool> ExperimentalSelect (int number)
{
return nodeSelector; // seems straightforward, i agree this should work
// how does this work ? intSelector is different type Func<>
// and it is executing it here, thereby returning the bool type result
// and not Func<> type as the return type of this method should
return (x, y) => intSelector(number, number);
// and how does this work ? what is node here ?
// and SomeMethod returns bool and not Func<> type
return (node, x) => SomeMethod(node, number, true);
}
private static bool SomeMethod(BinaryTreeNode<int> node, int someNumber,
bool doSomething)
{
return node.Value < someNumber;
}
编辑:
如果是分机。方法需要一个函数
IEnumerable<int> selected = tree.TakeWhile(ExperimentalSelect);
SomeMethod如何在这里工作?,它不是Func&lt;&gt; !
此语法的含义是:(node, x) => SomeMethod(node, number, true);
这里的节点或x在哪里?
答案 0 :(得分:4)
您在回复上方的评论不正确。
intSelector
和SomeMethod
不在那里执行。它们只会在执行ExperimentalSelect
的返回值时执行。
return (x, y) => intSelector(number, number);
这定义了一个带有两个参数的匿名方法。类型为BinaryTreeNode<int>
之一,类型为int且返回值为bool,因为这是ExperimentalSelect
的返回类型。 此匿名方法的主体是对intSelector
的调用,仅在执行匿名方法本身时执行。这意味着,这个匿名方法的主体可以是你想要的任何东西。它甚至可以是多个陈述:
return (x, y) => {
var temp;
temp = y;
y = x;
x = temp;
return intSelector(number, y);
}
然后返回匿名方法,而不是执行它的结果 您的退货声明等同于以下内容:
Func<BinaryTreeNode<int>, int, bool> result =
(x, y) => intSelector(number, number);
return result;
您可以使用调试器自行验证。在intSelector
内添加一个断点,然后跳过return
语句。你会看到,断点不会被击中。
重要的一点如下:
Func
可以看作是函数的指针。
Func<BinaryTreeNode<int>, int, bool> result =
(x, y) => SomeMethod(x, number, true);
这将创建一个匿名方法,result
将指向该匿名方法。
但是,请查看以下代码:
Func<BinaryTreeNode<int>, int, bool, bool> result = SomeMethod;
在这种情况下,结果将直接指向SomeMethod
。这里没有创建匿名方法。请注意result
类型的差异。由于第一个代码仅在匿名方法的主体中执行SomeMethod
,因此result
的类型不需要与SomeMethod
的签名匹配。但在第二个代码中,您直接将SomeMethod
分配给result
,因此result
的类型必须与SomeMethod
的签名匹配。
更多:
请查看以下代码:
public static Func<BinaryTreeNode<int>, int, bool> ExperimentalSelect (int number)
{
return (x, y) => intSelector(number, number);
}
Func<BinaryTreeNode<int>, int, bool> result = ExperimentalSelect(10);
Console.WriteLine(result(30, 20)); // writes false
它将打印false
,虽然30大于20.为什么?
原因是,您的匿名方法具有x
和y
作为输入参数,但它们不会在其正文中的任何位置使用。相反,您将number
作为两个参数传递给intSelector
。 number
的值为10,而10不大于10
编写此代码的正确方法如下:
public static Func<BinaryTreeNode<int>, int, bool> ExperimentalSelect ()
{
return (x, y) => intSelector(x, y);
}
Func<BinaryTreeNode<int>, int, bool> result = ExperimentalSelect();
Console.WriteLine(result(30, 20)); // writes true
如您所见,我现在将x
和y
传递给intSelector
。我还从number
中删除了参数ExperimentalSelect
,因为它未在任何地方使用。
答案 1 :(得分:2)
问问自己 - 这两行代码是否正确:
Func<BinaryTreeNode<int>, int, bool> a =
(x, y) => intSelector(number, number);
Func<BinaryTreeNode<int>, int, bool> b =
(node, x) => SomeMethod(node, number, true);
答案 - 是的。正如代码中的return语句一样。
我想也许你或者稍微误解了语法,或者可能没有准确理解Func
是什么(如果不是这样的话,道歉)。
答案 2 :(得分:2)
在这种情况下,您似乎认为
return (x, y) => intSelector(number, number);
返回的是intSelector(number, number)
部分。但实际上,return
关键字之后的整个事情都是返回值。你可以像这样重写它:
return (BinaryTreeNode<int> x, int y) => intSelector(number,number);
大致相当于返回一个匿名委托,其中包含两个类型为BinaryTreeNode<int>
和int
的参数,它们返回bool类型的值。所以这就是你的Func<BinaryTreeNode<int>, int, bool>
。
基本上,=>
左边的部分描述了参数,右边的部分是方法体,整个事物的返回类型是体的返回类型。
看看Eric White的Lambda Expressions article,这对你来说很有意义。