C#中的扩展方法重载,它有效吗?

pup*_*eno 6 .net extension-methods .net-3.5 c#-3.0

有一个有一个方法的类,如下所示:

class Window {
    public void Display(Button button) {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

是否有可能用另一个更广泛的方法重载该方法,如下所示:

class WindowExtensions {
    public void Display(this Window window, object o) {
        Button button = BlahBlah(o);
        window.Display(button);
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试时发生的事情是我有无限的递归.有没有办法让这项工作?我希望只有在无法调用其他方法时才调用扩展方法.

jas*_*son 9

我们来看看规范吧.首先,我们必须了解方法调用的规则.粗略地说,您从您尝试调用方法的实例指示的类型开始.您继续沿着继承链寻找可访问的方法.然后,您执行类型推断和重载解析规则,并在成功时调用该方法.只有在找不到这样的方法时,才会尝试将该方法作为扩展方法处理.所以从§7.5.5.2(扩展方法调用)看,特别是粗体语句:

在其中一个表单的方法调用(第7.5.5.1节)中

expr.identifier()

expr.identifier(args)

expr.identifier<typeargs>()

expr.identifier<typeargs>(args)

如果调用的正常处理找不到适用的方法,则尝试将该构造作为扩展方法调用进行处理.

除此之外的规则有点复杂,但对于简单的情况,你已经呈现给我们这很简单.如果没有适用的实例方法,则将WindowExtensions.Display(Window, object)调用扩展方法.如果参数to Window.Display是按钮或可隐式地转换为按钮,则实例方法适用.否则,将调用扩展方法(因为从中派生的所有内容都object可以隐式地转换为a object).

所以,除非有一点重要,否则你要做的就是工作.

因此,请考虑以下示例:

class Button { }
class Window {
    public void Display(Button button) {
        Console.WriteLine("Window.Button");
    }
}

class NotAButtonButCanBeCastedToAButton {
    public static implicit operator Button(
        NotAButtonButCanBeCastedToAButton nab
    ) {
        return new Button();
    }
}

class NotAButtonButMustBeCastedToAButton {
    public static explicit operator Button(
        NotAButtonButMustBeCastedToAButton nab
    ) {
        return new Button();
    }
}

static class WindowExtensions {
    public static void Display(this Window window, object o) {
        Console.WriteLine("WindowExtensions.Button: {0}", o.ToString());
        Button button = BlahBlah(o);
        window.Display(button);
    }
    public static Button BlahBlah(object o) {
        return new Button();
    }
}

class Program {
    static void Main(string[] args) {
        Window w = new Window();
        object o = new object();
        w.Display(o); // extension
        int i = 17;
        w.Display(i); // extension
        string s = "Hello, world!";
        w.Display(s); // extension
        Button b = new Button();
        w.Display(b); // instance
        var nab = new NotAButtonButCanBeCastedToAButton();
        w.Display(b); // implicit cast so instance
        var nabexplict = new NotAButtonButMustBeCastedToAButton();
        w.Display(nabexplict); // only explicit cast so extension
        w.Display((Button)nabexplict); // explictly casted so instance
    }
}
Run Code Online (Sandbox Code Playgroud)

这将打印

WindowExtensions.Button: System.Object
Window.Button
WindowExtensions.Button: 17
Window.Button
WindowExtensions.Button: Hello, world!
Window.Button
Window.Button
Window.Button
WindowExtensions.Button: NotAButtonButMustBeCastedToAButton
Window.Button
Window.Button
Run Code Online (Sandbox Code Playgroud)

在控制台上.


Mar*_*rth 0

这是不可能的(另请参阅Monkeypatching For Humans) - 也许使用 DLR 和method_missing.