Unity学习日志_C#基础注意事项

Unity基础学习之C#学习(一) C#基础部分1. 开发环境搭建1.1 Visual Studio1.2 Unity1.3 MSDN2. 进制2.1 进制概念2.2 进制转换3. 原码、反码、补码3.1 正负数三码的计算方式3.2 使用三码的原因4. C#开发语言介绍4.1 用VS创建一个项目4.2 第一个C#文件4.3 注释5. 数据类型5.1 C#支持的基础数据类型6. 常量和变量6.1 常量6.2 变量6.3 常量与变量之间的区别6.4 常量及变量命名规则和规范7. 运算符 1. 开发环境搭建 1.1 Visual Studio 下 阅读详情

Unity学习日志_Unity初识_C#基础注意事项

本篇博客将整理笔者学习C#基础以来认为需要注意的一些细节和事项,内容可能并不完整且可能存在错误,欢迎各位大佬前来指正。

1. 开始

  1. C#严格区分大小写。

    1. “=”的右侧可以为表达式,但会降低代码的可读性。
    
    1. 例:

      int numA = 1,numB = 2;
      bool _isEqucal = numA == numB;
      //_isEqucal值为false
      
    2. namespace :命名空间,包含一系列的类。对类进行逻辑划分,作用:为了避免重名。

    3. using :引用xx命名空间。

    4. C#格式化输出:string.Format();如何保留空字符:char a = ‘\0’;(\0也属于转义字符的一个)。String b = “”;保留空字符串。

    5. 局部变量必须声明赋值之后才可以使用。但是成员变量存在初值,可以声明之后直接使用。

    6. C#的数据类型默认不允许使用null赋值,但在数值类型后加一个?就可以了。例如:int? = null;

    7. 声明object类型,可赋值所有类型(因为所有类型都是object的子类)。

    8. 递归能别用就别用,递归的效率相对于循环很低。

    9. 交错数组不属于多维数组。它属于数组的数组。

    10. 对于引用类型,xx[0]改的一定是堆中的数据。xx = dd;改的一定是栈中的引用。

    11. 使用数组作为形参的时候,可以选择使用 数组名.CopyTo(需要复制的数组名,开始复制的索引值)来创建新数组,这种方法依旧会对方法外原数组产生影响。

    12. 对于string和数值类型的转换永远都是tostring和Parse方法。

    13. C#命名严格遵守驼峰命名法。

    14. 面向对象的三大特点:封装,多态,继承。

    15. 和多态相关的都不能是静态。因为静态不是面向对象的。

    16. 使用父类声明中存放着子类对象的形式,调用父类虚方法,一定会调用对应子类对象的重写方法。

数据类型:

在这里插入图片描述

2. 运算符

2. 赋值运算符

  1. 赋值表达式本身也有值,所以有以下写法:

    int numA,numB;
    numA = numB = 1;
    

3. 算数运算符

  1. int型相除,结果会先被保存为int型,之后转为存放结果的变量类型。所以整形相除小数点后面的数值一定会丢失!整型和非整型相除,非整型和非整型相除没有影响。小数精度取决于非整型。
  2. 数值类型计算时特殊现象:byte+byte=int,byte+short=int,这两个数值范围小,很容易超出范围所以结果存为int型。Decimal不能和非整型相加减,因为存储的结构不同,,但可以和整型相加减。,其余情况两个数值类型做计算时,数值类型向大的靠拢。

4. 快捷运算符

  1. 快捷运算符例如“+=”,“*=”等操作实际效果如下:

    int numA = 1,numB = 2;
    numA += numB;
    //numA结果为3。等价于下面操作:
    numA = numA + numB;
    

5. 一元操作符

  1. numA++和++numA的区别:

    int numA = 1,numB;
    numB = numA++;
    /*
    效果等同于:
    numB = numA;
    numA += 1;
    */
    numB = ++numA;
    /*
    效果等同于:
    numA += 1;
    numB = numA;
    */
    

6. 三元操作符

  1. 三元操作符的语法结构:

    //数据类型 变量名 = 条件?满足条件:不满足的条件;
    string str01 = 1 > 2 ? true:false;
    

7. 逻辑运算符

  1. 计算机短路逻辑:
    1. &&:对于与运算,如果第一项已经确定为假,则不在计算第二项,结果为假。
    2. ||:对于或运算,如果第一项已经确定为真,则不再计算第二项,结果为真。
    3. 总结:当进行逻辑运算时,不论是&&运算还是||运算,尽量让计算量小的占在第一计算项。这样可以减少平均计算时间。

3. 数值转换

  1. 显式转换:由大范围到小范围的强制转换。

  2. 隐式转换:由小范围到大范围的自动转换。

    1. 隐式转换的经典例题:

      /***************/
      int numA = 1;
      numA += 3;
      Console.WriteLine(numA);
      /***************/
      byte numB = 1;
      numB += 3;
      /***************/
      /*
      问题:这两个是否一样?
      答:不一样。因为byte+int = int,但b变量是byte类型的,需要转换成byte型进行存储。
      */
      
  3. 拆装箱操作:值类型和引用类型之间的转换。

    int numA = 123;
    Object tempNum = numA;//装箱操作,Object为引用类型
    float numB = (float)tempNum;//拆箱操作
    //注意:使用“+”直接做不同类型数据的字符串连接会导致拆装箱操作。连接字符串可用下面方法实现:
    String str01 = numA.toStirng()+"456";
    
  4. 数值与字符串之间的转换:(此过程不会发生拆装箱操作但属于值类型和引用类型之间的转换)

    1. 数值==》字符串:

      数值.toString();
      

      字符串==》数值:

      想要转成的数值类型.Parse("字符串");
      

