我正在编写两种扩展方法。一个用于处理单个对象,另一个用于处理对象集合。在调用扩展方法时,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);
}
}
这是编译失败的callsite行:
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);
}
为什么编译器无法找出匹配的扩展方法?更令人困惑的是,如果我将其中一个方法放在不同的命名空间中,并且我包含该命名空间,为什么编译会成功呢?我能做些什么来解决这个问题吗?
答案 0 :(得分:2)
通用约束不是方法签名的一部分,因此编译器选择PopulateRelations<T>(this T obj, params RelationToPrefetch[] relationsToPrefetch)
因为T
的派生程度高于IEnumerable<T>
。
示例,介于这两种方法之间:
public static void PopulateRelations(this List<ITable> obj, params RelationToPrefetch[] relationsToPrefetch)
{
// Do something
}
public static void PopulateRelations(this IEnumerable<ITable> objects, params RelationToPrefetch[] relationsToPrefetch)
{
// Do something
}
在致电时选择第一个:
List<ITable> list;
PopulateRelations(list, something); // Not calling as extension method to more clear
因为list
与List<ITable>
答案 1 :(得分:0)
您的泛型类型被约束为IDBObject,因此您可以将扩展方法设为非泛型:
public static void PopulateRelations(this IDBObject obj, params RelationToPrefetch[] relationsToPrefetch)
{
//...
}
public static void PopulateRelations(this IEnumerable<IDBObject> objects, params RelationToPrefetch[] relationsToPrefetch)
{
//...
}
它解决了编译错误。