C#中接口、委托的相关使用

什么是接口

在 C# 中,接口(Interface)是一种用于定义行为契约的类型。它是一个抽象的概念,描述了类或结构体应该具有的成员(方法、属性、事件等)的集合,而不提供具体的实现细节。

接口定义了一组方法、属性和事件的签名,这些成员可以被实现接口的类或结构体来实现。通过实现接口,类或结构体可以遵循接口所定义的契约,并提供自己的具体实现。

在 C# 中,使用 interface 关键字来声明一个接口。以下是一个简单的接口示例:

csharp 复制代码
public interface IMyInterface
{
    void Method1();
    string Method2();
    int Property { get; set; }
    event EventHandler MyEvent;
}

在上面的示例中,IMyInterface 接口定义了一个名为 Method1 的无返回值方法,一个名为 Method2 的返回类型为 string 的方法,一个名为 Property 的读写属性,以及一个名为 MyEvent 的事件。

类或结构体可以通过使用 classstruct 关键字来实现接口,并提供接口中定义的成员的具体实现。以下是一个实现了上述接口的类的示例:

csharp 复制代码
public class MyClass : IMyInterface
{
    public void Method1()
    {
        // 实现 Method1 的具体代码
    }

    public string Method2()
    {
        // 实现 Method2 的具体代码
        return "";
    }

    public int Property { get; set; }

    public event EventHandler MyEvent;
}

通过实现接口,MyClass 类遵循了 IMyInterface 接口所定义的契约,并提供了对应成员的具体实现。

接口在 C# 中被广泛用于实现多态和代码组织的目的,它允许定义统一的契约,并通过不同的实现类来实现具体的行为。

什么是委托

在 C# 中,委托(Delegate)是一种类型,用于表示对一个或多个方法的引用。委托可以像其他对象一样传递、存储和调用方法,使得方法能够像数据一样被处理。

委托提供了一种方便的方式来实现事件处理、回调函数和函数指针等功能。它允许将方法作为参数传递给其他方法,以及将方法作为返回值返回。

在 C# 中,委托通过声明委托类型来定义。委托类型指定了可以被委托引用的方法的签名。以下是一个简单的委托类型示例:

csharp 复制代码
public delegate void MyDelegate(string message);

上述示例定义了一个名为 MyDelegate 的委托类型,它可以引用一个具有一个 string 参数且返回类型为 void 的方法。

可以使用委托类型来创建委托实例,然后将其用于引用具有匹配签名的方法。以下是一个示例:

csharp 复制代码
public class MyClass
{
    public void Method1(string message)
    {
        Console.WriteLine("Method1: " + message);
    }

    public void Method2(string message)
    {
        Console.WriteLine("Method2: " + message);
    }
}

public class Program
{
    public static void Main()
    {
        MyClass obj = new MyClass();

        MyDelegate del = obj.Method1;
        del("Hello");  // 调用 Method1

        del = obj.Method2;
        del("World");  // 调用 Method2
    }
}

在上述示例中,MyClass 类定义了两个具有匹配签名的方法 Method1Method2。然后,通过委托类型 MyDelegate 创建了 del 委托实例,并将其分别引用了 Method1Method2

通过调用委托实例,可以间接调用被引用的方法,实现了方法的动态调用。

委托在 C# 中被广泛用于事件处理、异步编程和回调机制等场景,提供了灵活且可扩展的方法引用机制。

通过实例来运用接口和委托

场景

实现对周黑鸭工厂的产品生产统一管理,主要产品包括鸭脖和鸭翅。武汉工厂能生生产鸭脖和鸭翅,南京工厂只能生产鸭翅,长沙工厂只能生产鸭脖。