4. 内存分配

1. 内存分配:

程序运行时,CLR将申请到的内存空间逻辑划分成栈区和堆区

  1. 栈区:
    1. 空间小,读取速度快。
    2. 用于存储正在执行的方法,分配的空间叫做栈帧,栈帧中存储方法的参数以及变量等数据,方法执行完毕后,对应的栈帧会被清除。

  2. 堆区:

    1. 空间大,读取速度慢。
    2. 用于存储引用类型的数据。

2. 局部变量:

定义在方法内部的变量

  1. 特点:
    1. 没有默认值,必须自行设定初始值,否则不能使用。
    2. 方法被调用时,存在栈中,方法调用结束后从栈中清除。
  2. 局部变量中值类型和引用类型局部变量的区别:
    1. 值类型(直接存储数据):声明在栈中,数据存储在栈中。
    2. 引用类型(存储数据的引用):声明在栈中,数据存储在堆中。栈中存储该数据的内存地址。

3. 成员变量:

  1. 特点:
    1. 有初始值,可以声明后直接使用。
    2. 存在堆中。
    3. 类被实例化后存在堆中。类的实例化对象被回收时,成员变量从堆中被清除。(局部变量在方法被调用时生成)。
    4. 可以与局部变量重名。(局部变量的声明在栈中,成员变量在堆中,所以可以相互之间重名)。在一起使用的时候用this指代。
  2. 成员变量中值类型和引用类型局部变量的区别:
    1. 值类型(直接存储数据):声明在堆中,数据存储在堆中。
    2. 引用类型(存储数据的引用):声明在堆中,数据存储在堆中。

5. 循环语句

  1. for

    for循环的应用:预定次数的循环,遍历循环。累加累乘等操作。

  2. while

    while短路逻辑:

while(ture){
	if(结束条件){
		break;
	}
	//循环体
}

​ 3. foreach:非常适合遍历数组

​ 1. 语法:foreach(var item in array){

​ 方法体

​ };

​ 2. 其中item变量代表数组中的项,无法赋值,array为需要遍历操作的数组。

​ 3. 优点:对于遍历操作十分方便。

​ 4. 缺点:仅限于遍历方便。性能不如for循环。不能修改元素(赋值)。

6. 分支语句

  1. if else
  2. switch
    1. switch选择语句中,case后跟的是括号里变量或表达式的具体值。且括号里的变量不能为单纯的非整型变量(float之类)。
      1. 原因是switch的判断条件只能是等于,对于数据类型的精度要求比较高。字符型、布尔型、枚举型都可以转换成整型进行判断,是因为整形在相等不相等上有很大的确定性,而float和double表示的小数,毕竟精度都是有限的,超过限度以后的等于和不等于计算机就不好判定,故不能用。

在这里插入图片描述

7. 方法

  1. 有返回值类型的方法的返回值只要是可兼容(可以隐式转换的)的就行。比如:float返回值类型可以返回一个int变量。
  2. return语句的作用:返回数据,退出方法。对于返回值类型为void的方法内部可以写return;表示退出方法。
  3. 方法体应当写的小,这样代码的重用率会更高。
  4. 书写大型方法时的处理原则:分而治之。

1. 方法重载

  1. 方法重载:在不同条件下解决同一类相似问题可以使用相同的方法名(参数的类型,数量不同),不同方法之间根据参数来区分。当然方法体通常来说是有区别的。这样做可以让调用者只需要记住一个方法就可以了。

2. 递归

(1) 核心思想:将问题转移给范围缩小的子问题。

(2) 优势:可以将复杂的问题简单化;可以使用代码体现数学公式的思想。

(3) 缺点:性能较差。原因是每次递归的时候都需要在内存上开辟一段新的空间,每次return返回时都需要释放内存上开辟的空间。

(4) 适用性:当解决问题时发现了相同的规模更小的子问题时,可以用递归解决。

(5) 在写递归的时候一定要注意结束递归的条件不能丢。

8. 数组

  1. 数组:在内存上开辟的连续的一块空间,用于存储若干个相同类型的数据。

  2. 数组通过索引来访问数组内的数据,从0到数组.length-1。

  3. 可以使用foreach来遍历数组。

  4. 一维数组和交错数组动态获得数组长度:array.Length();

  5. 二维或多维数组动态获得数组长度:

    1. array.GetLength(0)获取行数。

    2. array.GetLength(1)获取列数。

    。。。。。。

    初始化交错数组时,其元素的new运算符不可省略。

