2011-05-31 71 views
4

我看到有人在Func <>模式下面写下类型。我正在尝试与Funcs和Lambdas合作,让概念正确。C#Func <>和扩展方法问题

so ExperimentalSelect返回一个Func(带有2个参数和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; 
} 

编辑:

如果一个分机。方法需要一个FUNC

IEnumerable<int> selected = tree.TakeWhile(ExperimentalSelect); 
  1. 如何在这里工作的someMethod?,它不是一个Func键<>!

  2. 是什么意思语法:(node, x) => SomeMethod(node, number, true);

哪里是在图片浏览的节点或x?

+0

请参阅我的答案更新。也许这会让事情变得更清晰。 – 2011-05-31 11:52:02

+0

@丹尼尔。我看到了。说得通。你能看到我对你答案的评论吗? – 2011-05-31 11:54:20

回答

3

您的评论以上的退货是不正确的。

intSelectorSomeMethod而不是在那里执行。只有在执行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); 
       } 

然后返回匿名方法,而不是执行它的结果。
你return语句等效于以下内容:

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。这里没有创建匿名方法。请注意0​​类型的差异。由于第一个代码仅在匿名方法的主体中执行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.为什么大?
原因是,您的匿名方法有xy作为输入参数,但它们不在其正文的任何​​位置使用。相反,您将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 

正如你看到的,我现在通过xyintSelector 。我还从ExperimentalSelect中删除了参数number,因为它没有在任何地方使用。

+0

我明白了。这些都是匿名方法返回的,对吗?和arg。类型被假定为返回Func类型。像x,y都返回intSelector。和节点x分别为SomeMethod的BinaryNode和int。这些是自动推断的。 – 2011-05-31 11:52:40

+0

@Munish:不太正确,但我在答案中解释错了,因为我忽略了你的问题。 x和y的类型从'ExperimentalSelect'的返回类型推断出来。请参阅我的答案更新。 – 2011-05-31 11:55:50

+0

@Daniel。雅这就是我的意思。 x和y从返回类型推断出来,这里的函数是Func 。 x和y应该是sourcetype1和sourcetype2的类型 – 2011-05-31 11:58:14

2

问自己 - 是这两行代码也是正确的:

Func<BinaryTreeNode<int>, int, bool> a = 
    (x, y) => intSelector(number, number); 

Func<BinaryTreeNode<int>, int, bool> b = 
    (node, x) => SomeMethod(node, number, true); 

的答案 - 是的。正如代码中的返回语句一样。

我想也许你对语法有轻微的误解,或者可能不完全了解Func究竟是什么(如果不是这种情况,道歉)。

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>

基本上,=>左边的部分描述了参数,右边的部分是方法体,整个事物的返回类型是body的返回类型。

看一看Eric White的Lambda Expressions article,这对你有意义。