2011-01-31 106 views
0

我有这些扩展方法:匹配错误的扩展方法

public static void Replace<T>(this IList list, T newItem) 

public static void Replace<T>(this IList<T> list, IEnumerable newItems) 

public static void Replace<T>(this IList<T> list, IEnumerable<T> newItems) 

我有产生IList<IWell>叫,井LINQ的声明。 (我在运行时井是IEnumerable<IWell>确认。)

然而,该声明

SelectedValues.Replace(wells); 

总是命中第一个扩展方法,而不是第二或第三。 (我在运行时确认SelectedValues是IList<IWell>。)

是否显而易见我在做什么错?

回答

1

SelectedValueswells的声明类型是什么?扩展方法在编译时绑定,而不是在运行时绑定,因此它是编译时类型的问题。

编辑:既然你说SelectedValues被声明为IList类型,为您提供的三个SelectedValues用作扩展方法唯一可能的候选人是

public static void Replace<T>(this IList list, T newItem) 

然后,编译器意识到它可以考虑wells作为TT是的wells声明类型,然后可以调用方法

public static void Replace<T>(this IList list, T newItem) 

其中SelectedValues填写参数listwells填写参数newItem,并且声明的类型为wells填充为类型参数T。这就是调用该扩展方法的原因。

同样,扩展方法在编译时绑定。如果要调用其他方法,则需要为SelectedValues使用不同的声明类型。

因此,这不是编译器的“匹配错误的扩展方法”的情况,这是编译器匹配唯一可能的扩展方法的情况。此行为是设计使然;这是一个功能,而不是一个错误。

+0

SelectedValues被声明为IList。 – 2011-01-31 20:18:56

+0

@凯利:那么你的答案就在那里。由于它被声明为'IList`类型,唯一的候选扩展方法是`public static void Replace (this IList list,T newItem)``。其他两个甚至从来没有被编译器考虑过。我会在编辑中详细说明一下。 – jason 2011-01-31 20:23:10

0

我不记得过载偏好的规则,但作为一个解决方案,指定(多余的)投通常会解决这些:

SelectedValues.Replace((IEnumerable<IWell>)wells); 
+0

当您收到编译时警告时,是否使用`#pragma`来禁用,或者找出根本原因? – jason 2011-01-31 20:09:46

0

这里有趣的类型不是SelectedValues,但wells - 其中TIEnumerableIEnumerable<T>是吗?如果您始终使用第一种方法,那么尽管名称有复数形式,但很可能是wells只是一个单独的T实例。

而且,它会很高兴知道究竟SelectedValues是什么类型 - 它实现IList<IWell>事实不从实施IList以及停止它。