6

从实现者调用适用于接口的扩展方法似乎需要使用 this 关键字。这似乎很奇怪。

有谁知道为什么?

有没有更简单的方法来获得接口的共享实现?

这让我很恼火,因为我正在遭受多重继承/混合退出。

玩具示例:

public interface ITest
{
    List<string> TestList { get; }
}

public static class TestExtensions
{
    private const string Old = "Old";
    private const string New = "New";

    public static void ManipulateTestList(this ITest test)
    {
        for (int i = 0; i < test.TestList.Count; i++)
        {
            test.TestList[i] = test.TestList[i].Replace(Old, New);
        }
    }
}

public class Tester : ITest
{
    private List<string> testList = new List<string>();
    public List<string> TestList
    {
        get { return testList; }
    }

    public Tester()
    {
        testList.Add("OldOne");
        testList.Add("OldTwo");

        // Doesn't work
        // ManipulateTestList();

        // Works
        this.ManipulateTestList();
    } 
}
4

3 回答 3

4

我直接向语言团队提出了这个确切的问题。我手头没有电子邮件,但基本上答案(来自 Mads,IIRC)是:

  • 减少搜索空间/复杂性 - 即不必考虑所有可用的扩展方法(并修剪它们),除非首先有表达式。
  • 减少扩展方法意外“接管”常规方法(即更好的匹配)的机会

就个人而言,我希望它能够始终如一地工作 - 第一个似乎不是一个大问题(但是,我不编写编译器),并且两者都没有接近通常this.*是可选事物的事实(可能会产生影响)作为本地代码样式指南,即“你应该使用this.”)。

于 2010-09-15T06:57:12.517 回答
3

语言规范中的相关部分说:

7.6.5.2 扩展方法调用

在其中一种形式的方法调用(§7.5.5.1)中

  • expr . 标识符 ( )
  • expr . 标识符 ( 参数 )
  • expr . 标识符 < 类型参数 > ( )
  • expr . 标识符 < typeargs > ( args )

如果调用的正常处理未找到适用的方法,则尝试将构造作为扩展方法调用进行处理。如果expr或任何args 具有 compile-time type dynamic,则扩展方法将不适用。

这清楚地表明扩展方法只能在表达式(expr)上调用。这个表达式当然可以是“<code>this”,但它必须存在。

于 2010-09-15T06:32:54.573 回答
1

扩展方法是一种编译器技巧,适用于将调用重定向到另一个静态类中的静态方法的对象。'这个。是编译器传递静态方法的对象。非工作示例只是编译器告诉您该方法不是该方法,并且实例方法仅限于该类。

于 2010-09-15T06:30:58.163 回答