C#笔记⑩

一、泛型(Generic)

为什么要引入泛型

  1. 避免成员膨胀

  2. 避免类型膨胀

而且泛型具有正交性,它能兼具的类型有类与接口等

来看看什么是类型膨胀,在方法一种出现的就是类型膨胀(若以后增加服务,又得增加类,那就会产生无穷无尽的类)

类型膨胀
    class Test
    {
    static void Main(string[] arg)
    {
        //方法一,一个一个实例,效率低且以后要是在加服务,将又要改代码
        // Apple apple=new Apple(){Color="Red"};
        // Box box1=new Box(){Cargo=apple};
        // System.Console.WriteLine(box1.Cargo.Color);

        // Book book=new Book(){Name="TI"};
        // BookBox box2=new BookBox(){Cargo=book};
        // System.Console.WriteLine(box2.Cargo.Name);

        //方法二,将盒子的类整合到一起,用根类型Object去储存(装箱),储存可以,但是获取值麻烦,在不知道对应值类型的时候,不好获取
        // Apple apple=new Apple(){Color="Red"};
        // Box box1=new Box(){Cargo=apple};
        // Book book=new Book(){Name="TI"};
        // Box box2=new Box(){Cargo=book};
        // System.Console.WriteLine(((Apple)box1.Cargo).Color);//只能强制类型转换取值
        // System.Console.WriteLine((box1.Cargo as Apple)?.Color);//或者as方法,?在这表示是否为Color类,不是返回null


        //方法一导致类型膨胀,方法二取值麻烦
        //引入泛型可以解决这类问题
        //方法三
        Apple apple=new Apple(){Color="Red"};
        Book book=new Book(){Name="TI"};
        Box<Apple> box1=new Box<Apple>(){Cargo=apple}; //泛型不能直接使用,必须进行特化<类型>
        Box<Book> box2=new Box<Book>(){Cargo=book};
        System.Console.WriteLine(box1.Cargo.Color);
        System.Console.WriteLine(box2.Cargo.Name);
    }

    }

    class Apple
    {
        public string Color{get;set;}
    }

    class Book
    {
        public string Name { get; set; }
    }

    //方法三
    class Box<T>
    { 
        public T Cargo { get; set; } 
        public string c { get; set; } 
    }



    //方法二
    // class Box
    // {
    //     public Object Cargo{get;set;}
    // }

    //方法一
    // class Box
    // {
    //     public Apple Cargo { get; set; }
    // }

    // class BookBox
    // {
    //     public Book Cargo {get;set;}
    // }

引入泛型后,我们要实例它时候,必须进行特化才能赋值与取值。

让我们来看看什么是成员膨胀(在同一类中,同方法,不同返回值与参数,相同作用的成员)

成员膨胀
    class Test
    {
    static void Main(string[] arg)
    {
        int[] a=new int[]{1,2,3,4,5};
        int[] b=new int[]{1,2,3,4,5,6};
        double[] c=new double[]{1.0,2.0,3.0,4.0,5.0};
        double[] d=new double[]{1.5,2.5,3.5,4.5,5.5,6.5};
        // int[]result=LickI(a,b);
        // foreach (var item in result)
        // {
        //     System.Console.WriteLine(item);
        // }
        // double[]resultD=LickD(c,d);
        // foreach (var item in resultD)
        // {
        //     System.Console.WriteLine(item);
        // }
        var resultI=Lick(a,b);  //因为实参告诉了Lick方法的类型,所以此处可以省略泛型特化
        var resultD=Lick<double>(c,d); //加了也无所谓
        foreach (var item in resultI)
        {
            System.Console.WriteLine(item);
        }
        foreach (var item in resultD)
        {
            System.Console.WriteLine(item);
        }
    }

    public static T[] Lick<T>(T[] a,T[] b)  //泛型用于数组时,T[],而它的类型由参数告诉方法,方法再告诉返回值
    {
        T[] result=new T[a.Length+b.Length];
        int aMove=0;
        int bMove=0;
        int rMove=0;
        while(aMove<a.Length||bMove<b.Length)
        {
            if(aMove<a.Length)
            {
                result[rMove++]=a[aMove++];
            }

            if(bMove<b.Length)
            {
                result[rMove++]=b[bMove++];
            }
        }

        return result;
    }

    //方法一,同样的方法,形成成员膨胀了,以后要引入ulong又要加代码
    //且弄将其作为重载,以后发现问题,不好修改
    // public static int LickI(int[] a,int[] b)
    // {
    //     int[] result=new int[a.Length+b.Length];
    //     int aMove=0;
    //     int bMove=0;
    //     int rMove=0;
    //     while(aMove<a.Length||bMove<b.Length)
    //     {
    //         if(aMove<a.Length)
    //         {
    //             result[rMove++]=a[aMove++];
    //         }

    //         if(bMove<b.Length)
    //         {
    //             result[rMove++]=b[bMove++];
    //         }
    //     }

    //     return result;
    // }

    // public static double[] LickD(double[] a,double[] b)
    // {
    //     double[] result=new double[a.Length+b.Length];
    //     int aMove=0;
    //     int bMove=0;
    //     int rMove=0;
    //     while(aMove<a.Length||bMove<b.Length)
    //     {
    //         if(aMove<a.Length)
    //         {
    //             result[rMove++]=a[aMove++];
    //         }

    //         if(bMove<b.Length)
    //         {
    //             result[rMove++]=b[bMove++];
    //         }
    //     }

    //     return result;
    // }
    }

