尽管没有实现接口,代码工作仍未实现

时间:2013-11-02 07:15:28

标签: c# interface

我有以下代码:

 interface ICalculator
 {
     int Sum ( int x,  int y);
 }

 abstract class AbsCalculator
 {
     public abstract int Sum(int x, int y);
 }

 class Calculator : AbsCalculator, ICalculator
 {
     public override int Sum(int x, int y)
     {
         Console.WriteLine ( "From overriden method" );
         return x + y;
     }
 }

以下语句工作正常,程序编译尽管我没有实现接口:

Calculator calculator = new Calculator();
Console.WriteLine ( calculator.Sum(10, 20) );

所以我的第一个问题是:它为什么有效?

然后,我将以下接口实现添加到Calculator类:

int ICalculator.Sum(int x, int y)
{
     Console.WriteLine("From implemented method");
     return x + y;
}

再次尝试以下声明时:

Calculator calculator = new Calculator();
Console.WriteLine ( calculator.Sum(10, 20) );

该方法覆盖了仍然被调用的抽象。 所以我的第二个问题是:为什么程序从抽象类调用方法而不是从接口调用方法?

3 个答案:

答案 0 :(得分:5)

有两种方法可以在C#中实现接口,无论是显式还是隐式,但CLR只有一种类型的实现 - 显式的。

当C#编译器发现某个类必须实现一个接口时,它会查找与该接口所需类的签名匹配的方法,并指示CLR这些是实现,以保存代码。

因此,在您的情况下,当C#编译器发现您的类实现了ICalculator时,它将查找与Sum(int,int)的签名匹配的公共方法,并将该方法视为实现。该方法被覆盖的事实并不重要。

如果你想为方法的实现赋予另一种含义,你应该明确地给它。

答案 1 :(得分:4)

不,你要求它!您的第一个代码块完全合法。名称和签名与界面要求匹配:int Sum(int x, int y)

现在,int ICalculator.Sum(int x, int y)之类的签名称为explicit interface implementation,这意味着您只能 通过接口类型的引用访问该方法。

interface ICalculator {
    int Sum ( int x,  int y);
}

abstract class AbsCalculator {
    public abstract int Sum(int x, int y);
}

class Calculator : AbsCalculator, ICalculator {
    public override int Sum(int x, int y) {
        Console.WriteLine ( "From overriden method" );
        return x + y;
    }

    int ICalculator.Sum(int x, int y) {
         Console.WriteLine("From explicitly implemented interface method");
         return x + y;
    }
}

class Program {
    static void Main() {
        Calculator calculator = new Calculator();
        ICalculator icalc = calculator;

        // These calls will print different messages.
        calculator.Sum(10,20);
        icalc.Sum(10,20);
    }
}

答案 2 :(得分:4)

回答您的第一个问题

在.NET中加载类型(Class)时,CLR会创建一个方法表,该表包含由类定义的方法的条目以及类继承的方法,因此在您的情况下Calculator class包含以下条目

  1. 默认情况下,每个类都隐式继承自Object基类,因此方法表包含Object类定义的每个虚拟实例方法的条目。

  2. 您的类继承自AbsCalculator抽象类,因此方法表定义了抽象类方法的条目Sum

  3. 您的类继承ICalculator接口,因此方法表定义了接口Sum方法的条目。

  4. 这里C#编译器假设您正在实现接口方法,因为该方法是Public并且接口方法和抽象类方法的签名是相同的。所以编译器没有给出任何错误

    回答第二个问题

    实施时有两个概念Implicit Interface Method ImplementationExplicit Interface Method Implementation

    Implicit Interface Method Implementation中,我们使用接口引用调用接口方法,如下所示

        Calculator calculator = new Calculator();
        ICalculator icalc = calculator;
    
        calculator.Sum(5,5);
        icalc.Sum(5,10);
    

    Explicit Interface Method Implementation中,当您使用接口名称为方法名称添加前缀时,它将成为显式方法实现。

    interface ICalc
    {
        int Sum(int x, int y);
    }
    
    abstract class AbsCalc
    {
        public abstract int Sum(int x, int y);
    }
    
    class Program : AbsCalc, ICalc
    {
        public override int Sum(int x, int y)
        {
            Console.WriteLine("From abstract Override");
            return x + y;
        }
    
        int ICalc.Sum(int x,int y)
        {
            Console.WriteLine("From Intrface");
            return x + y;
        }
    
    
        static void Main(string[] args)
        {
            Program p = new Program();
            p.Sum(1, 2);
    
            ICalc i = p;
            i.Sum(1,2);
        }
    }