扩展方法过载选择

时间:2012-03-25 12:13:29

标签: c# .net extension-methods overloading fluent-assertions

我有两种扩展方法:

public static IPropertyAssertions<T> ShouldHave<T>(this T subject)
{
    return new PropertyAssertions<T>(subject);
}

public static IPropertyAssertions<T> ShouldHave<T>(this IEnumerable<T> subject)
{
    return new CollectionPropertyAssertions<T>(subject);
}

现在我写一些使用它的代码:

List<Customer> collection2 = new List<Customer>(); 
collection2.ShouldHave(); //first overload is chosen
IEnumerable<Customer> collection3 = new List<Customer>(); 
collection3.ShouldHave(); //second overload is chosen

仅当我明确指定IEnumerable类型时才选择第二个重载。有两种方法可以在两种情况下选择第二次重载吗?

4 个答案:

答案 0 :(得分:7)

第一个重载是更好的匹配,因为T被推断为List<Customer>,这给出了完全匹配。对于第二个重载,它会将T推断为Customer,因此参数将为IEnumerable<Customer>,这与List<Customer>不完全匹配。

答案 1 :(得分:5)

不要这么认为。不要认为在这个案例IEnumerable<T>重载总是会被调用,因为它与T类型的较少准确匹配。如果您没有指定具体的IEnumerable<T>,那么最佳匹配将始终是第一种方法,在情况下。

答案 2 :(得分:1)

ShouldHave()具有双重含义。在第一种情况下,ShouldHave()有一个关于subject-parameter提供的对象的返回。在第二种情况下,返回是关于枚举中的项目,而不是关于枚举本身。

如果我创建自己的集合并且我想测试这个集合本身(而不是项目),我当然希望调用ShouldHave(这个T主题)而不是ShouldHave(这个IEnumerable主题)。

也许你应该重新考虑你的设计。 第二个ShouldHave()做两件事,所以应该分成一个方法来提取集合项和调用你已经拥有的第一个ShouldHave()。

答案 3 :(得分:1)

在Fluent Assertion 2.0中,我终于设法以一种体面的方式解决了上述问题。在这里阅读所有相关内容: http://www.dennisdoomen.net/2012/09/asserting-object-graph-equivalence.html