c#扩展方法编译/兼容性检查基于命名空间的顺序失败
本文关键字:命名空间 顺序 失败 检查 方法 扩展 编译 兼容性 | 更新日期: 2023-09-27 18:14:16
我正在编写两个扩展方法。一种用于处理单个对象,另一种用于处理对象集合。当调用扩展方法时,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'不能用作泛型类型或方法' lang . mi . dbobjectextensions '中的类型参数'T'。populaterrelationships (T, params granda . mi . relationtoprefetch[])'。没有从"System.Collections.Generic"的隐式引用转换。把' List'列到' grand . 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);
}
为什么编译器不能找出有一个匹配的扩展方法?更令人困惑的是,如果我把其中一个方法放在不同的命名空间中,并且包含了那个命名空间,为什么编译会成功?有什么我能做的吗?
一般约束不是方法签名的一部分,所以编译器选择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>
泛型类型被限制为IDBObject,因此您可以将扩展方法设置为非泛型:
public static void PopulateRelations(this IDBObject obj, params RelationToPrefetch[] relationsToPrefetch)
{
//...
}
public static void PopulateRelations(this IEnumerable<IDBObject> objects, params RelationToPrefetch[] relationsToPrefetch)
{
//...
}
解决编译错误