二、泛型接口

若一个类实现了泛型接口,这个类也要成为泛型类

点击查看代码
    class Test
    {
    static void Main(string[] arg)
    {
        //方法一
        //在实例时特化,即<int>,此时为泛型类
        // Student<int> stu=new Student<int>();
        // stu.ID=1;
        // stu.Name="W";
        // System.Console.WriteLine($"{stu.Name}的ID为{stu.ID}");

        //方法二,不用确认参数类型
        Student stu=new Student();
        stu.ID=100000000;
        stu.Name="W";
        System.Console.WriteLine($"{stu.Name}的ID为{stu.ID}");
    }

    }

    interface IUnique<Tid>  //声明的泛型接口
    {
        Tid ID { get; set; }
    }

    
    //方法二,在实现接口时候特化,即<ulong>
    class Student:IUnique<ulong>
    {
        public ulong ID { get; set; }
        public string Name { get; set; }
    }


    //方法一
    // class Student<Tid>:IUnique<Tid>
    // {
    //     public Tid ID { get; set; }
    //     public string Name { get; set; }
    // }


}

数据结构也是泛型的,如List<>Dictionary<>IList<>接口
Add加、Remove删

三、泛型委托

Action与Func为例子(其实内置委托本质就是要用泛型的)

点击查看代码
    class Test
    {
    static void Main(string[] arg)
    {
        //Action委托用于无返回值的方法
        Action<string> action1=new Action<string>(Say);
        Action<int> action2=new Action<int>(Add);
        action1.Invoke("W");
        action2(500);
        //Func委托用于有返回值的方法,且只有一个时候是返回值类型,有两个以上是参数然后再是返回值类型
        Func<double,double,double> x=(a,b)=>{return a*b;};
        Func<int,int,double> y=new Func<int, int, double>(Mul2);
        System.Console.WriteLine(x.Invoke(5.0,6.5));
        System.Console.WriteLine(y.Invoke(1,2));
    }

    public static void Say(string str)
    {
        System.Console.WriteLine($"Hello,{str}");
    }

    public static void Add(int a)
    {
        System.Console.WriteLine($"{a+100}");
    }

    public static double Mul(double a,double b)
    {
        return a*b;
    }

    public static double Mul2(int a,int b)
    {
        return a*b;
    }


    }

一个将泛型委托、方法委托、Lambda表达式结合的方法

点击查看代码
namespace MyTest
{
    class Test
    {
    static void Main(string[] arg)
    {
        // Func<int,int,int> func=new Func<int, int, int>((a,b)=>{return a+b;});
        //通过缩减可以得到下面这个表达式
        // Func<int,int,int> func=(a,b)=>{return a+b;};
        var x=Add((a,b)=>{return a+b;},500,600);
        System.Console.WriteLine(x);
    }

    public static T Add<T>(Func<T,T,T> func,T a,T b)
    {
        return func(a,b);
    }


    }

四、Partial类

把类进行分割,且减少类的派生,对数据库进行说明,再新建类中复制一份副本。
在我们对数据库进行更新时候,我们数据库的代码会被重写编写,所以我们要另外新建个类中加入partial来保护我们想要增加的代码。
要将库中代码复制

namespace BookStore.Client
{
    public partial class Book
    {
        public int ID { get; set; }
    }
}
新键类
namespace BookStore.Client
{
    public partial class Book
    {
        public void Report()
        {
            System.Console.WriteLine(this.ID);
        }
    }
}

五、枚举

枚举的引入就是规范数据格式的

点击查看代码
    class Test
    {
    static void Main(string[] arg)
    {
        Student stu=new Student();
        stu.grade=Grade.Junior;
        Student BigBoss=new Student();
        BigBoss.grade=Grade.Junior|Grade.Senior|Grade.Boss|Grade.BigBoss;
        System.Console.WriteLine(stu.grade);//打印结果为Junior
        System.Console.WriteLine(BigBoss.grade); //BigBoss使用比特位用法,这样就能让他身兼多职了
    }

    enum Grade 
    {
        Junior=1,
        Senior=2,
        Boss=4,
        BigBoss=8,
    }

    class Student
    {
        public int ID { get; set; }
        public Grade grade { get; set; }
    }

    }

}

六、结构体

结构体是值类型,所以他是将值赋给另外的变量,另外变量改变值,他也不会改变,两者无关系
struct不允许无参构造器,允许有参数构造器

点击查看代码
    class Test
    {
    static void Main(string[] arg)
    {
        Student stu=new Student(2);
        System.Console.WriteLine(stu.ID);
    }

    }

    struct Student
    {
        public Student(int id)
        {
            this.ID=id;
        }
        public int ID { get; set; }
    }
}
posted @ 2022-02-08 15:43  Ariaaaaa  阅读(6)  评论(0)    收藏  举报