下面是自己总结的一些C#语言方面用的少容易忘的地方,总结一下,在用的时候看一下。(仅针对本人)

参数数组

定义一个函数,用来取得数字的和,但是数字的个数不确定。

解决方案: 1,定义一个函数,参数传递过来一个数组; 2,定义一个参数个数不确定的函数,这个时候我们就要使用参数数组。

参数数组相比于数组参数的区别:params

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace _050_参数数组__定义一个参数个数不确定的函数_ {
  8. class Program {
  9. //如果一个函数定义了参数,那么在调用这个函数的时候,一定要传递对应类型的参数,否则无法调用(编译器编译不通过)
  10. static int Sum(int[] array)
  11. {
  12. int sum = ;
  13. for (int i = ; i < array.Length; i++)
  14. {
  15. sum += array[i];
  16. }
  17. return sum;
  18. }
  19.  
  20. //这里定义了一个int类型的参数数组,参数数组和数组参数(上面的)的不同,
  21. //在于函数的调用,调用参数数组的函数的时候,我们可以传递过来任意多个参数,
  22. //然后编译器会帮我们自动组拼成一个数组,参数如果是上面的数组参数,那么这个数组我们自己去手动创建
  23. static int Plus(params int[] array)
  24. {
  25. int sum = ;
  26. for (int i = ; i < array.Length; i++) {
  27. sum += array[i];
  28. }
  29. return sum;
  30. }
  31. static void Main(string[] args)
  32. {
  33. int sum = Sum(new int[] {, , , , , , });
  34. Console.WriteLine(sum);
  35. int sum2 = Plus(, , , , , , , , ,,,);//参数数组就是帮我们 减少了一个创建数组的过程
  36. Console.WriteLine(sum2);
  37. Console.ReadKey();
  38. }
  39. }
  40. }

委托

委托(delegate)是一种存储函数引用的类型。

委托的定义很简单,声明一个函数,然后在前面加上 delegate 关键字,这样就声明了一个委托

委托的使用分两步:声明,定义

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace _053_委托的使用 {
  8. //定义一个委托跟函数差不多,区别在于
  9. //1,定义委托需要加上delegate关键字
  10. //2,委托的定义不需要函数体
  11. public delegate double MyDelegate(double param1, double param2);
  12. class Program {
  13. static double Multiply(double param1, double param2)
  14. {
  15. return param1*param2;
  16. }
  17.  
  18. static double Divide(double param1, double param2)
  19. {
  20. return param1/param2;
  21. }
  22. static void Main(string[] args)
  23. {
  24. MyDelegate de;//利用我们定义的委托类型声明了一个新的变量
  25. de = Multiply;//当我们给一个委托的变量赋值的时候,返回值跟参数列表必须一样,否则无法赋值
  26.  
  27. Console.WriteLine(de(2.0, 34.1));
  28. de = Divide;
  29. Console.WriteLine( de(2.0,34.1) );
  30. Console.ReadKey();
  31. }
  32. }
  33. }

Action委托:返回值为void,参数可以为0个或多个   Action[<param...>] xxx = 某函数

Func委托:有一个返回值,参数可以为0个或多个    Func<[param...],returnType> xxx = 某函数

多播委托:就是定义一个委托后,不止绑定某一个函数,使用+=,-=符号来添加删除绑定的函数。要注意的是,多播委托中,中间如果某一个函数执行出错,后面的都不会执行

