简体   繁体   English

当存在非静态,更合适的方法时,如何使用动态参数调用静态方法?

[英]How to invoke static method with dynamic argument when a non-static, better-fit method exists?

Inspired by this question I have tried a following code on Mono 2.10.9 and Visual Studio 2010: 这个问题的启发,我在Mono 2.10.9和Visual Studio 2010上尝试了以下代码:

public class Example
{
    public static void Main()
    {
        Foo(1);
    }

    public static void Foo( dynamic x )
    {
        Example.Bar(x);
    }

    static void Bar( dynamic x )
    {
        x++;
    }

    int count;
    void Bar( int x )
    {
        count++;
    }
}

As you can see, Foo is static, so it can only access static Bar - and I explicitly invoke the static version! 如您所见, Foo是静态的,因此它只能访问静态Bar - 我明确地调用静态版本!

I know that I would not be able to declare static void Bar( int x ) , because a non-static version exists. 我知道我无法声明static void Bar( int x ) ,因为存在非静态版本。

However, changing the argument type of non-static Bar to, let's say, string, makes everything alright. 但是,将非静态Bar的参数类型更改为,例如string,可以使一切正常。

Why is that? 这是为什么? What are the rules here? 这里的规则是什么? Is it possible to call the static method? 是否可以调用静态方法?

Maybe it's a Mono DLR issue? 也许这是单声道DLR问题?

EDIT: For clarification. 编辑:澄清。 I would like to know what rules turn an explicit call to static method (at least I think it's explicit) into a call to a non-static one ? 我想知道什么规则将对静态方法的显式调用 (至少我认为是显式的)转换为对非 静态方法调用 This is obviously impossible from static context. 这在静态环境中显然是不可能的。

Or, if there are no such rules, can it be a bug ? 或者,如果没有这样的规则,它可能是一个错误吗? Can this behaviour be somehow avoided? 可以以某种方式避免这种行为吗?

The key statement there is that "I know that I would not be able to declare static void Bar( int x ), because a non-static version exists.". 关键声明是“我知道我无法声明静态void Bar(int x),因为存在非静态版本。” Using the dynamic keyword defers the overload resolution to run-time, but it doesn't exempt you from that rule when run-time comes along. 使用dynamic关键字会将重载决策推迟到运行时,但在运行时出现时,它不会使您免于该规则。

When that overload resolution finally occurs, the DLR evaluates all the options available and then chooses the best one. 当最终发生重载解析时,DLR会评估所有可用选项,然后选择最佳选项。 Until this resolution-time, parameters of dynamic type behave much like being of type object (see here ). 在此分辨率时间之前,动态类型的参数与类型对象的行为非常相似(请参见此处 )。 So normally the more specific method that takes an int would be the winner in the overoad resolution and thus be chosen over the one that takes a dynamic/object. 因此,通常采用int的更具体的方法将是overoad分辨率的赢家,因此选择采用动态/对象的方法。 This means that the instance method would normally win. 这意味着实例方法通常会获胜。 The DLR knows that two methods with the same signature cannot vary by staticness. DLR知道具有相同签名的两种方法不能因静态而变化。 When evaluating the options available, what you are expecting it to do is say "aha! In this case, static void Bar(dynamic x) can be interpreted as static void Bar(int x)". 在评估可用选项时,您期望它做的是“aha!在这种情况下,静态void Bar(动态x)可以解释为static void Bar(int x)”。 However, if it did say that, then the rule about not having otherwise identical static and non-static methods would be violated. 但是,如果它确实这样说,那么将违反关于不具有其他相同的静态和非静态方法的规则。 It's internal list of options would contain the static and non-static Bar methods, both of which would have the same signature. 它的内部选项列表将包含静态和非静态Bar方法,两者都具有相同的签名。 So it can't say that. 所以不能这么说。 This leaves the only other option, which happens to be an instance method. 这留下了唯一的其他选项,恰好是实例方法。 This is no use in the circumstances so the DLR throws a RuntimeBinderException. 在这种情况下没有用,因此DLR会抛出RuntimeBinderException。 If you change the parameter of the instance Bar to something other than an int, then the method signatures do not clash, so the DLR can interpret the static dynamic Bar as taking an int and select that overload instead. 如果将实例Bar的参数更改为int以外的其他值,则方法签名不会发生冲突,因此DLR可以将静态动态Bar解释为采用int并选择该重载。

    static void Bar( dynamic x )
    {
        x++;
    }

    int count;
    void Bar( int x )
    {
        count++;
    }

the static function can be seen as (so any call to the static method with a int type parameter will invoke the non-static, better-fit method): 静态函数可以看作是(所以使用int类型参数调用静态方法将调用非静态,更合适的方法):

    static void Bar( dynamic x )
    {
        if (x is Int)
           Bar(x); //Count++

        else
           x++;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM