2017-08-14 52 views
0

爲什麼這個工作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函數中注意到這種行爲,並且我很好奇編譯器在沒有找到合適的方法調用時會何去何從。我預計與回報中的其他一些方法有衝突,但哪一個? –

回答

1

回覆作爲一個答案,所以我可以粘貼一些代碼...

這不是過載的數量拉塞五卡爾森建議。行爲是由於鑄造。請參閱下面的代碼註釋:

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

編譯器不知道什麼類型的食物。

相關問題