【问题标题】:Extension methods with generics使用泛型的扩展方法
【发布时间】:2011-03-23 09:50:57
【问题描述】:

我正在查看this 问题,我很好奇为什么这个deos 不能编译。

鉴于此代码,谁能解释为什么对IBase.Test() 的调用无法解析为正确的扩展方法?

public interface IBase { }

public interface IChildA : IBase { }

public interface IChildB : IBase { }

public static class BaseExtensions
{
    public static IBase Test(this IBase self) { return self; }
    public static T Test<T>(this T self) where T : IChildB { return self; }
}

public static class TestClass
{
    public static void Test()
    {
        IChildA a = null; //Yeh i know its null but just testing for compile here..
        IBase firstTry = a.Test();  //Cannot resolve to BaseExtensions.Test(this IBase obj)
        IBase secondTry = ((IBase)a).Test();  //Resolves to BaseExtensions.Test(this IBase obj)

        IChildB b = null;
        IChildB touchedB = b.Test();
    }
}

我得到的错误是

Error 166 The type 'IChildA' cannot be used as type parameter 'T' in the generic type or method 'BaseExtensions.Test&lt;T&gt;(T)'. There is no implicit reference conversion from 'IChildA' to 'IChildB'.

我有一种感觉,因为它对于任何实现 IChildB 并且不知道要使用哪种扩展方法的东西都是模棱两可的,但是错误消息并没有抱怨它的那一面,如果你删除IBase firstTry = a.Test(); 行然后它编译得很好..

【问题讨论】:

  • 您的编译器错误与您发布的代码不匹配(测试与触摸)。请从您发布的 exact 代码中发布 exact 错误 - 否则我们将不知道您可能进行了哪些其他细微的更改。
  • 另请参阅blogs.msdn.com/b/ericlippert/archive/2009/12/10/…,大约有一百人告诉我这是一个明智的规则,我错了。

标签: c# .net generics extension-methods


【解决方案1】:

好的,问题是在重载解析过程中,编译器找到所有适用的候选方法没有检查方法中指定的泛型约束,选择最具体的一个,然后 检查通用约束。

在这种情况下,泛型方法比非泛型方法更具体(因为在类型参数替换之后,它实际上是一个带有IChildA 参数而不是IBase 参数的方法) - 但它随后失败了约束。

我有一个blog post 对此进行了更详细的解释,还有一个using it in a horrible way

【讨论】:

  • 啊哈,现在有道理了,我有一个 wtf 时刻 :)
  • 我浏览了第二个链接。就一个问题;为什么参数定义为T? ignored = default(T?) 而不是T ignored = default(T)?我是否忽略了某些东西,还是他们做了不同的事情?我问的原因,是因为乍一看可能会假设一个可为空的参数 is 是有效的,因为 ?
  • @Rob: 是的,关键是T 是不可为空的类型,而T? 是可空的版本...... Nullable&lt;T&gt; 上的T : struct 约束是什么强制T 在它是非结构时无效...因为 parameter 类型(替换后)会检查约束,即使类型参数本身不是。当我写邪恶的代码博客文章时,“一目了然”从来都不是一个好的起点:)
  • @JonSkeet 这些博文还在某处可用吗?
猜你喜欢
  • 2011-06-05
  • 2014-12-21
  • 1970-01-01
  • 2015-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
相关资源
最近更新 更多