通用重载方法解析问题
我有两种使用这些签名的方法:
void Method(T data) { } void Method(IEnumerable data) { }
它采用相同方法的重载来获取单个对象或它们的列表。 如果我尝试将List 传递给它,它会解析为第一种方法,当我想要第二种方法时。 我必须使用list.AsEnumerable()来解决它的问题。 无论列表是类型T [],IList ,List ,Collection ,IEnumerable 等,有没有办法让它解决到秒。
最好的解决方案:首先不要去那里 。 这是一个糟糕的设计 。 您会注意到没有一个框架类可以做到这一点。 列表有两种方法:Add和AddRange。 第一个添加一个项目,第二个添加一系列项目。
这是一个糟糕的设计,因为您正在编写一个自动生成错误的设备 。 再次考虑一个可变列表的例子:
List
您希望在查询列表中添加两个查询; 如果Add重载以获取序列,那么这会将查询结果添加到列表中,而不是查询。 您需要能够区分查询及其结果 ; 它们在逻辑上完全不同。
最好的办法是使方法有两个不同的名称。
如果你对这个糟糕的设计感到害怕,那么当你这样做时会受到伤害,不要这样做 。 过载分辨率旨在找到最佳匹配 。 不要试图锤击过载分辨率,以便它做更糟糕的事情。 再次,这是令人困惑和容易出错的。 使用其他一些机制解决问题。 例如:
static void Frob(IEnumerable ts) // not generic! { foreach(object t in ts) Frob(t); } static void Frob(T t) { if (t is IEnumerable) Frob((IEnumerable) t); else // otherwise, frob a single T. }
现在无论用户给你什么 – 一个T数组,一个T列表数组,无论如何,你最终只会擦拭单个Ts。
但同样,这几乎肯定是一个坏主意 。 不要这样做。 具有不同语义的两种方法应该具有不同的名称 。
取决于你是否这样做:
var list = new List(); Method>(list); // Will resolve to the first overload.
要么:
var list = new List(); Method (list); // Will resolve to the second overload.
发生这种情况的原因是,编译器会选择最具体的方法,因此在使用通用Method
的地方,它被编译为Method
,这比>(List
IEnumerable
更具体
重载决策将尝试找到最佳匹配过载。
在IEnumerable
重载的情况下,您确实需要显式转换或使用IEnumerable
,因为那样确实是最佳匹配。
否则,简单的generics重载将被视为更好的匹配。
有关更多详细信息,请阅读Eric Lippert的“重载决议”博客条目。
有一些方法可以采取单一事物或一组事物的重载是不寻常的,不是吗? 为什么不呢
void MethodSingle(T data) { Method(new T[] { data }); } void Method (IEnumerable data) { }
我建议,对编译器和阅读器都比较清楚。
问:
无论列表是类型T [],IList <'T>,List <'T>,Collection <'T>,IEnumerable <'T>等,有没有办法让它解决到秒。
T []不是列表而是数组,所以可能没有。
我不确定这会有所帮助,但您可以尝试创建一个有限制的方法
public void Method (U date) where U : IList { /* ... */ }
为什么不这样扩展方法:
void Method(T data) { var enumerable = data as IEnumerable ; if(enumerable != null) { Method(enumerable); return; } ... }