为什么Moq有时需要在返回中显式的类型声明?

问题描述:

为什么这个工作Returns((string food) => eat(food))虽然这不:Returns(food => eat(food))为什么Moq有时需要在返回中显式的类型声明?

全部工作示例:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var animal = new Mock<IAnimal>(); 
     Func<string, string> eat = food => $"Nom nom nom {food}"; 

     // works 
     animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(eat); 

     // works 
     animal.Setup(a => a.Eat(It.IsAny<string>())).Returns((string food) => eat(food)); 

     //cannot convert lambda expression to type 'string' because it is not a delegate type 
     animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(food => eat(food)); 

     //cannot convert lambda expression to type 'string' because it is not a delegate type 
     animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(food => $"Nom nom nom {food}"); 
    } 
} 

public interface IAnimal 
{ 
    string Eat(string food); 
} 
+1

这不是Moq需要这个,它是C#编译器。 '.Returns'方法的大量重载(在我的计数中为18)可能给编译器提供了太多的选择。另外,将来如果代码无法正常工作(如在,不会编译),请发布实际的错误消息。在这种情况下,它是“无法将lambda表达式转换为'string'类型,因为它不是委托类型”。 –

+0

@ LasseV.Karlsen公平地说,错误被嵌入到代码注释中,尽管我同意它应该更明显。 – DavidG

+0

@ LasseV.Karlsen我明白了,但我只在Moq Returns函数中注意到这种行为,并且我很好奇编译器在没有找到合适的方法调用时会何去何从。我预计与回报中的其他一些方法有冲突,但哪一个? –

回复作为一个答案,所以我可以粘贴一些代码...

这不是过载的数量拉塞五卡尔森建议。行为是由于铸造。请参阅下面的代码注释:

//works because "eat" knows it's own input type 
animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(eat); 

// works because you are explicitly typing input param 
animal.Setup(a => a.Eat(It.IsAny<string>())).Returns((string food) => eat(food)); 

然而,事情变得有点棘手,当你使用lambda表达式,因为lambda表达式实际上并没有输入型

animal.Setup(a => a.Eat(It.IsAny<string>())).Returns((string food) => eat(food)); 
// is equivalent to: 
animal.Setup(a => a.Eat(It.IsAny<string>())).Returns((string food) => {return eat(food); }); 

{return eat(food);}没有按” t知道什么类型food是。

因此,当你调用

animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(food => eat(food)); 
animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(food => $"Nom nom nom {food}"); 

编译器不知道什么类型的食物。