为什么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);
}
答
回复作为一个答案,所以我可以粘贴一些代码...
这不是过载的数量拉塞五卡尔森建议。行为是由于铸造。请参阅下面的代码注释:
//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}");
编译器不知道什么类型的食物。
这不是Moq需要这个,它是C#编译器。 '.Returns'方法的大量重载(在我的计数中为18)可能给编译器提供了太多的选择。另外,将来如果代码无法正常工作(如在,不会编译),请发布实际的错误消息。在这种情况下,它是“无法将lambda表达式转换为'string'类型,因为它不是委托类型”。 –
@ LasseV.Karlsen公平地说,错误被嵌入到代码注释中,尽管我同意它应该更明显。 – DavidG
@ LasseV.Karlsen我明白了,但我只在Moq Returns函数中注意到这种行为,并且我很好奇编译器在没有找到合适的方法调用时会何去何从。我预计与回报中的其他一些方法有冲突,但哪一个? –