1.结构体:
在 C# 中,结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。例如我定义了一个结构体,它有两个变量,创建一个这个类型的结构体,通过一个变量名调用多个变量,这些变量可以在结构体中赋值,也可以在结构体外进行更改。
public struct Test
{
public string name;
public string age;
}
public Test People;
public void GetTest()
{
People.age = "2";
People.name = "name";
}
结构体不能在声明时赋值
结构体是值类型,无需进行堆分配,类是引用类型
结构类型的变量直接存储数据结构,而类类型的变量存储对动态分配的对象的引用
类支持继承,结构体不支持继承
关键字简单说下,类是Class,结构体是Struct
2.构造函数
在实例化对象时会调用的用于初始化的函数
1.如果不写默认存在一个无参构造函数
2.没有返回值
3.函数名和类名必须相同
4.没有特殊需求时一般都是public的
5.构造函数可以被重载
6.this代表当前调用该函数的对象自己
注意!!
如果不自己实现无参构造函数而实现了有参构造函数
会失去默认的无参构造
其中有一种特殊写法:
class Person
{
public string name;
public int age;
public Person()
{
name = "name";
age = 1;
}
/// <summary>
/// 特殊写法,:this()表示先执行this()构造方法,然后再执行:this()前面的构造方法
/// </summary>
public Person(string name, int age) : this(name)
{
this.name = name;
this.age = age;
}
public Person(string name)
{
this.name = name;
}
}
3.垃圾回收机制
垃圾回收,英文简写GC(Garbage Collector)
垃圾回收的过程是在遍历堆(Heap)上动态分配的所有对象
通过识别它们是否被引用来确定哪些对象是垃圾,哪些对象仍要被使用
所谓的垃圾就是没有被任何变量,对象引用的内容
垃圾回收有很多种算法,比如
//引用计数(Reference Counting)
//标记清除(Mark Sweep)
//标记整理(Mark Compact)
//复制集合(Copy Collection)
注意!!:
GC只负责堆(Heap)内存的垃圾回收
引用类型都是存在堆(Heap)中的,所以它的分配和释放都通过垃圾回收机制来管理
栈(Stack)上的内存是由系统自动管理的
值类型在栈(Stack)中分配内存的,他们有自己的申明周期,不用对他们进行管理,会自动分配和释放
内存回收原理:
0代内存 1代内存 2代内存
代是垃圾回收机制使用的一种算法(分代算法)新分配的对象都会被配置在第e代内存中
每次分配都可能会进行垃圾回收以释放内存(e代内存满时)
在一次内存回收过程开始时,垃圾回收器会认为堆中全是垃圾,会进行以下两步:
1.标记对象从根(静态字段、方法参数)开始检查引用对象,标记后为可达对象,未标记为不可达对象,不可达对象就认为是垃圾
2.搬迁对象压缩堆(挂起执行托管代码线程)释放未标记的对象搬迁可达对象修改引用地址
大对象总被认为是第二代内存目的是减少性能损耗,提高性能,不会对大对象进行搬迁压缩85000字节(83kb)以上的对象为大对象
0代内存满了时候,会对0代内存进行垃圾回收,释放掉不可达对象,将可达对象迁移到1代内存压缩堆,1代内存满了时,对0代、1代内存都进行垃圾回收,迁移1代内存到2代内存,2代也是类似如此。
4.成员属性:
1.用于保护成员变量
2.为成员属性的获取和赋值添加逻辑处理
3.解决3P的局限性
public—内外访问
private—内部访问
protected一内部和子类访问
属性可以让成员变量在外部:
只能获取 不能修改 或者 只能修改 不能获取
class Person
{
private string name;
private int age;
private int id;
/// <summary>
/// 属性命名 帕斯卡命名 开头大写
/// </summary>
public string Name
{
get
{
//将属性值传递出去
return name;
}
set
{
//value 关键字,外部传入的值
name = value;
}
}
}
/// <summary>
/// 成员属性的使用
/// </summary>
class GetName
{
Person p = new Person();
void Start()
{
//set{}
p.Name = "name";
//get{}
Debug.Log(p.Name);
}
}
成员属性可以用来进行加密处理,例如:
public int Age
{
get
{
//解密处理
return age - 5;
}
set
{
//加密处理
age = value + 5;
}
}
同时也可以用来防止数据错误:
public int Age
{
get
{
//解密处理
return age - 5;
}
set
{
if(age < 0 )
{
age = 0;
Debug.Log("年龄不能小于0岁,已改为0岁");
}
//加密处理
age = value + 5;
}
}
注意!!成员属性set、get可以加访问修饰符
1.默认不加会使用属性申明时的访问权限
2.加的访问修饰符要低于属性的访问权限
3.不能让get和set的访问权限都低于属性的权限
public int Age
{
//添加了private以后,get属性在外部就不能被得到了
//但是不能set 和 get 都加private
private get
{
return age;
}
set
{
age = value;
}
}
set、get可以只有一个
如果类中有一个特征是只希望外部能得不能改的又没什么特殊处理
那么可以直接使用自动属性
public int Hight
{
get;
private set;
}
5.索引器:
让对象可以像数组一样通过索引访问其中元素,使程序看起来更直观,更容易
class Person
{
private string name;
private int age;
private Person[] ids;
/// <summary>
/// 索引器定义
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public Person this[int index]
{
get
{
return ids[index];
}
set
{
ids[index] = value;
}
}
}
class GetPeson
{
void Start ()
{
Person p = new Person();
//像获取数组一样获取值
p[0]=new Person();
Debug.Log(p[0]);
}
}
索引器可以写一些逻辑:
get
{
//索引器中可以写逻辑
//如果ids数组为空或者索引大于数组长度,直接返回空
if (ids == null|| ids.Length - 1 < index)
{
return null;
}
return ids[index];
}
set
{
//ids数组为空,为数组新建一个元素
if (ids == null)
{
ids = new Person[] {value};
}
//传进来的值索引大于ids数组长度,(把值赋给最后一个元素,自定义的规则)
else if(index>ids.Length-1)
{
ids[ids.Length-1] = value;
}
ids[index] = value;
}
索引器重载(同时可以根据传入参数返回对应值):
private string name;
private int age;
private Person[] ids;
public Person this[int index]
{
get
{
return ids[index];
}
set
{
ids[index] = value;
}
}
/// <summary>
/// 索引器重载
/// </summary>
public string this[string str]
{
get
{
switch (str)
{
case "name":
return name;
case "age":
return age.ToString();
}
return "";
}
}