10. 参数

  1. 参数数组:
    1. 关键字:params
    2. 适用性:当所需传入的参数类型固定但数量不固定时可以使用。
    3. 使用参数数组和不使用参数数组的区别(Add方法为参数列表为数组的累加方法):
      1. 使用params:Add(1,2,3,4,5,8,45);
      2. 不使用params:Add(new int[]{1,2,3,4,5,8,45});
    4. 优势:使用params对于方法内部没有影响,对于方法外部可以传入数组,可以传入一组类型相同的数据,也可以传入一组类型相同的变量。甚至可以不传递参数。方便调用者调用方法。
  2. 输出参数:
    1. 关键字:out
    2. 传递实参变量的引用(地址)这一点和引用参数相同。
    3. 作用:返回结果。传递的实参变量本身作为了存储结果的变量。
    4. 特点:使用前实参变量可以不赋值。
  3. 值参数:
    1. 无关键字默认就是值参数。
    2. 值参数的传递就是赋值的过程,即变量中存的是什么就传递什么。
  4. 引用参数:
    1. 关键字:ref
    2. 传递变量的地址。
    3. 对于ref参数,传进来的为变量的地址,当修改时修改的是变量所直接存放的数据。
    4. 值参数和引用参数的区别(以new新数组为例,上图为值参数,下图为引用参数):

在这里插入图片描述
在这里插入图片描述

11. 垃圾回收器GC

1. 产生垃圾的原因:当方法执行完后,对应的栈帧会被清除,此时值类型数据会随之一起被清除,但引用类型只是清除了一个指针,对应的堆中的数据并没有清除,此时就产生了垃圾。
2. 垃圾回收时会占用大量的计算机资源,所以在实际项目开发时要尽量选择时段进行垃圾回收。
3. 一般情况下,GC会在内存空间不够的时候进行自动调用。
4. GC工作原理:GC线程会跟踪栈中的引用,如果GC无法跟踪到某一个堆中的内存,则认为这块内存是垃圾,标记为可回收(不会立即回收)。

12. string类型

1. C#中的String和string的区别:

  1. string是c#中的类,String是.net Framework的类(在c# IDE中不会显示蓝色) 。
  2. c# string映射为.net Framework的String 。
  3. 如果用string,编译器会把它编译成String,所以如果直接用String就可以让编译器少做一点点工作 。
  4. 如果使用c#,建议使用string,比较符合规范 。
  5. String只有在前面有using System;的时候并且当前命名空间中没有名为String的类型(class、struct、delegate、enum)的时候才代表System.String 。
  6. string是关键字,String不是,也就是说string不能作为类、结构、枚举、字段、变量、方法、属性的名称,而String可以 。

2. string的特性:

1. 不可变性:
  	1. string类型作为C#的引用类型,其内部存储的数据是不可改变的。原因是无法得知接下来要存储的字符串大小,如果强行存入则会导致内存溢出。Object类型也存在这个特性。
2. 字符串池:
	1. 当一个新的字符串常量被创建时,都会先去字符串池中查看是否存在相同的文本。如果存在,则直接返回该对象的引用,否则创建新的字符串常量存储在字符串池中。目的:提高内存利用率。

13. 枚举

1. 枚举:用于使数值类型01234产生逻辑意义。相当于给01234这类数据添加了个标签。枚举类型与类同级但属于值类型,可以写在类内部和外部。
2. 当想要一次性选择多个枚举常量时:
  	1. 枚举值的要求:任意多个枚举值做|(按位或,也就是讲一个数转换成二进制后各个位对应做或操作)操作结果不会和其他枚举值冲突。(值以2的n次方来设置,这样可以保证做按位或操作时结果不会冲突)。
  	2. 定义枚举时用[flags]修饰,程序员内定的规则。
  	3. 当想要输入多个枚举值时,使用枚举值做|操作的方式传入。
  	4. 方法内部使用&(按位与)操作,&的结果不为0说明包含。
3. 枚举类型的数值转换:
	1. int ==》enum,显式转换直接转。
	2. enum ==》int,显式转换直接转。
	3. enum ==》string,tostring()方法。
	4. string ==》enum, enum.Parse方法。

14. 类和对象

  1. 通常每个类都在一个独立的cs文件中。

  2. 类中的变量默认为private,但是为了规范要自己手动敲出来。

  3. this关键字:this中存放当前调用方法的对象引用。

  4. 对象是类的实例,调用构造函数才会产生类的实例。

    Wife wife01 = new Wife();//调用构造函数之后,此时wife01成为Wife类的实例
    wife01.Cooking();//此时Cooking方法中的this指代的就是wife01
    
    1. 创建的类在堆中需要内存空间的大小取决于类中声明的字段。
  5. 自动属性不能限制存入字段中的数据,普通的公开属性可以限制。

类的进阶应用:

  1. 类(结构)属性进阶应用:定义以自身类型为返回值的方法或属性。此类用法应定义在构造函数之后。原因:返回对象需要new使用构造函数,且对象内包含的数据是类(结构)的字段,所以需要放在他们后面。

1. 构造函数

1. 构造函数:构造类的对象的函数,提供创建对象的方式,常常用于初始化类的数据成员。(类中没有构造函数时,会自动提供无参构造函数)构造函数没有返回值。构造函数只在new的时候调用一次。所以适合初始化。
2. 使用构造函数初始化的时候,建议使用属性赋值,因为通常情况下属性中存在数值限制。
3. 构造函数不能被外部手动调用,但构造函数可以调用构造函数。
4. 在构造函数后面加:this(参数列表)就可以调用对应的构造函数。

