• C# 继承,抽象,接口,泛型约束,扩展方法


    前言

    以前计算机本科学习的时候,我就知道了继承,重载,接口,抽象,泛型等概念。本章优先讲解继承,接口,抽象,泛型这一组概念。如果说继承,抽象只是为了标准化代码,规范程序编写的话,那么泛型约束就是给于了继承抽象这个写法的必要性。

    c# 继承

    浅谈C#中的抽象类(abstract)和接口(interface)

    C#泛型约束

    模拟需求

    因为我干的是上位机工作,这里我就讲解一下我用到的场景。上位机的代码重复性很高,泛型约束就是用于解决此类问题。

    场景模拟

    我是A公司,我有多种(为了简单按两种算)产品,这2种产品有一下两个特质

    • 每个产品存数据库的字段有完全相同的3个字段
      • Id:数据库Id
      • DeivceId:设备唯一Id,全部种类产品唯一的Id。
      • CreateTime:数据录入数据库时间

    重复性高的需求

    我们现在有个需求,给每个类添加一个打印CreateTime的方法

    初始类结构
     public class DeviceA
     {
         public string DeviceId { get; set; }
    
         public long Id { get; set; }    
    
         public DateTime CreateTime { get; set; }
    
         public string ValueA {  get; set; }
     }
    
     public class DeviceB
     {
    
         public string DeviceId { get; set; }
    
         public long Id { get; set; }
    
         public DateTime CreateTime { get; set; }
    
         public string ValueB { get; set; }
    
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    继承优化

    继承的目的就是为了减少重复的字段

    public class DeviceA:DeviceBase
    {
        public string ValueA {  get; set; }
    }
    
    public class DeviceB : DeviceBase
    {
        public string ValueB { get; set; }
    
    }
    /// 
    /// 使用基类优化代码
    /// 
    public class DeviceBase
    {
        public string DeviceId { get; set; }
    
        public long Id { get; set; }
    
        public DateTime CreateTime { get; set; }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    抽象类

    我们也可以在基类上面添加abstract关键字

    public abstract class DeviceBase
    {
        public string DeviceId { get; set; }
    
        public long Id { get; set; }
    
        public DateTime CreateTime { get; set; }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    区别就是抽象类无法实例化
    在这里插入图片描述

    那么抽象类的意义就是为了告诉你,我的基类是没有任何实际意义的,我单纯就是为了继承用的

    需求1:打印CreateTime
    方法1:使用重载
    static void Main(string[] args)
    {
        var DeviceA = new DeviceA() { CreateTime = DateTime.Now};
        var DeviceB = new DeviceB() { CreateTime = DateTime.Now };
        PrintCreateTime(DeviceA);
        PrintCreateTime(DeviceB);
    }
    public static void PrintCreateTime(DeviceA deviceA)
    {
        Console.WriteLine($"{deviceA.CreateTime}");
    }
    
    public static void PrintCreateTime(DeviceB deviceB)
    {
        Console.WriteLine($"{deviceB.CreateTime}");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    方法2:基类函数
    internal class Program
    {
        static void Main(string[] args)
        {
            var DeviceA = new DeviceA() { CreateTime = DateTime.Now};
            var DeviceB = new DeviceB() { CreateTime = DateTime.Now };
    		DeviceA.PrintCreateTime();
    		DeviceB.PrintCreateTime();
        }
     
    }
    
    /// 
    /// 使用基类优化代码
    /// 
    public class DeviceBase
    {
    	·······
        public void PrintCreateTime()
        {
            Console.WriteLine(CreateTime.ToString());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    方法3:泛型约束
    方法3.1:普通泛型方法
            static void Main(string[] args)
            {
                var DeviceA = new DeviceA() { CreateTime = DateTime.Now};
                var DeviceB = new DeviceB() { CreateTime = DateTime.Now };
                PrintCreateTime(DeviceA);
                PrintCreateTime(DeviceB);
            }
            /// 
            /// 泛型约束DeviceBase基类
            /// 
            /// 
            /// 
            public static void PrintCreateTime<T>(T model)where T : DeviceBase
            {
                Console.WriteLine(model.CreateTime.ToString());
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    方法3.2:高级泛型约束,扩展方法

    C#小轮子:扩展方法

    internal class Program
    {
        static void Main(string[] args)
        {
            var DeviceA = new DeviceA() { CreateTime = DateTime.Now};
            var DeviceB = new DeviceB() { CreateTime = DateTime.Now };
            DeviceA.PrintCreateTime();
            DeviceB.PrintCreateTime();
        }
    
    }
    
    public static class DeviceExtension
    {
        /// 
        /// 扩展方法是更高级的泛型方法,但是需要一个静态类扩展
        /// 
        /// 
        /// 
        public static void PrintCreateTime<T>(this T model) where T : DeviceBase
        {
            Console.WriteLine(model.CreateTime.ToString());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    总结
    优点缺点
    重载更灵活,每个类都可以定制重复性高
    基类方法降低重复度耦合度高,过多会导致基类臃肿,不符合属性类规范
    泛型约束降低重复度,耦合度低,易于扩展。不能访问基类以外的属性
    扩展方法最强的扩展性,完美代替基类方法需要单独一个静态类

    属性类:是我自己的规范。就是基础的属性类只有属性和构造函数,没有方法。

    番外篇:泛型方法和接口

    有些时候我们设备类的逻辑特别的复杂,比如每个产品都有四个方法:

    • 连接
    • 发送
    • 接受
    • 关闭连接
    public interface IDevice
    {
        public void Connect();
    
        public void Send();
        public void Recive();
    
        public void Close();
    
    }
    public class DeviceA : DeviceBase, IDevice
    {
        public string ValueA {  get; set; }
    
        public void Close()
        {
            throw new NotImplementedException();
        }
    
        public void Connect()
        {
            throw new NotImplementedException();
        }
    
        public void Recive()
        {
            throw new NotImplementedException();
        }
    
        public void Send()
        {
            throw new NotImplementedException();
        }
    }
    
    public class DeviceB : DeviceBase, IDevice
    {
        public string ValueB { get; set; }
    
        public void Close()
        {
            throw new NotImplementedException();
        }
    
        public void Connect()
        {
            throw new NotImplementedException();
        }
    
        public void Recive()
        {
            throw new NotImplementedException();
        }
    
        public void Send()
        {
            throw new NotImplementedException();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    泛型约束抽象接口
    static void Main(string[] args)
    {
        var DeviceA = new DeviceA() { CreateTime = DateTime.Now};
        var DeviceB = new DeviceB() { CreateTime = DateTime.Now };
        GetData(DeviceA);
        GetData(DeviceB);
    }
    
    /// 
    /// 泛型约束也可以约束接口
    /// 
    /// 
    /// 
    public static void GetData<T>(T model) where T : IDevice
    {
        model.Connect();
        model.Send();
        model.Recive();
        model.Close();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    总结

    不是说只能用泛型约束去解决问题,而且泛型约束和扩展方法更具有扩展性,低耦合的特点。大家可以根据自己代码的习惯选择性的使用。

  • 相关阅读:
    python 处理json数据
    我有一个朋友,分享给我的字节跳动测试开发真题
    【c#】前后端分离练习小项目学习笔记----纯干货
    nginx 日志处理goaccess、shell
    Prometheus-Operator使用ServiceMonitor监控配置时遇坑与解决总结
    数组与链表
    Redhat(8)-日志架构-systemd-journald-rsyslog-logrotate
    v-resize-observer 检测 DOM 元素的尺寸变化
    【MATLAB】(高数)
    多级分类(树形结构)数据解决方案
  • 原文地址:https://blog.csdn.net/qq_44695769/article/details/134275911