C# 正确使用界面?

C# 正确使用界面?,c#,interface,C#,Interface,我读了一些关于接口的文章,但有些东西对我来说还不够清楚。请帮助找到使用接口的正确方法。我的问题在codesample中的注释中: using System; namespace IfTest { public interface ICalculator { void Sum(int a, int b); } public class MyCalc : ICalculator { public void Sum(int a,

我读了一些关于接口的文章,但有些东西对我来说还不够清楚。请帮助找到使用接口的正确方法。我的问题在codesample中的注释中:

using System;
namespace IfTest
{
    public interface ICalculator
    {
        void Sum(int a, int b);
    }

    public class MyCalc : ICalculator
    {
        public void Sum(int a, int b)
        {
            Console.WriteLine(a + b);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //What's the difference between
            ICalculator mycalc;
            mycalc = new MyCalc();
            mycalc.Sum(5, 5);

            //and this. When should we use this way?
            MyCalc mc = new MyCalc();
            mc.Sum(5, 5);
        }
    }
}

使用
ICalculator mycalc
可以声明类型为
ICalculator
的变量,并且在编译时只能调用作为此接口一部分的方法。您将无法调用不属于接口但仅属于实现类的方法

使用
MyCalc mc
可以声明类型为
MyCalc
的变量,并且在编译时只能调用该类及其继承的接口上的所有方法

在运行时,两者之间将没有任何区别

在针对接口编程时,建议针对对象层次结构中最抽象的可能类型进行编程。因此,在这种情况下,这将是
ICalculator
接口


这样可以更好地分离调用代码和实际实现。如果调用代码是根据接口编程的,则它不再绑定到特定的
MyCalc
实现,该实现可以与其他实现交换。

使用
ICalculator MyCalc
您将声明类型为
ICalculator
的变量,并且在编译时您将只能调用方法它们是此接口的一部分。您将无法调用不属于接口但仅属于实现类的方法

使用
MyCalc mc
可以声明类型为
MyCalc
的变量,并且在编译时只能调用该类及其继承的接口上的所有方法

在运行时,两者之间将没有任何区别

在针对接口编程时,建议针对对象层次结构中最抽象的可能类型进行编程。因此,在这种情况下,这将是
ICalculator
接口


这样可以更好地分离调用代码和实际实现。如果调用代码是针对接口编程的,则它不再绑定到特定的
MyCalc
实现,该实现可以与其他实现交换。

当您希望程序依赖于抽象契约而不是硬实现时,可以使用接口。通过使用
ICalculator
接口定义变量(或字段),您可以允许该程序的未来实现提供该契约的其他实现

ICalculator mycalc;
mycalc = new MyCalc(); // or mycalc = new OtherCalc(); or mycalc = new FinancialCalc();

将来,当出现更高效的实现时,您可以用实现接口的不同类快速替换
mycalc
,您的程序将继续按预期运行。如果您不希望您的程序由于硬实现(如
MyCalc

提供的未知副作用或实现细节)而失败,这一点尤其重要。如果您希望您的程序依赖于抽象契约,而不是硬实现,则使用接口。通过使用
ICalculator
接口定义变量(或字段),您可以允许该程序的未来实现提供该契约的其他实现

ICalculator mycalc;
mycalc = new MyCalc(); // or mycalc = new OtherCalc(); or mycalc = new FinancialCalc();

将来,当出现更高效的实现时,您可以用实现接口的不同类快速替换
mycalc
,您的程序将继续按预期运行。如果您不希望程序因未知的副作用或硬实现(如
MyCalc

接口)提供的实现细节而失败,这一点尤为重要。假设您有一个使用计算器进行计算的方法。不要在此方法中实例化计算器,而是将计算器作为参数传递给它:

 public void PerformSomeCalculations(ICalculator calculator)
 {
     calculator.Sum(5, 5);
     ...
}
这允许您随时通过另一个实现更改计算器。方法
PerformSomeCalculations
对特定实现一无所知。出于测试目的,您甚至可以向它传递一个虚拟计算器,该计算器跟踪已调用的方法,以查看该方法是否执行预期的操作

例如,您甚至可以提供一个计算器,比较两个非常不同的计算器的行为


编程与接口比编程与特定类型更灵活。编程与接口相比更容易。

使用接口时,接口将完全生效。假设您有一个使用计算器进行计算的方法。不要在此方法中实例化计算器,而是将计算器作为参数传递给它:

 public void PerformSomeCalculations(ICalculator calculator)
 {
     calculator.Sum(5, 5);
     ...
}
这允许您随时通过另一个实现更改计算器。方法
PerformSomeCalculations
对特定实现一无所知。出于测试目的,您甚至可以向它传递一个虚拟计算器,该计算器跟踪已调用的方法,以查看该方法是否执行预期的操作

例如,您甚至可以提供一个计算器,比较两个非常不同的计算器的行为


编程与接口比编程与特定类型更灵活。编程与接口相比更容易。

通常情况下,一个类使用另一个类的服务。“使用服务”是指调用其公共方法。例如,
CalculatorUser
使用
MyCalc
-
CalculatorUser
实例将在某处调用
MyCalc.Sum()

想象一下,现在您将包含类
Calculato的应用程序提供给客户