我正在编写两个扩展方法,一个用于单个对象,另一个用于对象集合。当调用这些扩展方法时,C#编译器似乎会混淆使用哪一个,并且导致编译失败。
更令人惊讶的是,如果我将这些扩展方法移动到不同的命名空间中,即使在调用点包含这两个命名空间,只有当命名空间按字母顺序排序时,编译才会失败 - 切换命名空间会导致编译成功。
以下是代码:
更令人惊讶的是,如果我将这些扩展方法移动到不同的命名空间中,即使在调用点包含这两个命名空间,只有当命名空间按字母顺序排序时,编译才会失败 - 切换命名空间会导致编译成功。
以下是代码:
public static class DBObjectExtensions
{
public static void PopulateRelations<T>(this T obj, params RelationToPrefetch[] relationsToPrefetch) where T : IDBObject
{
if (obj == null)
{
return;
}
obj.Transaction.PopulateRelations<T>(new[]{ obj }, relationsToPrefetch);
}
public static void PopulateRelations<T>(this IEnumerable<T> objects, params RelationToPrefetch[] relationsToPrefetch) where T : IDBObject
{
var first = objects.FirstOrDefault();
if (first == null)
{
return;
}
first.Transaction.PopulateRelations<T>(objects, relationsToPrefetch);
}
}
这是导致编译失败的调用站点代码行:
List<ITable> list = ... // ITable inherits from IDBObject
list.PopulateRelations(xxx);
出现错误CS0311:
类型'System.Collections.Generic.List'无法用作泛型类型或方法'Granta.MI.DBObjectExtensions.PopulateRelations(T, params Granta.MI.RelationToPrefetch[])'中的类型参数'T'。从'System.Collections.Generic.List'到'Granta.MI.IDBObject'不存在隐式引用转换。
请注意,如果我删除第二个扩展方法,则此行编译成功。
还要注意编写跳板方法(对于每种可能的集合类型...)也可以正常工作:
public static void PopulateRelations<T>(this List<T> objects, params RelationToPrefetch[] relationsToPrefetch) where T : IDBObject
{
((IEnumerable<T>)objects).PopulateRelations(relationsToPrefetch);
}
public static void PopulateRelations<T>(this IList<T> objects, params RelationToPrefetch[] relationsToPrefetch) where T : IDBObject
{
((IEnumerable<T>)objects).PopulateRelations(relationsToPrefetch);
}
为什么编译器无法找到匹配的扩展方法?更令人困惑的是,如果我将其中一个方法放在不同的命名空间中,并包含该命名空间,那么为什么编译就会成功呢?有没有什么办法可以解决这个问题呢?
T
,为什么您需要在扩展中使用T
而不是只使用IDbObject
? - JclT
的使用感到困惑,就像你所说的,如果在扩展方法中不需要T
,只需像 @jakub-lortz 的回答中那样简单地更改方法即可。 - mijailTransaction.PopulateRelations
也需要一个类型 T,然后调用typeof
,所以我需要那个 T 是一个具体的类型,而不仅仅是IDBObject
。 - Michael Parker