代码实现

  • 定义接口 IProductionFactory,包含生产鸭脖和鸭翅的方法。

    csharp 复制代码
        public interface IProductionFactory
        {
            void ProduceDuckNecks();
            void ProduceDuckWings();
        }
  • 定义类 WuhanFactory、NanjingFactory、ChangshaFactory 分别实现接口 IProductionFactory,用于具体的生产工厂。

    说明:这里对于类中不能生产的处理方法是抛出异常

    1. 武汉工厂
    csharp 复制代码
        class WuhanFactory : IProductionFactory
        {
            public void ProduceDuckNecks()
            {
                Console.WriteLine("Wuhan factory produce duck necks...");
            }
            public void ProduceDuckWings()
            {
                Console.WriteLine("Wuhan factory produce duck wings...");
            }
        }
    1. 南京工厂
    csharp 复制代码
        class NanjingFactory : IProductionFactory
        {
            public void ProduceDuckNecks()
            {
                throw new NotImplementedException("Error: Nanjing factory cannot produce duck necks!");
            }
            public void ProduceDuckWings()
            {
                Console.WriteLine("Nanjing factory produce duck wings...");
            }
        }
    1. 长沙工厂
    csharp 复制代码
        class ChangshaFactory : IProductionFactory
        {
            public void ProduceDuckNecks()
            {
                Console.WriteLine("Changsha factory produce duck necks...");
            }
            public void ProduceDuckWings()
            {
                throw new NotImplementedException("Error: Changsha factory cannot produce duck wings!");
            }
        }
  • 使用委托 ProductionDelegate 定义生产委托。

    csharp 复制代码
        public delegate void ProductionDelegate();
  • 在 Main 函数中,创建不同工厂的实例,并通过生产委托进行生产。

    说明:抽离出FactoryProduct,函数入参为委托类型,方便对委托进行统一化调用,同时进行了异常处理,提高代码复用性

    csharp 复制代码
        public static void FactoryProduct(ProductionDelegate productionDelegate)
        {
            // 无误则正常调用
            try
            {
                productionDelegate();
            }
            // 异常则抛出异常
            catch (NotImplementedException e)
            {
                Console.WriteLine(e.Message);
            }
        }
        public static void Main(string[] args)
        {
            // 创建工厂实例
            IProductionFactory wuhanFactory, nanjingFactory, changshaFactory;
            wuhanFactory = new WuhanFactory();
            nanjingFactory = new NanjingFactory();
            changshaFactory = new ChangshaFactory();
    
            // 实现委托
            ProductionDelegate wuhanDelegate, nanjingDelegate, changshaDelegate;
            // 武汉
            wuhanDelegate = wuhanFactory.ProduceDuckNecks;
            wuhanDelegate += wuhanFactory.ProduceDuckWings;
            // 南京
            nanjingDelegate = nanjingFactory.ProduceDuckWings;
            // 长沙
            changshaDelegate = changshaFactory.ProduceDuckNecks;
    
            // 通过委托进行生产
            FactoryProduct(wuhanDelegate);
            FactoryProduct(nanjingDelegate);
            FactoryProduct(changshaDelegate);
        }
  • 运行结果

    • 正常情况
    • 异常情况

      csharp 复制代码
         wuhanDelegate = wuhanFactory.ProduceDuckNecks;
         wuhanDelegate += wuhanFactory.ProduceDuckWings;
         // 南京
         nanjingDelegate = nanjingFactory.ProduceDuckWings;
         nanjingDelegate += nanjingFactory.ProduceDuckNecks;
         // 长沙
         changshaDelegate = changshaFactory.ProduceDuckNecks;
         changshaDelegate += changshaFactory.ProduceDuckWings;

小结

通过接口我们可以实现对类的统一定义,定义接口完成顶层设计,而将具体的实现交给类,而不是使用派生和继承的方式,具有灵活性、解耦合、实现多态、接口隔离原则的特点,优化了多继承问题的解决;而使用委托则是统一了调用入口,让函数的调用更加简洁,统一,使代码的可读性更高,同时在本次代码实例中通过异常抛出的方法描述错误调用接口会有什么样的后果,而不是用空函数来取代这个部分,使得代码的可维护性更高,我们也能更直观的感受到接口的调用。