2. 访问修饰符

1. public:类的内部和外部都可以访问。
2. internal:同一程序集(namespace)的可以访问,程序集外的不能访问。
3. protected internal:类的内部,继承该类的子类或者另一程序集继承该类的类可以访问。
4. protected:类的内部和继承该类的子类可以访问。
5. private:类的内部可以访问。

15. 继承

  1. 继承的特点:
    2. 子类可以继承父类成员,但只能使用父类的非私有成员。(私有成员会被继承,但受限于修饰符限制子类无法使用)
    3. 父类不可以使用子类成员。
    4. 继承时基类的构造函数不被继承。
    5. 父类引用可以指向子类对象。但只能使用父类成员,或者子类的重写方法。
  2. 适用性:不同类之间存在相同的代码,则将相同的代码提取出来作为这几个类的父类。
  3. 其他叫法:父类也叫基类,子类也叫派生类。
  4. 继承的特性:
    1. 单根性:一个派生类只能有一个基类(可以有多个接口)
    2. 传递性:可以将继承想成树结构,子节点的类可以继承向上回溯所有父节点类的非私有字段。
  5. base关键字:由于基类在子类被创建时会在子类对象中创建基类对象,base指的就是这个基类对象(base指向直接基类),是这个子类对象独有的。
  6. 一个类或者结构体只能继承一个基类,但可以继承多个接口。

关于构造函数

  1. 关于构造函数的继承:首先需要明确的是,子类并没有继承父类的构造函数。因为如果父类中存在私有字段,子类的实例就无法对父类的私有字段赋值。
  2. 问题解决:C#中,当创建子类对象的时候会调用子类的构造函数,这时候C#会从扩充类以此向上寻找基类,当找到最初的基类后,依次向下执行无参构造函数,最后执行子类的构造函数。原因:子类想要调用父类的成员就需要有父类对象。所以要调用父类的构造函数。
  3. 例子:有A,B,C,D四个类,且A->B->C->D(D为基类)则创建A对象的时候构造函数的执行顺序为:D,C,B,A。
  4. 如果new的是子类的全参构造函数需要通过:base(参数列表)调用父类的全参构造函数。

16. 静态(包含静态和实例的一些比较)

