两个同名的扩展方法

本文关键字:扩展 方法 两个 | 更新日期: 2023-09-27 18:35:43

我有以下两个扩展方法(方法的主体对于我的问题不是特别重要,但无论如何都包括代码)

public static class DictionaryExtensions
{
    public static TValue GetValue<TKey, TValue>(this IDictionary<TKey, TValue> source, TKey key, TValue defaultValue)
    {
        return (source.ContainsKey(key) ? source[key] : defaultValue);
    }
}
public static class WebExtensions
{
    public static T GetValue<T>(this HttpContext context, string name, T defaultValue)
    {
        object value = context.Request.Form[name] ?? context.Request.QueryString[name];
        if (value == null) return defaultValue;
        return (T)value;
    }
}

这两种方法共享相同的名称,但它们扩展了两种非常不同的类型。我希望以下代码很简单,并且编译器能够选择适当的扩展方法:

var myDict = new Dictionary<int, string>()
{
    { 1, "foo" },
    { 2, "bar" }
};
var result = myDict.GetValue(5, "baz");

但是,由于某种未知的原因,Visual Studio 拒绝编译我的代码,并出现以下编译时错误:"类型'System.Web.HttpContext'是在未引用的程序集中定义的。您必须添加对程序集'System.Web'的引用。此错误告诉我编译器在 WebExtensions 类中选择了 GetValue 扩展方法,而不是 DictionaryExtension 类中的方法。

我能够通过以下方式解决问题:

var result = DictionaryExtensions.GetValue(myDict, 5, "baz");

但我试图理解为什么编译器首先感到困惑。有人知道为什么吗?

两个同名的扩展方法

另一种选择是将 2 个扩展类分解为单独的命名空间,并且不要WebExtensions 类驻留在使用代码中的位置添加 using 语句。 这样编译器就不会尝试将GetValue解析为WebExtensions

只需按照编译器所说的操作并添加对 System.Web.dll 的引用。然后它应该编译。

存在这些扩展方法类的外部程序集依赖于 System.Web.dll。编译器应该能够找出重载,但为了做到这一点,它需要引用HttpContext存在的程序集,即 System.Web.dll。

另一方面,如果您不希望使用扩展方法程序集的项目依赖于 System.Web.dll,则需要在单独的程序集中定义这两个扩展方法类。

@Steve Danner 也有一个很好的解决方案:将两个扩展方法类放入同一程序集中的不同命名空间中,并省略包含 WebExtensions 类的命名空间的 using 语句。

我偶尔会遇到诸如System.Runtime.Serialization,System.ServiceModel.Activation等内容。当您的依赖项被删除两次时,可能会发生这种情况。换句话说,根项目依赖于一个程序集,该程序集依赖于另一个程序集的类型。