【问题标题】:Matching wrong Extension method匹配错误的扩展方法
【发布时间】:2011-01-31 20:00:44
【问题描述】:

我有这些扩展方法:

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 )

我有一个 Linq 语句,它产生一个名为 wells 的 IList&lt;IWell&gt;。 (我在运行时确认 wells 是 IEnumerable&lt;IWell&gt;。)

然而,声明

SelectedValues.Replace( wells );

总是点击第一个扩展方法,而不是第二个或第三个。 (我在运行时确认 SelectedValues 是 IList&lt;IWell&gt;。)

我做错了什么很明显吗?

【问题讨论】:

    标签: linq c#-3.0 extension-methods


    【解决方案1】:

    SelectedValueswells 的声明类型是什么?扩展方法是在编译时绑定的,而不是在运行时绑定的,所以重要的是编译时类型。

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

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

    然后编译器意识到它可以将wells 视为T,其中Twells 的声明类型,然后可以调用该方法

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

    其中SelectedValues填写参数listwells填写参数newItemwells的声明类型填写类型参数T。这就是调用扩展方法的原因。

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

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

    【讨论】:

    • SelectedValues 被声明为 IList。
    • @Kelly:那么你的答案就在那里。由于它被声明为IList 类型,唯一的候选扩展方法是public static void Replace&lt;T&gt;(this IList list, T newItem)。编译器甚至从不考虑其他两个。我会在编辑中详细说明。
    【解决方案2】:

    我不记得重载偏好的规则,但作为一种解决方案,指定(多余的)强制转换通常可以解决这些问题:

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

    【讨论】:

    • 当您收到编译时警告时,您是使用#pragma 禁用,还是找出根本原因?
    • @Jason:我相信在这方面比我受过更好教育的人会发布一个详细说明为什么会发生这种情况的答案。
    • 这行得通,在我添加了一个新方法后, public static void Replace( this IList list, IEnumerable newItems ) 并且由于我是本地的,所以我从 IList 更改了它的声明 到 IEnumerable。这也有效,没有演员表。那么,所有参数类型都必须完全匹配,而不考虑它们继承了哪些类或实现了哪些接口?
    • @Kelly:为什么请看我的回答:stackoverflow.com/questions/4855465/….
    • 谢谢马蒂;你的回答让我走了,然后杰森填写了“为什么”。
    【解决方案3】:

    这里有趣的类型不是SelectedValues,而是wells——是TIEnumerable还是IEnumerable&lt;T&gt;中的哪一个?如果您总是使用第一种方法,那么wells(尽管它的名称是复数形式)很可能只是一个 T 实例。

    另外,很高兴确切地知道SelectedValues 是什么类型 - 它实现了IList&lt;IWell&gt; 的事实并不能阻止它实现IList

    【讨论】:

    • wells 是 IList,我确保它总是有多个项目。
    猜你喜欢
    • 1970-01-01
    • 2012-02-08
    • 2012-04-09
    • 1970-01-01
    • 2017-06-01
    • 1970-01-01
    • 2020-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多