1. 静态成员变量:

  1. 静态成员变量:在类中,带有static修饰符的字段为静态成员变量。类中分为实例成员变量和静态成员变量。
  2. 静态成员变量属于类,类在被加载时初始化(在C#中类名一旦被提及,对应的类就会被加载装入内存),且只有一份存储在内存中的“静态区”。
  3. 实例成员变量属于对象,在每一个对象被创建时初始化(对象创建时需要开辟多大的空间取决于实例成员变量),且每个对象一份。
  4. 特点:存在优先于对象,被所有对象共享,常驻内存。

2. 静态构造函数:

  1. 静态构造函数&(实例构造函数):
    1. 初始化类的静态数据成员。(初始化类的实例数据成员)
    2. 仅在类被加载时调用一次。(仅在创建对象时调用一次)
    3. 不能使用访问修饰符。(可以使用访问修饰符,一般为public)

3. 静态方法不能访问实例成员:

  1. 静态方法只能访问静态成员:当对象调用实例化方法时会传递对象自身的引用,这样方法才能知道是谁调用了自己。并可以使用实例成员。而静态方法是类的方法,调用时不需要引用,故不能访问实例成员。实例方法在被调用时才会被装入内存。

4. 优点:

  1. 单独空间存储
  2. 可被本类的所有对象共享
  3. 可直接被类名调用

5. 缺点:

  1. 静态方法只能访问静态成员
  2. 共享时会出现并发。

17. 密封类

1. 关键字:sealed
2. 用途:
  	1. 防止继承的滥用而导致项目结构过于复杂。
  	2. 防止重写方法被再次改写。
3. 注意:
	1. 密封类中不能包含虚方法(Virtual)和抽象方法(abstract),因为在密封的类没有为派生类提供实现其虚方法和抽象方法的机会。如果想要密封这个类,这个类必须是“完整的”。
	2. 密封方法必须是重写方法。
	3. 静态不能密封。

18. 结构体

1. 语法:与类基本相同。

  1. 使用关键词定义(结构:struct,类:class)。
  2. 语法结构包含字段,属性,构造函数,方法。
  3. 非带有static,const修饰的字段不可直接初始化。(由于类相对于构造体更为常用,所以在类中编译器会根据习惯来自动为开发者做一些事情)
  4. 构造函数中需要初始化所有字段或者不做初始化。

2. 结构体相对于类的区别:

  1. 结构是值类型,直接存储数据;类是引用类型,间接存储数据。
  2. 结构的无参构造函数不能写,编译器自带。
  3. 结构中如果要使用自动属性,需要构造函数调用无参构造函数来辅助实现。
  4. 结构不能继承,但可以实现接口。

3. 适用性:

  1. 表示坐标,颜色(RGBA)等轻量级对象,原因是方法调用结构的时候,结构对象的值存储在栈(空间小,不适合存储大量变量)中。
  2. 表示坐标这种变换频繁的变量。因为方法中的结构对象存储在栈中,频繁改变不会产生垃圾。

19. 抽象类

1. 关键字:abstract
2. 抽象类只能做其他类的基类。不能实例化。
3. 派生类需要实现所有的抽象方法,普通方法不用管。
4. 当基类中有方法不确定方法体时就可以使用抽象类。

20. 接口

接口特点:

  1. 接口完全抽象,内部不可以有实现的方法。
  2. 一个类可以继承一个基类和多个接口。
  3. 接口适合用来做小而简炼的功能。
  4. 接口命名:IXXXable。
  5. 接口中只能包含方法,属性,索引器和事件声明,不能包含构造函数,也不能包含字段。
  6. 接口中都隐式声明为public(类里默认private),不能再用public声明。
  7. 接口可以用类或者结构实现。
  8. 接口不能实例化。
  9. 接口只能继承接口,类可以继承接口也可以继承类。
  10. 接口可以多继承,可以用一个接口将多个需要继承接口集合在一起,再由类去继承。
  11. 继承接口的方法必须全部实现,而继承抽象类则需要实现所有抽象方法。

显示实现接口:解决方法重名问题。

  1. 实现接口方法时命名采用:接口名.方法名。

接口的作用:

  1. 代码通过接口定义来表明自己对外开放的能力,具体的实现则交给实现这个接口的类。只要实现了这个接口的类,都一定存在对应的方法,那么我拿到这个类的实例对象的时候,就一定可以调用这个对象所实现的方法。

21. 多态

多态:C#中关于多态的定义是同一操作(相同的方法)可作用于不同类的实例,且有不同的执行结果。

1. 实现多态1:虚拟方法和重写方法。

  1. 在基类中用virtual标记的方法称之为虚拟方法,可以在扩充类中使用override重写此方法。

    1. 重写的方法的返回值类型,参数个数,类型,方法名称都需要和虚拟方法一致。
    2. 虚拟方法不能是static类型,因为多态是面向对象的需要实例化。
    3. 虚拟方法不可以是private类型。因为子类不能访问父类的私有对象。
  2. 补充:new隐藏方法:

    1. 当基类无法被修改但又不是虚方法,需要使用new来隐藏基类中的同名方法。

2. 实现多态2:实现抽象类。

3. 实现多态3:实现接口。

22. 泛型

1. C#泛型集合类:集合类型<数据类型>,比如List<User>,c#泛型集合类本质是对特定类型数组的封装,直接操作数组比较麻烦,所以就把一些特定功能和数组一起封装在了一个集合类中。集合类型包括:List<Type>列表,SoredList<TKey,TValue>排序列表,Dictionary<TKey,TValue>字典,Queue<Type>队列,Stack<Type>栈。
2. 强烈推荐使用泛型集合类而不使用非泛型集合类,虽然两者都是对于数组的封装,但非泛型集合类没有指定数据类型,这导致了频繁的拆装箱操作和不安全数据类型问题,泛型集合通过指定数据类型很好的解决了这两个问题。

where

  1. where用于限定泛型的范围。

  2. 可以限定特定类型where T :int

  3. 可以限定是引用类型还是值类型:

    1. where T :class//限定引用类型
    2. where T :struct//限定值类型
  4. 可以限定构造函数的类型:

    1. where T :new()//类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。
  5. 可以是限定为一个接口:

    1. where T :Iinterface//其中T必须是一个实现了接口的类型
  6. 可用于泛型类,泛型方法,泛型委托

23. 委托&事件

委托(引用类型):

  1. 特点:所有的方法都可以通过委托来调用。委托相当于是C++中的函数指针,存放方法的引用。

  2. 可以将委托理解成方法的多态,同一个委托可以调用不同的返回值类型,参数相同的方法。

  3. 语法:

    1. [访问修饰符] delegate 返回类型 委托名(参数列表);
  4. 通过委托调用方法:

    1. 直接使用方法名,前提是该方法与传入的委托类型有相同的返回值类型和参数列表。
    2. 实例化委托(将方法引用存放到委托中),调用委托。
    3. 注意这时候传进来的对象是一个方法。
  5. 通过委托可以调用静态方法,也可以调用实例方法。

事件(本质还是委托):

事件的本质是委托,其是利用委托来实现的,所以和对应委托有相同的返回值类型和参数列表。同时注册事件的方法也需要有相同的返回值类型和参数列表。注:这导致事件和其委托返回值类型为void。

  1. 事件声明:

    1. 先声明一个委托:
      1. public delegate void MyEventHandle();
    2. 利用委托声明事件:
      1. public event MyEventHandle MyEvent;
  2. 事件注册:

    1. 使用 “+=” 注册,使用 “-=” 取消注册。注册的方法可以为委托。单委托在注册的时候需要实例化。注册的过程其实就是将引用传给事件的过程。被注册的方法叫做事件处理方法。
  3. 事件被触发的过程:

    1. 事件触发–》调用OnXXX方法–》调用事件–》根据注册事件调用对应的事件处理方法。
    2. 其中OnXXX方法需要和被监测对象(可以是属性(通常用于监测字段变化),可以是方法)放在一起。
    3. 一旦调用了OnXXX方法,后面就会连锁调用。
  4. 具有标准签名的事件:

    1. 在绝大多数情况下使用的都是具有标准签名的事件。
      1. public delegate void EventHandler(object sender, EventArgs e);
      2. public delegate void EventHandler (object sender, TEventArgs e);
    2. 其中EventHandler用于不包含事件数据的事件,EventHandler用于包含事件信息的事件。如果没有事件数据,可将第二个参数设置为EventArgs.Empty,否则第二个参数类型需要从EventArgs类继承。

24. Lamda表达式

  1. 语法:

    1. (参数列表)=>表达式/{语句块};
    2. Lambda表达式或者语句块是没有return。
  2. Func委托和Action委托使用Lambda表达式:

    1. Func委托和Action委托都属于官方提供的泛型委托,一般直接拿来用就可以,不需要自己定义新的委托。
    2. Func委托是带返回参数的委托,Action委托则是void委托。
//正常委托实例化应该是这样的:
Func<int,int> MyFunc1 = new Func<int,int>(Class.Function);
//使用Lambda实例化:
Func<int,int> MyFunc2 = n => n*3;
//使用匿名委托:
Func<int,int> MyFunc3 = delegate(){return Class.Function};
//所以lambda表达式YES!

ntArgs e);
2. 其中EventHandler用于不包含事件数据的事件,EventHandler用于包含事件信息的事件。如果没有事件数据,可将第二个参数设置为EventArgs.Empty,否则第二个参数类型需要从EventArgs类继承。

