【问题标题】:Why does Moq sometimes require explicit type declaration in Returns?为什么 Moq 有时需要在 Returns 中明确类型声明?
【发布时间】:2018-01-22 09:55:20
【问题描述】:

为什么Returns((string food) => eat(food)) 有效,而Returns(food => eat(food)) 无效?

完整的工作示例:

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);
}

【问题讨论】:

  • 不是起订量需要这个,而是 C# 编译器。 .Returns 方法的大量重载(在我的计数中为 18 个)可能给编译器提供了太多选项。此外,将来,当代码不起作用时(如无法编译),请发布实际的错误消息。在这种情况下,它是“无法将 lambda 表达式转换为类型‘字符串’,因为它不是委托类型”。
  • @LasseV.Karlsen 公平地说,错误嵌入在代码 cmets 中,尽管我同意它应该更明显。
  • @LasseV.Karlsen 我明白了,但我只在 Moq Returns 函数中注意到了这种行为,我很好奇是什么让编译器找不到合适的调用方法。我预计与 Returns 中的其他一些方法存在冲突,但是哪个?
  • 我现在看到了,对此感到抱歉,但是,我的其余评论仍然存在,这不是起订量问题,这只是 C# 问题(尽管正如我所提到的,它可能是重载的数量会产生这个问题)。泛型的类型推断并不能解决所有问题,函数式编程的倡导者已经学会了艰难的方法,C# 编译器处理了大量的情况,但不是全部。我无法准确地告诉你哪个重载或重载组合会导致编译器出错,但我已经无数次看到这个问题了。

标签: c# generics lambda delegates moq


【解决方案1】:

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

这不是 Lasse V. Karlsen 建议的重载数量。该行为是由于铸造。请参阅下面代码中的 cmets:

//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);} 不知道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}");

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

【讨论】:

    猜你喜欢
    • 2012-08-17
    • 2012-04-05
    • 2011-04-16
    • 1970-01-01
    • 2019-11-20
    • 2020-04-19
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多