委托的使用:比如要定义一个针对学生名及学生成绩的排序(也可能是其它情况),以前的排序方法,需要我们针对不同的情况写不同的排序方法。现在有了委托后,我们可以传入一个类型不定的数组,传入一个委托类型的排序方法,在这个排序方法中写好排序就行。

  1. namespace _007_冒泡排序拓展 {
  2. class Employee {
  3. public string Name { get; private set; }
  4. public int Salary { get; private set; }
  5.  
  6. public Employee(string name, int salary)
  7. {
  8. this.Name = name;
  9. this.Salary = salary;
  10. }
  11. //这里定义了一个针对Employee的比较方法
  12. public static bool Compare(Employee e1, Employee e2)
  13. {
  14. if (e1.Salary > e2.Salary) return true;
  15. return false;
  16. }
  17.  
  18. public override string ToString()
  19. {
  20. return Name + ":" + Salary;
  21. }
  22. }
  23. }
  1. namespace _007_冒泡排序拓展 {
  2. class Program {
           //这里定义了一个通用的排序方法
  3. static void CommonSort<T>(T[] sortArray, Func<T,T,bool> compareMethod)
  4. {
  5. bool swapped = true;
  6. do {
  7. swapped = false;
  8. for (int i = ; i < sortArray.Length - ; i++) {
  9. if (compareMethod(sortArray[i],sortArray[i+])) {
  10. T temp = sortArray[i];
  11. sortArray[i] = sortArray[i + ];
  12. sortArray[i + ] = temp;
  13. swapped = true;
  14. }
  15. }
  16. } while (swapped);
  17. }
  18. static void Main(string[] args) {
  19. Employee[] employees = new Employee[]
  20. {
  21. new Employee("dsf",),
  22. new Employee("435dsf",),
  23. new Employee("234dsf",),
  24. new Employee("ds234f",),
  25. new Employee("dssfdf",)
  26. };
  27. CommonSort<Employee>(employees,Employee.Compare);
  28. foreach (Employee em in employees)
  29. {
  30. Console.WriteLine(em);
  31. }
  32. Console.ReadKey();
  33. }
  34. }
  35. }

Lambda表达式:凡是能用委托表达的都能使用Lambda表达式来表达,反正式子中有这玩意"=>",也没见用这玩意咋样,还要难理解些,不用,谁用谁煞笔

事件:事件是基于委托的,有了委托才会有事件。下面举一个例子,有两个类,丈夫和妻子,妻子类有个方法是看丈夫在玩游戏没,丈夫类有个方法是观察妻子的动向。在以往的写法中,每当妻子调用她的方法后,丈夫也要调用自身的方法,这样在本例中还算好的,如果换成其它的一对多的关系,那么代码量会很大,且维护起来很麻烦。有了委托后(注意,这里说的还是委托,还没有用到事件),我们在创建丈夫后,将丈夫的方法绑定到妻子的一个委托上,这样妻子每次检查时丈夫都会观察到并执行相应函数。

  1. namespace ConsoleApp1
  2. {
  3. class Wife//妻子
  4. {
  5. //这里声明一个委托用来绑定丈夫的观察函数
  6. public Action bindfunc;
  7. public void Coming()
  8. {
  9. Console.WriteLine("妻子:去看看老公在玩游戏没");
  10. if(bindfunc != null)
  11. {
  12. bindfunc();
  13. }
  14. }
  15. }
  16. }
  1. namespace ConsoleApp1
  2. {
  3. class Husband//丈夫
  4. {
  5. public Husband(Wife wife)
  6. {
  7. // 在构造丈夫的时候,就把自身的函数绑定到妻子的delegate上
  8. wife.bindfunc = See;
  9. }
  10.  
  11. public void See()
  12. {
  13. Console.WriteLine("丈夫:盯到看到,媳妇来老");
  14. }
  15. }
  16. }
  1. namespace ConsoleApp1
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. Wife wife = new Wife();
  8. Husband husband = new Husband(wife);
  9. wife.Coming();
  10. }
  11. }
  12. }

嗯嗯,关于事件event,它就是把上面在妻子中声明的委托  public Action bindfunc 改成 public event Action bindfunc,就是加了个event表示而已,那它有啥作用呢。如果不用event标识,那妻子中的委托bindfunc我们可以使用妻子的实例随手调用,用event声明后,它就是一个事件,不能随手用。

属性

我们习惯上把类中的字段设置为私有的,这样外接不能够修改字段的值,然后我们通过定义属性来设置和取得字段中的值

  1. private int age;
  2. public int Age
  3. {
  4. set{age = value;}
  5. get{return age;}
  6. }

从上面可以看到,属性包含两个块,get块和set块。访问属性和访问字段一样,当取得属性的值的时候,就会调用属性中的get块,所以get块,当我们去给属性设置值的时候,就会调用属性中的set块