24. Lamda表达式

  1. 语法:

    1. (参数列表)=>表达式/{语句块};
  2. Func委托和Action委托使用Lambda表达式:

    1. Func委托和Action委托都属于官方提供的泛型委托,一般直接拿来用就可以,不需要自己定义新的委托。
    2. Func委托是带返回参数的委托,Action委托则是void委托。
//正常委托实例化应该是这样的:
Func<int,int> MyFunc1 = new Func<int,int>(Class.Function);
//使用Lambda实例化:
Func<int,int> MyFunc2 = n => n*3;
//使用匿名委托:
Func<int,int> MyFunc3 = delegate(){return Class.Function};
//所以lambda表达式YES!
Unity插件 Unitask学习日志 阅读详情

相关推荐

C#游戏开发中的注意事项

主要内容包括: 性能优化:避免不必要的循环、减少字符串拼接、利用Unity生命周期函数、使用对象池。 内存管理:及时释放非托管资源、避免空引用异常、合理使用引用与值类型、防止内存泄漏。 异常处理:避免过度使用异常、采用防御性编程、记录和调试异常。 线程同步:使用线程同步机制、避免死锁、采用异步编程模式。 代码设计:遵循面向对象原则、避免重复代码、使用设计模式。 资源管理:合理加载资源、避免内存泄漏、使用资源池技术。 安全性:验证用户输入、加密敏感数据、防止调试与逆向工程。

2401_82505179的博客 1305

Unity C# 编程时注意事项

不要随便改代码 编程时,如果程序运转正常,就不要随便改代码。即使这个代码看起来没有什么关联,也没有用了,也不要随便删除。因为代码与代码之间有非常复杂的关系,你一删除,可能这个关系链条就断了,就影响其他代码。 所以,你要研究非常清楚,再改动代码,改动你非常清楚的代码。 而且,一次只改一小点代码,然后测试,没问题,再改一点,再测试。这如果发现问题,好知道哪里改错了。如果你一次性改很多代码,一旦出错,你都不知道哪里错了,而且,都不知道改过哪些代码了。 ...

m0_51962250的博客 924

Unity游戏开发学习路径规划:从入门到精通的实战指南

游戏开发是一个融合编程、设计、美术等多领域的综合性技术领域,其核心在于通过引擎工具将创意转化为可交互的数字体验。Unity作为业界主流的跨平台游戏引擎,其工作原理基于组件化架构和实时渲染管线,开发者通过C#脚本驱动游戏对象的行为逻辑。掌握Unity开发不仅能提升个人技术栈的广度与深度,更能为独立游戏创作、虚拟现实应用、工业仿真等场景提供强大支持。对于初学者而言,如何高效学习Unity并构建完整的知识体系是关键挑战。本文围绕Unity开发者的核心需求,系统梳理了从引擎入门、C#基础到高级优化、网络同步等全阶段

weixin_33816821的博客 353

曲线救国,使枚举enum支持字符串string

枚举是不支持string的,有的时候我们需要为枚举成员指定相应的说明性文字,如我引用SimpleEnum.Today的时候,需要在我的主界面上打印“今天”,而不是“Today”。这样就使我们在编码的时候要不停的编写switch来表示枚举变量的注释。那么,有没有更好的办法来维护我们的枚举成员呢。本文将提供一种解决方法。 例如,有如下枚举变量:public enum SimpleEnum

9338

【Unity3D游戏魔坦之争】抽象父类继承实现【三】

