两个具有相同名称的扩展方法

des*_*lsj 3 c# extension-methods

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

我能够解决以下问题:

var result = DictionaryExtensions.GetValue(myDict, 5, "baz");
Run Code Online (Sandbox Code Playgroud)

但我试图理解为什么编译器首先被混淆了.有人知道为什么吗?

Ste*_*ner 5

另一种选择是将2个Extension类分解为单独的名称空间,并且不要using在WebExtensions类消耗代码中添加类.这样编译器不会尝试解决GetValue到WebExtensions.


dan*_*wig 3

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

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

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

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

我偶尔会遇到类似 System.Runtime.Serialization、System.ServiceModel.Activation 等问题。当您有两次删除的依赖项时,可能会发生这种情况。换句话说,您的根项目依赖于一个程序集,而该程序集又依赖于另一个第三个程序集的类型。