tips of c#
2018-09-21 本文已影响0人
魍瞳
基础类型的大小是固定,因为会被映射成内部类型
char //System.Char 16bit unicode
byte //System.Int8
short //System.Int16
int //System.Int32
long //System.Int64
可空值类型, 可空值类型不能赋值给普通的值类型
int? i = 0;
ref 参数 用来传引用,传进去的值必须先初始化。
out 参数 用来传出值,但是不需要初始化,但是函数内部要对它赋值。
ref或者out一个引用类型,就类似于指针的指针
struct 和 enum 都是值类型,派生自System.ValueType,值类型都是密封的,即不能被继承
值类型都在分配在栈上面,比较小(小于 16 byte)或者不作为函数参数来传递的类型适合声明成值类型
//System.Object == object
object test;
object 可以用int来赋值
会自动转化成引用类型,也就是把在堆上面申请新的内存并把原来在栈上面的值复制过去
这就是所谓的装箱, 但是拆箱需要强制转型
int i = 10;
object obj = i;
int j = (int)obj;
装箱对于复杂的值类型是有坑的,例如
public struct Test {
public int a;
public void ChangeX(int to) {
x = to;
}
}
Test t = new Test();
object obj = t;
((Test)obj).ChangeX(10); // 这样obj是不会被改变的,拆箱出来的是一个临时栈变量(一个右值)
所以struct的每个变量最好是readonly的 这样struct就会被作为一个整体来看待
这也是为啥unity里面position的xyz不能单独修改的原因,position属性返回了一个新的Vector3值类型
if (i is Point) // is 判断是不是一种类型
i as Point //as 类似dynamic_cast 如果不是返回null
enum Number : short { One, Two, Three } //第一个值默认是0 然后递增,默认类型是int
struct:
- 不能自己写默认构造函数,系统总会生成一个
- 不可以定义的时候初始化
- new 出来的会调用构造函数,自己写的构造函数必须把每个成员变量都初始化,这样每个成员变量都是初始化过的
class:
- 会自己初始化成员变量,这个初始化是个语法糖,实际会发生在class的构造函数里面,并且在父类的构造函数之前
- 可以在定义的时候初始化
可以这样显示的指定复写的是哪个接口的函数,然后通过不同类型的ref来调用不同的实现 但是感觉不是很常用的方法
interface IMachine{
void hello();
}
interface IMan{
void hello();
}
class Robot : IMachine, IMan{
void IMachine.hello(){}
void IMan.hello(){}
}
abstract class Car {} //抽象类,不能实例化
sealed class Car {} //密封类 不能被继承
public int X {
get { return this._x; }
set { this._x = value; }
}
//interface属性
interface IMachine{
int Name { get; set; }
}
//自动创建 自动生成 this._height
class Robot{
public int Height { get; set; }
}
delegate 提供了类似函数指针的功能
delegate本身是个类,里面包含了target,method_ptr和用来处理委托链的结构
使用的时候需要new一个然后把函数指针传进去
event这个关键字只用于限制delegate的invoke范围,即只能类内调用