030 泛型,partial类,枚举,结构体 · 语雀https://www.yuque.com/yuejiangliu/dotnet/timothy-csharp-030
泛型在OOP编程中的地位和接口相当
泛型避免类型膨胀和成员膨胀
泛化 特化
<T>类型参数
泛型类似于cpp中的模板-vector<int>
泛型类:
//迭代1
namespace cstimothy301
{
class Program
{
static void Main(string[] args)
{
Apple apple = new Apple() { Color = "Red" };
Box box = new Box() { Cargo = apple };
Console.WriteLine(box.Cargo.Color);
}
}
class Apple
{
public string Color { get; set; }
}
class Box
{
public Apple Cargo { get; set; }
}
}
//迭代2
//加book
//类型膨胀
namespace cstimothy302
{
class Program
{
static void Main(string[] args)
{
Apple apple = new Apple() { Color = "Red" };
AppleBox appleBox = new AppleBox() { Cargo = apple };
Console.WriteLine(appleBox.Cargo.Color);
Book book = new Book() { Name = "New Book" };
BookBox bookBox = new BookBox() { Cargo = book };
Console.WriteLine(bookBox.Cargo.Name);
}
}
class Apple
{
public string Color { get; set; }
}
class Book
{
public string Name { get; set; }
}
class AppleBox
{
public Apple Cargo { get; set; }
}
class BookBox
{
public Book Cargo { get; set; }
}
}
//迭代3
//box增加属性
//成员膨胀
namespace cstimothy303
{
class Program
{
static void Main(string[] args)
{
Apple apple = new Apple() { Color = "Red" };
Box box1 = new Box() { Apple = apple };
Console.WriteLine(box1.Apple.Color);
Book book = new Book() { Name = "New Book" };
Box box2 = new Box() { Book = book };
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; }
}
}
//迭代4
//Box类中使用Object类型
//取东西时必须进行强转/as
namespace cstimothy304
{
class Program
{
static void Main(string[] args)
{
Apple apple = new Apple() { Color = "Red" };
Box box1 = new Box() { Cargo = apple };
//Console.WriteLine(box1.Cargo.);//Cargo的属性是Object类型,无法访问Color,需要强转/as
Console.WriteLine((box1.Cargo as Apple)?.Color);
Book book = new Book() { Name = "New Book" };
Box box2 = new Box() { Cargo = book };
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; }
}
}
//迭代5-泛型类
namespace cstimothy305
{
class Program
{
static void Main(string[] args)
{
Apple apple = new Apple() { Color = "Red" };
Box<Apple> box1 = new Box<Apple>() { Cargo = apple };//特化
Console.WriteLine(box1.Cargo.Color);
Book book = new Book() { Name = "New Book" };
Box<Book> box2 = new Box<Book>() { Cargo = book };
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; }
}
}
泛型具有正交性
泛型类型:
泛型类,泛型接口,泛型委托
泛型成员:
泛型方法,泛型属性,泛型字段
泛型接口:
//泛型接口
namespace cstimothy306
{
class Program
{
static void Main(string[] args)
{
Student<int> stu1 = new Student<int>();
stu1.ID = 101;
stu1.Name = "Timothy";
Teacher tech = new Teacher();
tech.ID = 10000000001;
tech.Name = "Tom";
}
}
interface IUnique<TID>
{
TID ID { get; set; }
}
//如果1个类实现了泛型接口,这个类本身也是泛型的
class Student<TID> : IUnique<TID>
{
public TID ID { get; set; }
public string Name { get; set; }
}
//实现特化后的泛型接口,此时这个类就不是泛型类了
class Teacher : IUnique<ulong>
{
public ulong ID { get; set; }
public string Name { get; set; }
}
}
泛型集合:
//C#List相当于Java中的ArrayList,cpp中的vector,动态数组;
//接口类型的变量可以引用1个引用类型的实例
//IEnumerable<T>-可迭代
//ICollection<T>-集合,可以添加和移除元素
//interface ICollection<T> : IEnumerable<T>
//泛型集合
using System.Collections.Generic;
namespace cstimothy307
{
class Program
{
static void Main(string[] args)
{
//C#List相当于Java中的ArrayList,cpp中的vector,动态数组;
//IList泛型接口
//List泛型类
//IEnumerable<T>-可迭代
//ICollection<T>-集合,可以添加和移除元素
//public interface ICollection<T> : IEnumerable<T>, IEnumerable
IList<int> list = new List<int>();
for (int i = 0; i < 10; i++)
{
list.Add(i);
}
foreach (var item in list)
{
Console.WriteLine(item);
}
//Dictionary
//接口类型的变量可以引用1个引用类型的实例
IDictionary<int, string> dict = new Dictionary<int, string>();
dict[1] = "Tim";
Console.WriteLine($"{dict[1]}");
}
}
}
泛型方法:
//方法膨胀比属性膨胀更严重
//方法重载-函数名相同,参数列表不同,与返回值无关
//泛型方法
//不使用泛型会造成成员膨胀
//方法膨胀比属性膨胀更严重
//方法重载-函数名相同,参数列表不同,与返回值无关
namespace cstimothy308
{
class Program
{
static void Main(string[] args)
{
int[] a1 = { 1, 2, 3 };
int[] a2 = { 3, 4, 5 };
double[] a3 = { 1.1, 2.2, 3.3 };
double[] a4 = { 4.4, 5.5, 6.6 };
var ret = Zip(a3, a4);//类型参数的自动推断
Console.WriteLine(string.Join(",", ret));
}
static T[] Zip<T>(T[] a, T[] b)
{
T[] zipped = new T[a.Length + b.Length];//int[] c=new int[6];
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;
}
}
}
泛型委托:
//泛型委托
//泛型委托+lambda+LINQ
namespace cstimothy309
{
class Program
{
static void Main(string[] args)
{
//Action委托-无返回值的方法
Action<string> action1 = Say;
action1("Timothy");
Action<int> action2 = Mul;
action2(1);
//Func委托-有返回值的方法
Func<int, int, int> func1 = Add;
Console.WriteLine(func1(100, 200));
//泛型委托+lambda表达式
Func<int, int, int> func2 = (x,y) => x * y;
Console.WriteLine(func2(100, 200));
}
static void Say(string str)
{
Console.WriteLine($"{str}");
}
static void Mul(int x)
{
Console.WriteLine(x*100);
}
static int Add(int x, int y)
{
return x + y;
}
}
}
partail类
减少类的派生
partial类与EF-Entity Framework
partial类与ASP.NET Core
枚举类型
枚举类型的本质是认为限定取值范围的整数
枚举类型的比特位用法1248
按位取或|
应用场景-控制文件的打开方式
//枚举类型
namespace cstimothy309
{
class Program
{
static void Main(string[] args)
{
Person person1 = new Person(){ Level = Level.Employee };
Console.WriteLine((int)Level.Employee);//0
Console.WriteLine((int)Level.BigBoss);//3
//比特位用法
person1.Skill = Skill.Cook | Skill.Program | Skill.Drive | Skill.Teach;
Console.WriteLine(person1.Skill);//15
Console.WriteLine((person1.Skill & Skill.Cook)>0);//True
Console.WriteLine((person1.Skill & Skill.Cook)==Skill.Cook);//True
}
}
class Person
{
public int ID { get; set; }
public string Name { get; set; }
public Level Level { get; set; }
public Skill Skill { get; set; }
}
enum Level
{
Employee,//0
Manager,//1
Boss,//2
BigBoss,//3
}
//比特位用法
enum Skill
{
Drive=1,
Cook=2,
Program=4,
Teach=8,
}
}
结构体
struct为值类型
//装箱-将studnet的实例copy后,放在堆上,obj引用着在堆内存上的studnet的实例
//拆箱-将obj引用着的实例强制类型转换回来
//引用类型变量赋值的时候,变量之间copy的是对对象的引用
//值类型变量赋值的时候,变量之间copy的是1个完整的对象
结构体可以实现接口,不能派生自类/结构体
结构体不能有显式的无参构造器,但可以有显式的有参构造器
//结构体
namespace cstimothy3010
{
class Program
{
static void Main(string[] args)
{
//student为局部变量,内存分配在栈上
Student studnet1 = new Student() { ID = 101, Name = "Timothy" };
//装箱-将studnet的实例copy后,放在堆上,obj引用着在堆内存上的studnet的实例
Object obj = studnet1;
//拆箱-将obj引用着的实例强制类型转换回来
Student studnet2 = (Student)obj;
Console.WriteLine($"{studnet2.ID},{studnet2.Name}");//101,Timothy
//引用类型变量赋值的时候,变量之间copy的是对对象的引用
//值类型变量赋值的时候,变量之间copy的是1个完整的对象
Student stu1 = new Student() { ID = 101, Name = "Timothy" };
Student stu2 = stu1;
stu2.ID = 102;
stu2.Name = "Tom";
Console.WriteLine($"{stu1.ID},{stu1.Name}");//101,Timothy
//显示的有参构造器
Student stu3 = new Student(3,"Tim");
stu3.Speak();
}
}
interface ISpeak
{
void Speak();
}
struct Student:ISpeak
{
public int ID { get; set; }
public string Name { get; set; }
public void Speak()
{
Console.WriteLine($"{this.ID},{this.Name}");
}
public Student(int id,string name)
{
this.ID = id;
this.Name = name;
}
}
}