END - 完整代码

csharp 复制代码
    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 鸭脖和鸭翅_接口和委托
{
    internal class Program
    {
        public interface IProductionFactory
        {
            void ProduceDuckNecks();
            void ProduceDuckWings();
        }
        class WuhanFactory : IProductionFactory
        {
            public void ProduceDuckNecks()
            {
                Console.WriteLine("Wuhan factory produce duck necks...");
            }
            public void ProduceDuckWings()
            {
                Console.WriteLine("Wuhan factory produce duck wings...");
            }
        }

        class NanjingFactory : IProductionFactory
        {
            public void ProduceDuckNecks()
            {
                throw new NotImplementedException("Error: Nanjing factory cannot produce duck necks!");
            }
            public void ProduceDuckWings()
            {
                Console.WriteLine("Nanjing factory produce duck wings...");
            }
        }
        class ChangshaFactory : IProductionFactory
        {
            public void ProduceDuckNecks()
            {
                Console.WriteLine("Changsha factory produce duck necks...");
            }
            public void ProduceDuckWings()
            {
                throw new NotImplementedException("Error: Changsha factory cannot produce duck wings!");
            }
        }
        public delegate void ProductionDelegate();
        public static void FactoryProduct(ProductionDelegate productionDelegate)
        {
            // 无误则正常调用
            try
            {
                productionDelegate();
            }
            // 异常则抛出异常
            catch (NotImplementedException e)
            {
                Console.WriteLine(e.Message);
            }
        }
        public static void Main(string[] args)
        {
            // 创建工厂实例
            IProductionFactory wuhanFactory, nanjingFactory, changshaFactory;
            wuhanFactory = new WuhanFactory();
            nanjingFactory = new NanjingFactory();
            changshaFactory = new ChangshaFactory();

            // 实现委托
            ProductionDelegate wuhanDelegate, nanjingDelegate, changshaDelegate;
            // 武汉
            wuhanDelegate = wuhanFactory.ProduceDuckNecks;
            wuhanDelegate += wuhanFactory.ProduceDuckWings;
            // 南京
            nanjingDelegate = nanjingFactory.ProduceDuckWings;
            //nanjingDelegate += nanjingFactory.ProduceDuckNecks;
            // 长沙
            changshaDelegate = changshaFactory.ProduceDuckNecks;
            //changshaDelegate += changshaFactory.ProduceDuckWings;

            // 通过委托进行生产
            FactoryProduct(wuhanDelegate);
            FactoryProduct(nanjingDelegate);
            FactoryProduct(changshaDelegate);
        }

    }
}
相关推荐
新手unity自用笔记15 小时前
项目-坦克大战学习-子弹的移动与销毁
笔记·学习·c#
qinzechen15 小时前
分享几个做题网站------学习网------工具网;
java·c语言·c++·python·c#
yufei-coder19 小时前
C# Windows 窗体开发基础
vscode·microsoft·c#·visual studio
dangoxiba19 小时前
[Unity Demo]从零开始制作空洞骑士Hollow Knight第十三集:制作小骑士的接触地刺复活机制以及完善地图的可交互对象
游戏·unity·visualstudio·c#·游戏引擎
AitTech19 小时前
深入理解C#中的TimeSpan结构体:创建、访问、计算与格式化
开发语言·数据库·c#
hiyo5851 天前
C#中虚函数和抽象函数的概念
开发语言·c#
开心工作室_kaic1 天前
基于微信小程序的校园失物招领系统的设计与实现(论文+源码)_kaic
c语言·javascript·数据库·vue.js·c#·旅游·actionscript
时光追逐者1 天前
WaterCloud:一套基于.NET 8.0 + LayUI的快速开发框架,完全开源免费!
前端·microsoft·开源·c#·.net·layui·.netcore
friklogff1 天前
【C#生态园】打造现代化跨平台应用:深度解析.NET桌面应用工具
开发语言·c#·.net
hiyo5852 天前
C#的面向对象
开发语言·c#