Mic*_*ker 5 c# generics extension-methods
我正在写两种扩展方法.一个用于处理单个对象,另一个用于处理对象集合.在调用扩展方法时,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);
}
}
Run Code Online (Sandbox Code Playgroud)
这是编译失败的callsite行:
List<ITable> list = ... // ITable inherits from IDBObject
list.PopulateRelations(xxx);
Run Code Online (Sandbox Code Playgroud)
失败,错误CS0311:
类型'System.Collections.Generic.List'不能用作泛型类型或方法'Granta.MI.DBObjectExtensions.PopulateRelations(T,params Granta.MI.RelationToPrefetch [])'中的类型参数'T'.没有从'System.Collections.Generic.List'到'Granta.MI.IDBObject'的隐式引用转换.
请注意,如果我删除第二个扩展方法,此行将成功编译.
另请注意,编写trampoline方法(对于每种可能的集合类型......)也有效:
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);
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器无法找出匹配的扩展方法?更令人困惑的是,如果我将其中一个方法放在不同的命名空间中,并且我包含该命名空间,为什么编译会成功呢?有什么办法可以解决这个问题吗?
通用约束不是方法签名的一部分,因此编译器选择它是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
}
Run Code Online (Sandbox Code Playgroud)
调用时选择第一个:
List<ITable> list;
PopulateRelations(list, something); // Not calling as extension method to more clear
Run Code Online (Sandbox Code Playgroud)
因为list直接匹配List<ITable>
| 归档时间: |
|
| 查看次数: |
124 次 |
| 最近记录: |