为什么C#编译器没有故障代码,其中一个静态方法调用一个实例方法?(Why does the C# c

2019-08-01 08:55发布

下面的代码有一个静态方法, Foo()调用实例方法Bar()

public sealed class Example
{
    int count;

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

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

它编译没有错误*但产生在运行时运行时绑定异常。 删除动态参数,这些方法会导致编译器错误,符合市场预期。

那么,为什么有一个动态参数允许代码被编译? ReSharper的不显示为错误要么。

编辑1:*在Visual Studio 2008

编辑2:增加了sealed ,因为它可能是一个子类可以包含一个静态的Bar(...)方法。 当它是不可能的,除实例方法之外的任何方法可以在运行时调用,即使密封版本编译。

Answer 1:

出于某种原因,重载总会发现检查静态与非静态的最佳匹配。 请试试这个代码与所有的静态类型:

class SillyStuff
{
  static void SameName(object o) { }
  void SameName(string s) { }

  public static void Test()
  {
    SameName("Hi mom");
  }
}

这不会编译,因为最好的过载是一个走一个string 。 但是,嘿,这是一个实例方法,所以编译器抱怨(而不是采取的第二个最好的过载)。

另外:所以我认为的解释dynamic原来的问题的例子是,为了保持一致,当类型是动态的,我们也要先找到最好的过载(只检查参数编号和类型等,而不是静态对比非静态), 然后才是检查静态的。 但是,这意味着,静态检查必须等待,直到运行时。 因此,观察到的行为。

晚此外:为什么他们选择做的事情这个有趣的顺序可以从推断有些背景由埃里克利珀这个博客帖子 。



Answer 2:

FOO具有参数“X”表示是动态的,这意味着酒吧(x)是一个动态的表达。

这将是完全可能例如有这样的方法:

static Bar(SomeType obj)

在这种情况下,正确的方法将得到解决,因此,声明栏(x)是完全合法的。 有一个实例方法吧(x)的事实无关紧要,甚至没有考虑: 通过定义 ,因为酒吧(x)是一个动态的表达,我们已经推迟到运行时决定。



Answer 3:

“动态”表达会在运行时绑定,因此,如果你定义一个静态方法与正确的签名或一个实例方法,编译器不会检查它。

“正确”的方法将在运行期间确定。 编译器无法知道,如果在运行时有一个有效的方法存在。

“动态”关键字的动态和脚本语言,该方法可以在任何时间,即使在运行时进行定义,定义。 疯狂的事情

这里负责处理,因为该方法的整数,但没有琴弦,一个样品上的实例。

class Program {
    static void Main(string[] args) {
        Example.Foo(1234);
        Example.Foo("1234");
    }
}
public class Example {
    int count;

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

    public static void Bar(int a) {
        Console.WriteLine(a);
    }

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

您可以添加处理所有“错误”的呼叫的方法,它无法处理

public class Example {
    int count;

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

    public static void Bar<T>(T a) {
        Console.WriteLine("Error handling:" + a);
    }

    public static void Bar(int a) {
        Console.WriteLine(a);
    }

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


文章来源: Why does the C# compiler not fault code where a static method calls an instance method?