【unity之IMGUI实践】抽象父类继承实现【三】——抽象父类的抽象方法适用于必须重写的情况如开火行为,每个坦克的开火行为不同,而选择性重写的虚方法则的情况可适用于受伤行为,受伤行为大同小异,可选择性重写

秩沅 1516

【从零开始入门unity游戏开发之——C#篇38】C#预处理器指令

C#预处理器指令

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 1949

关于Unity的脚本使用和注意事项

学习和分享:Unity拥有庞大的社区和资源库,你可以通过学习和分享来提高自己的技能。利用Unity的事件系统:Unity提供了一个强大的事件系统,你可以使用它来处理游戏对象的交互和行为。这样可以更加方便地管理游戏逻辑。使用注释和文档:为了方便自己和他人理解代码,你应该在关键部分添加注释,解释代码的作用和使用方式。编写可复用和易于理解的代码:为了提高代码的可维护性和可复用性,你应该尽量遵循一些基本的编码规范和最佳实践。例如,使用有意义的变量和函数命名、拆分复杂的功能模块为小的、易于理解的子函数等。

lxl2092828212的博客 732

Ubuntu 22.04 搭建 PX4 飞控系统完全指南:从仿真到硬件试飞

定义消息文件protobufuint64 timestamp # 时间戳float32 temperature # 温度float32 humidity # 湿度生成代码:bashPX4 在 Ubuntu 22.04 的搭建涉及环境配置、编译仿真、硬件连接等多环节,核心是理解 PX4 1.14 的新特性(uXRCE-DDS、动态控制分配)。通过本文指南,开发者可快速构建稳定的 PX4 开发环境,为无人机应用开发奠定基础。

zqmgx13291的博客 3041

Unity学习日志_Unity脚本

Unity学习日志_Unity脚本 1. unity脚本基础介绍 1. unity脚本中需要注意的事项: 一个脚本一个功能。 脚本是附加在游戏对象上用于定义游戏对象行为的指令代码。 文件名必须与类名一致。 写好的脚本必须附加到物体上才可以执行。 附加到游戏对象上的脚本必须继承MonoBehaviour类(单纯的工具类不需要继承此类)。 unity脚本本质是一个c#类。 将unity脚本绑定到游戏对象(也是对象,GameObject类)上本质是创建了一个对象,并将对象的引用存储在游戏对象的“组件管理数组”中

BraveRunTo的博客 1711

ArcGIS基础:CAD数据转换为GIS数据(符号化显示、数据转换、线转面、空间连接)

1、符号化显示: CAD数据加载进来有很多列表,包含了点【point】、线【polyline】、面【polygon】、标注数据【Annotation】等数据,本次实验我们需要用到的是面数据,也就是.dwgPolygong格式的数据。如下图所示: 把数据加载进来,然后在2处打开属性表,查看CAD数据的属性表,打开后可以发现【layer】图层表示就是地块的用地性质,它就是符号化显示的依据。 我们在数据上右键【属性】,打开图层属性,找到【符号系统】,选择类别中的【唯一值】,然后在【值字段】下拉选择【layer】,

yuanYW7556的博客 2万+

AxMath行间公式转化为office公式求和符号以及编号显示问题

AxMath行间公式转化为office公式求和符号以及编号显示问题问题描述解决方法 问题描述 首先打出axmath公式,如下: 转换后的OfficeMath公式: 字体先不说,word公式字体默认cambria math且无法编辑。比较难受的一点是求和符号与后面的 ai+bi2a_i+b_i^2ai​+bi2​比例不匹配啊!正常的比例应该是: (虽然也不太正常,将就下) 解决方法 点击变换后的office公式右侧,选择更改为"显示" 可以看到,多了一些软回车符号(⬇),如果你想删除它,不要直接选中

weixin_43543177的博客 4653

Unity 学习日志—C# 基础(2)

~如果感兴趣可以去支持一下b站一唐老狮一

Nan_Gua_pie的博客 832

QT5.14.2离线安装包保姆级教程:断网、选组件、避坑全记录

本文详细介绍了QT5.14.2离线安装包的完整流程,特别针对Windows平台开发者提供断网安装、组件选择及避坑指南。作为QT5系列中最后一个免费离线版本,5.14.2具有免注册、全组件离线安装等独特优势,是开源开发者的理想选择。文章涵盖从环境准备到安装后配置的全方位指导,帮助开发者高效完成安装并避免常见问题。

weixin_30924087的博客 578

Unity游戏制作中的C#基础(1)界面操作基础

Unity游戏制作中的C#基础(1)

徽程22级的在读学生 711

【技能】OpenClaw Skills学习及手搓一个极简skill

本文介绍了OpenClaw Skills的基础概念与使用方法。Skills是OpenClaw代理使用工具的核心载体,通过SKILL.md文件定义技能属性和执行方式。技能加载遵循"工作区>本地>内置>自定义目录"的优先级规则。用户可通过ClawHub一键安装现成技能,也可自定义开发技能:创建技能目录,编写包含YAML元数据和执行指令的SKILL.md文件,放置于工作区skills目录进行测试。文章还介绍了多代理场景下的技能共享、插件集成以及安全注意事项,包括沙箱使用和敏感

海兰 3976

OpenCloudOS9操作系统搭建Confluence8.2.1+Jira企业级WIKI

