2011-01-31 91 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以及停止它。