天天看点

如何在C#中不使用接口

在设计应用程序时,您经常需要使用接口和抽象类。 本文讨论了“接口滥用”的一些常见示例以及我们可以用来避免它们的策略。 它还讨论了宗旨的含义,“对接口进行编程,而不是对实现进行编程”。

[InfoWorld的要点: CI / CD入门:使用CI / CD管道自动执行应用程序交付 。 • CI / CD的5个常见陷阱以及如何避免它们 。 | 通过InfoWorld的App Dev Report新闻通讯了解编程方面的热门话题。 ]

什么是接口?

首先,让我们了解接口以及为什么在编程中需要它们。 接口严格来说是合同; 它没有任何实现。 接口仅包含成员声明。 您可以有方法声明,但没有定义。 接口中声明的成员应以扩展或实现接口的类型(类和结构)实现。 接口不能包含字段。 接口不能序列化,因为它不能具有数据成员。 如我所说,接口只能有声明,而不能有定义。

避免更改界面

扩展接口的类或结构应实现其所有成员。 如果实现更改,您的代码仍将起作用。 但是,如果合同(即接口)发生了变化,则必须更改扩展接口的所有类型的实现。 换句话说,对接口的任何更改都会影响扩展接口的所有类型。 扩展接口的类型必须遵守合同。 因此,仅在很少需要更改接口时才使用接口。 同样,创建新界面总比更改现有界面更好。

编程到接口,而不是实现

您可能不时听到“编程到接口而不是实现”的字样。 您可能在代码中使用了接口,但是仍在为实现编程。 现在让我们研究两种方法之间的区别。

在对接口进行编程时,您将使用最通用的抽象(接口或抽象类)而不是具体的实现。 由于接口保证了一致性,因此对接口进行编程意味着可以以统一的方式处理相似的对象。 这样一来,您便与实现脱离了关系—即,您的实现可能会有所不同。 这也为您的设计增加了灵活性。

以下代码段说明了对接口的编程。 考虑一个名为IRepository的接口,其中包含一些方法的声明。 ProductRepository和CustomerRepository类扩展了IRepository接口并实现了在IRepository接口中声明的方法,如下所示。

public interface IRepository
    {
        //Some code
    }
    public class ProductRepository: IRepository
    {
        //Some code
    }
    public class CustomerRepository: IRepository
    {
        //Some code
    }
           

以下代码可用于创建ProductRepository的实例。

IRepository repository = new ProductRepository();
           

这个想法是,您可以在此处使用任何实现IRepository接口的类。 因此,以下语句也是有效的。

IRepository repository = new CustomerRepository();
           

当您对实现进行编程时,这种一致性会丢失。 取而代之的是,您通常会有一些构造,例如“ if..else”或“ switch..case”语句,用于控制代码中的行为。

避免过度使用接口

将每个类与一个接口相关联不是一个好习惯。 以这种方式过度使用接口会造成不必要的复杂性,引入代码冗余,违反YAGNI并降低代码库的可读性和可维护性。 接口用于将具有相同行为的对象组合在一起。 如果对象的行为不同,则无需进行分组。 当您不会有多种实现时使用接口是接口过度使用的一个示例。

为与该类的公共成员匹配的类创建接口是很常见的。 这样做根本不增加任何值-您只需复制类的接口,而无需添加任何实际的抽象。

现在让我们看一个如何过度使用接口的示例。 考虑以下名为IProduct的接口。

public interface IProduct
    {
        int Id { get; set; }
        string ProductName { get; set; }
        double Price { get; set; }
        int Quantity { get; set; }
    }
           

Product类扩展了IProduct接口,如下所示。

public class Product : IProduct
    {
        public int Id { get; set; }
        public string ProductName { get; set; }
        public double Price { get; set; }
        public int Quantity { get; set; }
    }
           

显然,我们不需要IProduct接口,因为该接口及其实现是相同的。 多余的代码是不必要的。

让我们看另一个例子。 下面的代码片段显示了一个名为IProductManager的接口,该接口声明了两个方法,即Save和Update。

 public interface IProductManager
    {
        void Save(IProduct product);
        void Update(IProduct product);
    }
           

IProductManager接口包含ProductManager类的公共方法的声明。 这是ProductManager类的外观。

 public class ProductManager : IProductManager
    {
        public void Save(IProduct product)
        {
           //Write your implementation here
        }
        public void Update(IProduct product)
        {
            //Write your implementation here
        }
    }
           

IProduct和IProductManager接口是接口过度使用的示例。 这两个接口都有一个单一的实现,它们根本不增加任何值。

通过使用接口,您可以删除代码中不必要的耦合,并使代码易于测试。 但是,应避免过度使用接口。 仅当接口将有多个实现时才使用接口。 当您的班级扮演许多角色或承担多个职责时,也可以使用接口。 在这种情况下,您的类可以实现多个接口-每个角色一个。

From: https://www.infoworld.com/article/3391960/how-not-to-use-interfaces-in-c.html

c#