Atlassian Confluence是一个专业的企业知识管理与协同软件,可用于构建企业wiki

背锅神童的博客 1023

unity 查看日志

在Unity中,查看日志是一个重要的调试和追踪问题的手段。Unity提供了几种不同的方式来查看和过滤日志。

lcfengokok的博客 3060

Spring AI Alibaba实战训练营-14基于A2A协议智能体应用开发指南

本文介绍了基于A2A协议的智能体应用开发流程,主要包括客户端和服务端两个模块的实现。关键技术包括A2A通信协议、Nacos服务发现、Spring AI Alibaba框架和DashScope通义千问API。开发步骤涵盖环境准备(JDK17、Maven、Nacos)、项目创建、依赖配置(重点引入spring-ai-alibaba相关组件)以及Nacos和DashScope的核心配置。整个系统架构采用客户端通过Nacos发现服务端Agent,再调用阿里云AI服务的模式,实现了AI能力的解耦与复用。

program哲学 506

unity一键注释日志和反注释日志

1.先检测代码中是否存在不规范代码,类似if(a > 1) Debug.Log("11") 这种代码如果注释掉日志会引起业务逻辑问题需要先找出来,类似的不限于if else for foreach while这些 所以尽可能的要做这个检测,有这类问题直接报错。2.注释Debug.Log或者UnityEngine.Debug.Log,但是有一个问题就是注释之后再注释的问题,所以在调用这个接口前需要调用反注释然后调用注释,这样就可以保证注释是没有问题的。Log($"请使用括号封装你的日志!

yangjie6898862的专栏 1395

C#函数返回多个值实现实例

本文实例讲解C#函数返回多个值多种实现方法。

qq_30725967的博客 1170

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

unity常见面试题

接口是一种完全抽象的类型,它只定义了成员的签名,但没有提供成员的实现。接口定义了对象应该具有的方法、属性和事件。抽象类是一种包含了抽象成员(方法、属性、索引器、事件)的类,它可以包含抽象成员和非抽象成员的实现。抽象类可以包含方法的实现,也可以包含字段和构造函数等。

yasin的博客 1万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

unity的学习

因为需要构建一个三维物理环境,所以学习了unity,半天就可以,非常简单清晰。

wangduqiang747的博客 1248

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Unity面试全攻略:从C#基础到性能优化的核心考点解析

在游戏开发和实时3D应用领域,Unity引擎因其强大的跨平台能力和丰富的生态系统,成为众多开发者的首选工具。其核心原理建立在C#语言与.NET运行时之上,通过组件化架构和高效的渲染管线,实现了复杂的交互逻辑与视觉呈现。掌握Unity不仅意味着能够实现功能,更代表着具备解决性能瓶颈、设计可维护架构的工程实践能力,这对于构建流畅的元宇宙体验、工业仿真及高质量游戏至关重要。本文聚焦Unity客户端开发中的高频面试考点,深入剖析C#内存管理、Unity生命周期、资源系统(如Addressables)以及性能优化策略

weixin_34115824的博客 330

Unity改变打印调试日志文字颜色

颜色参考原文链接:https://blog.youkuaiyun.com/weixin_42565127/article/details/126231480。Debug.Log("<color=#00FFFF>Alt+F4 被拦截!// print("<color=yellow>Alt+F4 被拦截!10 巧克力色 #5C3317。24 深铜绿色 #4A766E。25 深橄榄绿 #4F4F2F。28 深石板蓝 #6B238E。32 深绿松石色#7093DB。

AgilityBaby的博客 1127

Unity与华为快游戏JS桥接实战:实现高效日志输出与跨平台通信

在跨平台游戏开发中,JavaScript桥接技术是实现不同运行环境间通信的核心机制。其原理是通过建立C#与JavaScript之间的互操作层,解决如Unity引擎与轻量级Web容器间的数据交换问题。这项技术的价值在于能够打通原生平台能力,实现性能监控、调试信息收集等关键功能。在应用场景上,尤其适用于需要适配华为快游戏等平台的Unity WebGL项目,其中日志系统的桥接是保障应用稳定性和可维护性的基础实践。通过封装简洁的C#接口并利用WebGL Interop机制,开发者可以高效地将游戏内的调试信息输出到平

weixin_34167819的博客 434

Unity C#命名规范全解析:从基础规则到团队协作实践

在软件开发中,命名规范是代码可读性与可维护性的基石,直接影响团队协作效率与项目长期健康。其核心原理在于通过统一的命名规则(如帕斯卡命名法与骆驼命名法)建立清晰的代码语义层,使开发者能快速理解变量、函数与类的职责。从技术价值看,规范的命名不仅是编码风格问题,更是降低认知负荷、减少沟通成本、提升代码质量的关键工程实践。在Unity游戏开发等复杂应用场景中,命名规范尤为重要,它贯穿于脚本编写、资产管理、项目架构等各个环节。本文聚焦Unity C#开发,深入探讨如何将基础命名原则与Unity引擎特性相结合,系统解决

weixin_34175509的博客 433
下一篇: Unity学习日志_Unity脚本
BraveRunTo
博客等级 码龄7年 91粉丝 75原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值