C#笔记:泛型、委托、lambda 表达式与部分代码规范(第四次课)
泛型(类、方法)
本质:通过尖括号<>向类中传递数据类型的参数
目的:既可以处理多种类型的参数,又保证了类型安全
委托(功能类似函数指针)与 事件(特殊的多播委托)
-
委托
-
声明:需要类似声明方法一样声明 返回值 和 参数(被委托的函数必须匹配),也可以使用系统内置的两种委托:Action,Func(通过泛型传递参数类型和返回值)
Aciton:返回值为void,泛型传递参数类型
Func:最后一个泛型传递返回类型,前面的泛型传递参数类型
ps:重要的是数据类型,故使用泛型省略掉了参数名! -
实例化:必要时可使用泛型对 返回类型和参数类型进行选择
-
使用:使用 返回值类型 和 参数类型匹配的方法为其赋值,可以使用 +、-、+=、-=等运算符为委托赋多个值,实现多播委托。(同时调用所有被委托函数)
-
-
事件(特殊的多播委托)
- 使用的委托类型需要传入发送者参数(object sender)
- 将委托实例化时必须使用event关键词修饰(event 不影响运行,去掉也可以)
匿名方法与 lambda 表达式
特点:可以访问匿名函数外的局部变量!(?)、简洁
-
匿名方法:
格式(使用delegate作为“函数名”):delegate(argsType args...) { code body}
(委托中已经定义返回类型,不需要再声明) -
lambda表达式:
格式:(args,...) => {cods}
委托时已定义参数类型和返回类型,不需要再次声明
当参数只有一个时,参数列表的圆括号()可以省略,当只有一行代码时花括号可以省略(类似循环体)
异常处理
-
异常处理关键词
- try:保护区,发生异常则停止执行跳转catch异常处理区
- catch ([ExceptionType e]):可以有多个相连的catch,用于分别处理不同类型的异常,执行规则类似分支判断(因此更上级的异常更靠后)
- finally:无论是否发生异常,都执行的部分
-
自定义异常与异常抛出
- 自定义异常:继承异常父类
- 抛出异常:throw new MyException(args,...)
- 异常抛出的传播:不断向上抛出异常,直到被 catch 捕获(一直到static Main 方法)
attribute
本质上也是一个类
-
自定义:通过继承 attribute 父类定义自定义attribute,可以有各种成员(本质上还是类)
-
使用:
将attribute对象加在方法、类前进行修饰
通过:class/functionType.GetCunstomAttribute(AttributeType) 可以获取在类前面的attribute对象 -
ps:ClassType.GetMethods() 可以获取所有方法方法信息(返回 MethodInfo[]),通过MethodInfo对象可以访问该方法的 attribute
代码组织
-
命名空间(命名空间间可嵌套,通过‘.’访问)
解决:避免类的重名问题
声明:namespace xxx.xxx {}
使用(可以使用该命名空间中定义的类了):using xxx.xxx; -
嵌套类
声明:在类内部声明的类
使用(类似命名空间):声明所在的类.嵌套类
访问:受声明所在的类和自身的访问控制权限控制
场景:当该类一般仅被声明所在的类使用时 -
ps:类本身其实也是一种命名空间?
学习作业代码规范
-
控制属性合法性(作业中以时间类为例):
使用字段 + 属性控制时分秒的合法输入,非法则抛出异常。 -
类的实现应尽量符合实际功能(作业中以时钟为例,使用线程模拟时钟自己走时)
有自运行功能的类可以使用线程实现(Thread)// 线程方法定义 public void Run() { while (true) { DateTime now = DateTime.Now; CurrentTime = new ClockTime(now.Hour, now.Minute, now.Second); TickEvent(this); if (AlarmTime.Equals(CurrentTime)) AlarmEvent(this); Thread.Sleep(1000); } } // 线程方法调用 new Thread(clock.Run).Start(); -
事件作为一种特殊的委托通常会传入事件本身的触发者 sender(作业中以TickEvent为例)
// 事件声明 public event Action<AlarmClock> TickEvent; // 事件声明者触发事件 TickEvent(this); // 传入自身作为参数 // 订阅该事件 clock.TickEvent += ShowTime; // 委托的函数 private static void ShowTime(AlarmClock sender) { // 使用sender接受触发事件的对象 /*code*/ }