属性需要注意的地方:

1:、另外,set块和get块可以只提供一个(两个都不提供也行,那相当于该属性没有用),如果只提供set块表示只写,只提供get块表示只读

2、set块和get块可以设置为私有的,设置为私有的块只能在类的内部访问(当然该属性也可以设置为私有,这样该属性只能在类的内部使用)

  1. public string name
  2. {
  3. private set{name = value;}
  4. get{return name;}
  5. }

3、我们也可以不用创建字段,直接设置属性,这样编译器会帮我们自动创建

  1. public int Age{get;set;}

4、属性相对于以前单独创建函数来设置和获取字段值,不同是它可以在设置的时候,做一些需要的操作,比如判断

  1. public int Age
  2. {
  3. set
  4. {
  5. if(value > )
  6. age = value;
  7. }
  8. }

虚方法和隐藏方法

虚方法:在父类中使用virtual关键字声明函数,在子类中使用override关键字声明该函数

隐藏方法:不适用virtual关键字和override关键字声明

定义2个类,Enemy和Boss,Boss继承自Enemy

  1. class Enemy
  2. {
  3. public void Run()
  4. {
  5. print("父类Run");
  6. }
  7. public virtual void Eat()
  8. {
  9. print("父类Eat");
  10. }
  11. }
  1. class Boss:Enemy
  2. {
  3. public void Run()
  4. {
  5. print("子类Run");
  6. }
  7. public override void Eat()
  8. {
  9. print("子类Eat");
  10. }
  11. }
  1. class Test
  2. {
  3. static void Main(string[] args) {
  4. Enemy e1 = new Boss();
  5. e1.Run(); //父类Run
  6. e1.Eat(); //子类Eat
  7.  
  8. Boss b1 = new Boss();
  9. b1.Run(); //子类Run
  10. b1.Eat(); //子类Eat
  11. }
  12. }

可以看到,如果是隐藏方法,那么如果使用父类声明子对象,调用的方法还是父类的方法。因为,隐藏方法只是隐藏,父类中的方法还在。

如果是虚方法,那么调用后都是执行子类中的代码。因为,虚方法重写后父类中的方法就不存在了。

使用虚方法还有一个重要的作用,那就是当声明一个函数的时候,如果当时并不知道具体的实现,只知道以后子类会用到它,那么我们可以先把它声明为虚方法,等着以后子类去实现。

  1. class Test
  2. {
  3. public void Use()
  4. {
  5. UseThis();
  6. }
  7. public virtual void UseThis()
  8. {
  9. }
  10. }

抽象类

抽象类其实和前边说的虚方法有关。虚方法中,用virtual关键字声明后,在子类中可以重写也可以不重写。抽象类使用abstract关键字声明函数(注意:函数使用abstract声明后,那么类自动称为抽象类,也需要使用abstract声明,编译器会提示的),子类中必须使用关键字override实现该函数。

注意,抽象类可以声明子类对象,但是不能直接使用抽象类实例化对象。

  1. abstract class Test
  2. {
  3. public abstract void Use();
  4. }

接口

接口是特殊的抽象类,在抽象类中可以定义字段和普通的方法,但是在接口中只能定义方法,且不允许提供接口中任何成员的实现方式,不允许声明成员修饰符,接口中的成员都是共有的。

说白了,接口中就是声明了一些公有方法,让继承该接口的子类自己去实现。

  1. public interface Test
  2. {
  3. public void Use();
  4. public void Do();
  5. ...
  6. }

