为什么以下测试失败?
[TestClass]
public class DynamicTests
{
public class ListOfIntsTotaller
{
public float Total(List<int> list) { return list.Sum(); }
}
public static class TotalFormatter
{
public static string GetTotal(IEnumerable list, dynamic listTotaller)
{
// Get a string representation of a sum
return listTotaller.Total(list).ToString();
}
}
[TestMethod]
public void TestDynamic()
{
var list = new List<int> { 1, 3 };
var totaller = new ListOfIntsTotaller();
Assert.AreEqual("4", totaller.Total(list).ToString()); // passes
Assert.AreEqual("4", TotalFormatter.GetTotal(list, totaller)); // fails
}
}
出现以下错误:
Test method MyTests.DynamicTests.TestDynamic threw exception:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: The best overloaded method match for 'MyTests.DynamicTests.ListOfIntsTotaller.Total(System.Collections.Generic.List<int>)'
has some invalid arguments
绑定器是否应该足够聪明以使list
与其基础类型List<int>
匹配,从而成功绑定到GetTotal
方法?
答案 0 :(得分:5)
问题是list
方法中的GetTotal
不是List<int>
。
动态调用是根据您使用的变量的类型确定的,而不是它指向的对象的实际类型。方法Total
需要List<int>
,而不是IEnumerable
。
答案 1 :(得分:4)
这是因为在调用函数Total时,IEnumerable无法转换为List类型。
List implements IList<T>, ICollection<T>,
IEnumerable<T>, IList, ICollection, IEnumerable
传递
IEnumerable<int>
同时总计和 GetTotal 都可以解决问题。
答案 2 :(得分:2)
这是因为你无法从IEnumerable
转变为List<int>
请尝试使用此行代替
public float Total(IEnumerable<int> list) { return list.Sum(); }
所以这不是你的动态失败,而是函数调用没有传入有效的参数
答案 3 :(得分:1)
这是对Guffa答案的补充(仍然完全有效)。
就像afeygin一样,我认为动态调用会检查正确的底层类型 但在我的情况下,由于缺乏信息,我没有机会修改界面。
以下是例子:
// I know that doit will be a certain type like MyDoIt but i can't know the actual type
// The only information I have is that MyDoIt is implementing IToBeDone
public void DoIt(IToBeDone doit)
{
// I know that _doItInstance.DoIt will expect MyDoIt but can't know the actual
// type here so this will throw
_doItInstance.DoIt(doit);
}
这是一个解决方法:
public void DoIt(IToBeDone doit)
{
// this will cause that IToBeDone won't be used for type resolution but the real
// type instead (in my case MyDoIt)
dynamic dynDoit = doit;
_doItInstance.DoIt(dynDoit);
}