cs
using System;
using System.Collections.Generic;
namespace HelloGeneric
{
internal class Program
{
public static void Main(string[] args)
{
Apple apple = new Apple { Color = "Red" };
Book book = new Book { Name = "C# Programming" };
Box<Apple> appleBox = new Box<Apple> { Cargo = apple };
Box<Book> genericBookBox = new Box<Book> { Cargo = book };
Console.WriteLine($"Apple Color: {appleBox.Cargo.Color}");
Console.WriteLine($"Book Name: {genericBookBox.Cargo.Name}");
Student<ulong> student = new Student<ulong>();
student.Id = 100000000000000;
student.Name = "Alice";
Console.WriteLine($"Student ID: {student.Id}, Name: {student.Name}");
Teacher teacher = new Teacher();
teacher.Id = 10000000;
teacher.Name = "Mr. Smith";
Console.WriteLine($"Teacher ID: {teacher.Id}, Name: {teacher.Name}");
// 使用泛型列表 特化后
IList<int> list = new List<int> { };
for (int i = 0; i < 100; i++)
{
list.Add(i);
}
foreach (var item in list)
{
Console.WriteLine(item);
}
// 使用泛型字典 特化后
IDictionary<int, string> dict = new Dictionary<int, string>();
dict[1] = "Tom";
dict[2] = "Jerry";
foreach (var kvp in dict)
{
Console.WriteLine($"Key: {kvp.Key}, Value: {kvp.Value}");
}
// 使用无返回值泛型委托 特化后
Action<string> sayAction = Say;
sayAction("World");
// 使用有返回值泛型委托 特化后
Func<int, int, int, int> addFunc = Add;
var result = addFunc(1, 2, 3);
Console.WriteLine($"Add Result: {result}");
// 使用Lambda表达式 特化后
Func<double, double, double> multiplyFunc = (x, y) => x + y;
var mulResult = multiplyFunc(2.5, 4.0);
Console.WriteLine($"Multiply Result: {mulResult}");
}
static void Say(string message)
{
Console.WriteLine($"Hello,{message}!");
}
static int Add(int a, int b, int c)
{
return a + b + c;
}
}
class Apple
{
public string Color { get; set; }
}
class Book
{
public string Name { get; set; }
}
//非泛型类实现泛型接口 特化之后
//
class Teacher : IUnique<int>
{
public int Id { get; set; }
public string Name { get; set; }
}
//泛型类实现泛型接口
class Student<TId> : IUnique<TId>
{
public TId Id { get; set; }
public string Name { get; set; }
}
//泛型接口
interface IUnique<TId>
{
TId Id { get; set; }
}
//泛型类
class Box<TCargo>
{
public TCargo Cargo { get; set; }
}
}
2.总结笔记
C#笔记 程序:可读性 健壮性
9.谁调用谁负责压栈,压多个参数时,先压左边再压右边
函数变成类的成员时,变成方法
复用:a函数的定义中使用b函数,b函数的定义中使用c函数,其中使用也叫复用
耦合:类与类之间的关联叫耦合,关联越高耦合越大,耦合越大越不好
聚合:类自己内部联系叫内聚,联系越高内聚越大,内聚越大越好
方法中实参和形参要个数相同和类型相同
构造器:类自带初始化的构造器,将类中变量初始化为0,也可以public+类名(){}创建,构造器可以延伸出工厂模式
构造函数缺点:1.不能返回子类实例的结果 2.要实现多个功能的话要不断重载,所以不如工厂模式起码名字能显而易见
字符串的值如果全是0将,该字符串就是null值
重载:名字相同,参数个数或类型不同,或方法类型不同可构成重载
委托:委托函数(方法)可以被委托一个无返回无参数的方法
new操作符可以调用构造器创建实例赋给变量,也可以不赋那么一次性的用后自动释放
依赖注入,把紧耦合改成低依赖耦合
try{check}catch(){}用来抓捕异常,try是等待,chech是抓捕异常
int x = 100;是声明变量时追加了初始化器 总共一步
int x;x = 100;是先声明变量,然后赋值,总共两步,所以二者不同
const int x = 100;const修饰的变量后面一定要跟初始化器,毕竟const修饰的常量不允许被赋值
无论块语句里有多少语句,编译器只把块语句当作一条语句看待,{}内的是块语句
快捷键:ctrl+{ 跳转至程序开始花括号{ ctrl+} 跳转至程序结束花括号}
if+一条语句 但因为{}被当作一条语句,所以常用if+()+{}来执行{}中的多条语句,他们三个部分组成一条语句
作用域:变量声明之后,变量声明块语句之内
冒号是标签的意思,一个语句可以打多个标签
迭代语句--循环语句:while(){} do{}while();
do{}while();先执行->(true)->继续执行,反之(fasle)->结束
contine 放弃当前循环,开始新的循环;break 跳出并结束循环
foreach() 每访问一个元素就进行一次循环,直到把所有元素都访问完
C#中所有数组的基类都是array这个类
字段只存活在类体里,也就是{}中
实例字段创建在运行到实例程序时,静态字段创建在加载程序时,所以静态字段只创建一次,实例不一定
被readonly修饰的就是只读字段,只读字段只能在构造器里被赋值
字段属性特征:保护字段被赋予合法值,相比构造访问接口更简洁便捷
把委托当作参数传进方法,常用两种用法
模板方法:借用指定的外部方法产生结果
回调方法:调用指定的外部方法
模板方法示例(类似函数指针):
public Box WrapProduct(Func<Product>getProduct
{
Box box = new Box(); //获取一个箱子
Product product = getProduct.Invoke(); //去获取产品
box.Product = product; //把产品装到箱子里去
return box; //返回这个箱子
}
class ProductFactory
{
public Product MakePizza()
{
自定义委托:
委托是一种类 pubilc delegate double Calc(double x,double y);
其中Public表示公开,delegate表示委托类,double表示返回值类型,括号内的double表示参数类型
单播委托,一个委托调用一个方法;多播委托,一个委托调用多个方法,且顺序与用户封装顺序一致
可用接口取代委托,也就是头文件方法
Action<>委托只能引用没有返回值的委托
Func<>委托能引用有返回值的委托,最后一个类型是返回值类型
属性是存储访问数据,方法是加工数据,事件是对象或类间的信息传递
MVC MVP MVVM等模式是事件模式的高级玩法
事件模型五部分:事件拥有者,事件成员,事件响应者,事件处理器(本质是回调方法),事件订阅
类型一:拥有者是响应者的一个字段或成员
类型二:响应者是拥有者的一个字段或成员
类型三:响应者和拥有者是同一个对象
类型四:响应者和拥有者是不同类的成员
抽象类:未完全实现的类
1.要用abstract修饰,没有被实现的类,不能有任何逻辑实现(类似纯虚函数)
2.唯一作用,给别的类当基类,将未实现的抽象功能下推给派生类去实现或者派生类也可以不实现,继续下推
abstract class Vehicle{
public void stop(){
Console.WriteLine("Stopped!");
}
public abstract void Run();//这是抽象类里的抽象方法
}
class Car:Vehicle{
public overridde void Run(){//对继承的抽象方法进行重载实现功能
Console.WriteLine("Car is running...");
}
}
接口:完全未实现的类
1.接口一般和抽象类搭配使用
2.接口里面的函数都是抽象函数且都是public,所以省略了public abstract的修饰
3.接口就是服务的提供者和服务的消费者之前的契约
interface IVehicle{
void Stop();
public abstract void Fill();//其他两个只是省略了修饰词,其实作用都一样
void Run();
}
abstract class Vehicle:IVehicle{
public void stop(){
Console.WriteLine("Stopped!");
}
public overridde void Fill(){//因为这个函数的父类被abstract修饰,所以要用overide进行重载实现
Console.WriteLine("Pay the fill...");
}
}
依赖反转:不再是传统自顶向下,而是在顶和底之间添加接口层
单元测试:用xuint和mock进行模拟测试
接口分离原则:将胖接口分离成多个小接口,胖接口再继承多个小接口
接口隔离原则:服务调用者不会多要,服务提供者不会多个
接口显式实现:只有特定的实例化对象才能看到该类的隐藏接口,其他的就是显式接口
依赖注入式通过反射和接口结合形成的应用
反射:
依赖注入:要加using Microsoft.Etensions.DependencyInjection
依赖注入是自动连线功能,用注册的类型创建对象再都注入到构造器中,类似java的springboot
泛型(generic):解决类型膨胀和成员膨胀
泛型类模板:class Box<TCargo>{public TCargo Cargo{get;set;}}
list:数组,有自动扩容机制,当原来分配的存储空间不足时会自动生成更大的空间将原来的数据copy进去并替换原来的数组
Lambda表达式:(参数)=>{逻辑},匿名方法
Partial类:实现将同一个类分成几份在不同文件
文件1:public partial class Book{}
文件2:public partial class Book{}
枚举:枚举只能定义命名的常量值
定义:enum Level{Employee,Manager,}
使用:public Level Level{}
结构体:值类型,copy的是完整对象
结构体只能从接口派生,不能从其他类型派生出来,而且结构体的构造器得是有参的
现代编程:算法,数据结构,面向对象
马士兵老师设计模式