C#笔记⑩
一、泛型(Generic)
为什么要引入泛型
-
避免成员膨胀 -
避免类型膨胀
而且泛型具有正交性,它能兼具的类型有类与接口等
来看看什么是类型膨胀,在方法一种出现的就是类型膨胀(若以后增加服务,又得增加类,那就会产生无穷无尽的类)
类型膨胀
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; }
}
}

浙公网安备 33010602011771号