《C# 语言入门详解(刘铁锰) - 学习笔记 - 泛型》

泛型

文章目录

  • 泛型
  • 前言
  • 一、泛型是什么?
  • 二、泛型接口
  • 三、泛型方法
  • 四、泛型委托

前言

  • 泛型: 避免成员膨胀类型膨胀。(解决功能相似模块,处理数据不一样的问题,提升代码性能)
  • 正交性: 泛型类型(类/接口/委托/…)、泛型成员(属性/方法/字段…)(泛型正交性很好,即,泛型无处不在,应用广泛)

一、泛型是什么?

  • 定义: 允许编写一个可以与任何数据类型一起工作的类或方法。(使用泛型可以最大限度重用代码、提高性能)
  • 类型膨胀: 对于不同属性的成员,定义不同类型的类进行装载
using System;

namespace InterfaceTest
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            Apple apple = new Apple() { Color = "Red" };
            AppleBox box = new AppleBox() { Cargo = apple };
            System.Console.WriteLine(box.Cargo.Color);

            Book book = new Book() { Name = "New Book" };
            BookBox box1 = new BookBox() { Cargo = book };
            System.Console.WriteLine(box1.Cargo.Name);
        }
    }
    class Apple
    {
        public string Color { get; set; }
    }

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

    //定义不同盒子类装载不同的类,会造成类型膨胀,即需要定义不同的盒子类型装载不同的类
    class AppleBox
    {
        public Apple Cargo { get; set; } //AppleBox(Cargo)用来装载Apple类中的color
    }

    class BookBox
    {
        public Book Cargo { get; set; } //BookBox(Cargo)用来装载Book类中的name
    }
}

  • 成员膨胀: 对于不同类型的成员,在同一类中按对应属性装载,使用时,存在除使用者属性外的其它属性没有使用的不足。
using System;

namespace InterfaceTest
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            Apple apple = new Apple() { Color = "Red" };
            Book book = new Book() { Name = "New Book" };
            Box box1 = new Box() { Apple = apple };
            Box box2 = new Box() { Book = book };

            System.Console.WriteLine(box1.Apple.Color);
            System.Console.WriteLine(box2.Book.Name);
        }
    }
    class Apple
    {
        public string Color { get; set; }
    }

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

    //对于不同类型的成员,在同一类中按对应属性装载,使用时,存在除使用者属性外的其它属性没有使用的不足。
    class Box
    {
        public Apple Apple { get; set; }
        public Book Book { get; set; }
    }
}
  • 解决办法: 1. 使用object类装载对应属性;2. 使用泛型
  • Object类
using System;

namespace InterfaceTest
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            Apple apple = new Apple() { Color = "Red" };
            Book book = new Book() { Name = "New Book" };
            Box box1 = new Box() { Cargo = apple };
            Box box2 = new Box() { Cargo = book };

            System.Console.WriteLine(((Apple)box1.Cargo).Color); //强制类型转换 或者 as操作符
            System.Console.WriteLine((box2.Cargo as Book)?.Name);
        }
    }
    class Apple
    {
        public string Color { get; set; }
    }

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

    class Box
    {
        public object Cargo { get; set; }
    }
}
  • 泛型
using System;

namespace InterfaceTest
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            Apple apple = new Apple() { Color = "Red" };
            Book book = new Book() { Name = "New Book" };
            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<TCargo>
    {
        public TCargo Cargo { get; set; }
    }
}

二、泛型接口

  • 若类继承泛型接口,则该类为泛型类
using System;

namespace InterfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Student<int> student = new Student<int>();
            student.Id = 101;
            student.Name = "Nancy";
        }
    }

    interface IUnique<TId>
    {
        TId Id { get; set; }
    }

	//泛型类
    class Student<TId>:IUnique<TId>{
        public TId Id{get;set;}
        public string Name{get;set;}
    }
}
  • 若类继承泛型特化接口,则该类不是泛型类
using System;

namespace InterfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Student student = new Student();
            student.Id = 101;
            student.Name = "Nancy";
        }
    }

    interface IUnique<TId>
    {
        TId Id { get; set; }
    }

	//非泛型类,继承特定的泛型接口
    class Student:IUnique<int>{
        public int Id{get;set;}
        public string Name{get;set;}
    }
}
  • 多参数泛型接口:
using System;
using System.Collections.Generic;

namespace InterfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            IDictionary<int, string> dic = new Dictionary<int, string>();	//多态,父类实现子类的实例化
            dic[1] = "Timothy";
            dic[2] = "Michael";
            System.Console.WriteLine($"Student #1 is {dic[1]}");
            System.Console.WriteLine($"Student #2 is {dic[2]}");
        }
    }
}

三、泛型方法

using System;
using System.Collections.Generic;

namespace InterfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] a1 = { 1, 2, 3, 4, 5 };
            int[] a2 = { 1, 2, 3, 4, 5, 6 };
            double[] a3 = { 1.1, 2.2, 3.3, 4.4, 5.5 };
            double[] a4 = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 };
            var result = Zip(a3, a4);
            System.Console.WriteLine(string.Join(",", result));

        }

		//泛型方法
        static T[] Zip<T>(T[] a, T[] b)
        {
            T[] zipped = new T[a.Length + b.Length];
            int ai = 0, bi = 0, zi = 0;
            do
            {
                if (ai < a.Length) zipped[zi++] = a[ai++];
                if (bi < b.Length) zipped[zi++] = b[bi++];
            } while (ai < a.Length || bi < b.Length);

            return zipped;
        }
    }
}

四、泛型委托

  • Action 委托:无返回值
using System;

namespace InterfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Action<string> a1 = Say;
            a1("Timothy");
        }

        static void Say(String str)
        {
            System.Console.WriteLine($"Hello,{str}!");
        }
    }
}
  • function委托:有返回值
using System;

namespace InterfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<int, int, int> func1 = Add;  //func<参数1,参数2,返回值>
            var result = func1(3, 5);
            System.Console.WriteLine(result);
        }

        static int Add(int a, int b)
        {
            return a + b;
        }
    }
}
  • lambda表达式
using System;

namespace InterfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<int, int, int> func1 = (int a, int b) => { return a + b; };  //lambda表达式
            var result = func1(3, 5);
            System.Console.WriteLine(result);
        }
    }
}

你可能感兴趣的:(学习笔记,c#)