C#易忘点的更多相关文章

  1. 关于Verilog HDL的一些技巧、易错、易忘点(不定期更新)

    本文记录一些关于Verilog HDL的一些技巧.易错.易忘点等(主要是语法上),一方面是方便自己忘记语法时进行查阅翻看,另一方面是分享给大家,如果有错的话,希望大家能够评论指出. 关键词: ·技巧篇 ...

  2. jQuery学习易忘细节

    1.类似于alert(""),但不会中断页面操作:console.log("last"); 2.javascript是HTML5以及所有现代浏览器中的默认脚本语 ...

  3. tableView使用的易忘技术点(相对于自己)

    1.在tableView设置右向导航指示箭头 cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator; 2.tableView的系 ...

  4. linux日常易忘指令

    1.编辑全局指令 进入~/.bash_profile 增加"exprot +(启动文件的地址)" source ~/.bash_profilr(刷新) 2.修改mysql密码 my ...

  5. .NET易忘备留 ORACLE存储过程调用

    1.Oracle存储过程调用[返回信息,单体或者列表] public IResult FundBuild(string partnerId,string userId, DateTime beginD ...

  6. Linux考试易忘命令

    这是为了考试而做的笔记 mv命令可以移动可以改名 mv a /test //移动a到test文件夹下 mv a b //把a改名为b 软链接和硬链接的创建 ln -s profile a //prof ...

  7. (一)S5PV210开发板常用易忘操作记录

    一.调试串口 2.SD卡槽 (三)启动方式选择 蜂鸣器下面的白色2针插座(图中红色线圈出来的那个)为选择USB/SD卡启动的开关.默认情况下为SD卡启动,如果需要USB启动则使用短路帽(若没有短路帽, ...

  8. Jsp页面设计易忘点

    文本标签: <b>文本加粗 <i>斜体 <u>下划线 <sub>作为下标 <sup>作为上标 样式: italic;斜体 text-deco ...

  9. 关于canvas 易忘属性

    globalAlpha=1//表示全局的一个透明度值 默认值是1 globalCompositeOperation // 默认值="source-over"(Default)

随机推荐

  1. UNIX高级环境编程(11)进程控制(Process Control)- 进程快照,用户标识符,进程调度

    1 进程快照(Process Accounting) 当一个进程终止时,内核会为该进程保存一些数据,包括命令的小部分二进制数据.CPU time.启动时间.用户Id和组Id.这样的过程称为proces ...

  2. Linux 辅助命令

    0. 说明 记录在 Linux 使用过程中的一些有帮助的命令 1. 命令集合 [1.1 错误输出重定向] # 将错误信息重定向到 /dev/null source /xxx >/dev/null ...

  3. 读高性能JavaScript编程 第三章

    第三章  DOM Scripting  最小化 DOM 访问,在 JavaScript 端做尽可能多的事情. 在反复访问的地方使用局部变量存放 DOM 引用. 小心地处理 HTML 集合,因为他们表现 ...

  4. FZU Monthly-201901 tutorial

    FZU Monthly-201901 tutorial 题目(难度递增) easy easy-medium medium medium-hard hard 思维难度 AHG F B CE D 编码难度 ...

  5. 【Alpha】团队课程展示

    团队展示报告 团队分工 陈涵 PM + 后端开发 ,统筹全队安排,完成了登录界面,以及一部分部门模块和课程中教室模块的编写. 张鹏 后端开发,主要完成了主界面和其他功能界面的编写,课程界面的编写,以及 ...

  6. Articulate Presenter文字乱码的排除

    Articulate Presenter乱码的问题如何设置? 字体乱码的设置: 1.首先如果ppt中有中文内容,肯定需要将Articulate Presenter的Character Set设置为No ...

  7. JSSDK图像接口多张图片上传下载并将图片流写入本地

    <span style="font-size: 14px;"><!DOCTYPE html> <html lang="en"> ...

  8. Scala学习之路 (三)Scala的基本使用

    一.Scala概述 scala是一门多范式编程语言,集成了面向对象编程和函数式编程等多种特性.scala运行在虚拟机上,并兼容现有的Java程序.Scala源代码被编译成java字节码,所以运行在JV ...

  9. 模糊查询SSD_DATA盘谁使用率高?

    select sum(bytes / 1024 / 1024 / 1024),       d.owner,       d.segment_name,       d.segment_type  f ...

  10. Docker学习要点记录

    Docker的架构和底层技术: 1.docker提供了一个开发,打包,运行app的平台2.把APP和底层infrastructure隔离开来 docker底层技术支持: 1>Namespaces ...