【问题标题】:C# Method Resolution, long vs intC# 方法解析,long 与 int
【发布时间】:2011-09-01 19:21:31
【问题描述】:
class foo
{
  public void bar(int i) { ... };
  public void bar(long i) { ... };
}


foo.bar(10);

我希望这段代码会给我一些错误,或者至少是一个警告,但不是这样......

什么版本的 bar() 被调用,为什么?

【问题讨论】:

    标签: c# methods resolution


    【解决方案1】:

    正在调用 bar 的 int 版本,因为 10 是一个 int 字面量,编译器将寻找与输入变量最匹配的方法。要调用长版本,您需要指定一个长文本,如下所示:foo.bar(10L);

    这里是 Eric Lippert 的一篇关于更复杂的方法重载版本的帖子。我会尝试解释它,但他做得更好,我可以做到:http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx

    来自 C# 4.0 规范:

    方法重载允许多个 同一类中的方法具有 相同的名称,只要它们具有唯一性 签名。当编译一个 调用重载方法, 编译器使用重载决议 确定具体方法 调用。重载解析发现 一种最匹配的方法 如果没有参数或报告错误 可以找到单个最佳匹配。这 以下示例显示重载 决议生效。评论为 Main 方法中的每次调用 显示实际上是哪种方法 调用。

     class Test {   
          static void F() {
            Console.WriteLine("F()");   
          }     
          static void F(object x) {
            Console.WriteLine("F(object)");     
          }
          static void F(int x) {
            Console.WriteLine("F(int)");    
          }
          static void F(double x) {
            Console.WriteLine("F(double)");     
          }
          static void F<T>(T x) {
            Console.WriteLine("F<T>(T)");   
          }
          static void F(double x, double y) {
            Console.WriteLine("F(double,double)");  
          }     
    
          static void Main() {
            F();                // Invokes F()
            F(1);           // Invokes F(int)
            F(1.0);         // Invokes F(double)
            F("abc");       // Invokes F(object)
            F((double)1);       // Invokes F(double)
            F((object)1);       // Invokes F(object)
            F<int>(1);      // Invokes F<T>(T)
            F(1, 1);        // Invokes F(double, double)
          } 
    }
    

    如示例所示,一个特定的 方法总是可以选择 将参数显式转换为 确切的参数类型和/或 显式提供类型参数。

    【讨论】:

    • 幸运的是,这是一个特别奇怪和不切实际的过载解决问题示例(在您提供给我博客的链接中)。希望在现实生活中几乎没有人真正遇到过这个问题。
    • 我真正喜欢这篇文章的地方在于,它展示了表面上看起来很简单的东西如何变成极其复杂的东西。简而言之,重载解决似乎很简单,但实际上案例的数量使得它很难做到正确。
    • 确实,重载解析至少是 C# 中的复杂度等级 NP-HARD。您可以(理论上)让编译器解决旅行推销员问题以计算出调用哪个重载!
    • 坦克!我在发布之前阅读了 Eric 的文章,但发现它对于我的简单案例来说很复杂......不过我想我应该去拿一份规格的副本......
    【解决方案2】:

    我会说如果你超出限制

    -2,147,483,648 to 2,147,483,647
    

    控制权将转到long

    long 的范围

    –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
    

    int 的最大值

    foo.bar(-2147483648);
    

    foo.bar(2147483648);
    

    如果我们超过该值 2147483648,Long 将获得控制权

    【讨论】:

      【解决方案3】:

      正如凯文所说,有一个过载解决流程。该过程的基本草图是:

      • 识别所有可访问的候选方法,可能对泛型方法使用类型推断
      • 过滤掉不适用的方法;也就是说,由于参数没有隐式转换为参数类型而无法工作的方法。
      • 一旦我们有了一组适用的候选者,就可以对它们运行更多过滤器以确定唯一的最佳候选者。

      过滤器相当复杂。例如,最初在派生程度较高的类型中声明的方法总是比最初在派生程度较低的类型中声明的方法好。参数类型与参数类型完全匹配的方法比不完全匹配的方法要好。等等。具体规则见规范。

      在您的特定示例中,“更好”算法很简单。 int 与 int 的精确匹配优于 int 与 long 的不精确匹配。

      【讨论】:

        猜你喜欢
        • 2011-05-08
        • 1970-01-01
        • 1970-01-01
        • 2020-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-05
        相关资源
        最近更新 更多