Unity学习笔记(六)

好的数据结构

C#中定义了栈、队列和HashSet。栈和队列我们已经很熟悉了,一个遵循后进先出(LIFO)模型,一个遵循先进先出(FIFO)模型。原理就不再赘述了,接下来介绍一下见得较少的数据类型。

HashSet

这种结构不能储存重复值,并且没有顺序,这意味着它的元素不以任何方式排序。它们可以极快地执行集合运算和元素查找。
变量声明:

HashSet<elementType> name = new HashSet<elementType>(); 

集合运算作用于调用的集合对象和传入的集合对象。一系列的api都是类似于数学中的集合运算。

探讨委托、泛型等

到目前为之,我们定义和使用的类型都非常具体。但是在某些情况下,我们需要类或者方法以相同的方式处理其实体,不管是什么类型,都要求类型是安全的。泛型编程允许我们使用占位符而不是具体类型来创建可重复使用的类、方法和变量。
创建泛型类实例或使用泛型方法时,会分配一个具体类型,但代码本身会将其视为泛型类型。这些泛型类型需要能够对元素执行相同的操作,而不考虑类型。之前在列表类型中就可以发现,列表类型本身就是一个泛型类型。无论它是储存整数、字符串还是单个字符,我们都可以访问它的所有添加、删除和修改方法。

泛型对象

创建泛型类和非泛型类的方式相同,但有一个重要区别:泛型类使用的是泛型类型的参数。下面讲解一个泛型集合类的示例。

public class SomeGeneriCollection<T> {}

上面声明了一个名为SomeGenericCollextion的泛型集合类,并指定T作为参数类型命名。现在,T将代表泛型列表中将储存的元素类型,并可以像其他类型一样在泛型类中使用。
每当创建SomeGenericCollection的实例时,都需要指定要存储的值的类型:

SomeGeneriCollection<int> highScores = new SomeGeneriCollection<int>();
对泛型类型参数的命名完全自由,但许多编程语言默认使用大写的T。
如果要以不同方式命名参数类型,请考虑以大写T开头,以保持一致性和可读性。

泛型方法

单独的泛型方法也需要有一个参数类型占位符,就像泛型类一样,以允许根据需要将占位符包含在泛型或非泛型类中:

public void GenericMethod<T> (T genericParameter) {}

但是如果要在泛型类中声明泛型方法,则不必指定新的T类型:

public class SomeGeneriCollection<T> 
{
	public void NonGenericMethod(T genericParameter) {}
}

约束类型参数

泛型的一大优点就是可以限制其参数类型。这似乎与迄今为止学到的有关泛型的知识相悖,但仅因为一个类可以包含任意类型,并不意味着就应该这样做。
为了约束泛型的参数类型,则需要一个新的关键字和一个以前从未见过的语法:

public class SomeGeneriCollection<T> where T:ConstraintType {}

where关键字定义了T在用作泛型参数类型之前必须满足的规则和约束。从本质上说,只要符合约束类型,SomeGenericCollection就可以接受任何T类型。约束规则并不神秘可怕,在先前已经讨论过有关它们的概念:

  • 添加class关键字,会将T限制为类的类型。

  • 添加struct关键字,会将T限制为结构体的类型。

  • 添加一个接口,例如IManager,会将T限制为采用该接口的类型。

  • 添加自定义类会将T限制为该类类型。

      如果需要更灵活的方法说明具有子类的类,可以使用where T:U,指定泛型T类型必须属于或继承U类型。
    

委托行为

有时需要传递方法或委托方法的实际执行。在C#中,这可以使用委托类型来实现。委托类型储存对方法的引用,并且可像其他变量一样使用。需要注意的是,委托本身和被分配的方法都需要相同的签名。

我的理解就是将方法名当作变量,利用这个变量来调用方法。

创建委托的语法混合了编写方法和声明变量:

public delegate returnType DelegateName(int param1,string param2);

从访问修饰符开始,后跟delegate关键字,这样的声明可以使编译器将他识别为委托类型。委托类型可以像常规方法那样具有返回类型和名称,已经可能需要用到的参数。但是,此语法仅声明委托类型本身。若要使用委托,需要像使用类一样创建一个实例:

public DelegateName someDelegate;

声明委托变量后,便很容易分配一个与委托签名相匹配的方法:

public DelegateName someDelegate = MatchingMethod;

public void MatchingMethod(int param1,string param2)
{
	//...Executing code here
}

将MatchingMethod()方法分配给someDelegate变量时,不需要在方法名后面加括号,因此不会调用该方法,只是将调用权委托给了someDelegate。这意味着可以用如下方式调用函数:

someDelegate();

同样,委托本身也可以用作方法参数,与前面介绍内容区别不大。

触发事件

C#事件允许基于游戏或应用程序的行为创建订阅系统。任何类都可以通过触发事件的调用类来订阅或取消订阅某个事件。
声明事件与声明委托类似,因为事件都具有特定的方法签名。可以使用委托来指定事件的方法签名,然后使用delegate类型和event关键字创建事件:

public delegate void EventDelegate(int param1,string param2);
public event EventDelegate eventInstance;

订阅者很容易添加,与委托类型分配方法引用非常相似:

someClass.eventInstance += EventHandler;

由于事件是属于声明它们的类的变量,而订阅者是其他类,因此订阅者需要引用包含事件的类。+=运算符用于分配方法,该方法将在事件执行时触发,就像设置自动回复消息一样。与分配委托一样,事件处理方法的方法签名必须与事件类型相匹配。在需要取消订阅事件时,只需要用-=运算符执行相反的操作。

一般在类被初始化或销毁的时候处理事件订阅,从而轻松地实现和管理多个事件,并避免代码变得杂乱。

抛出异常

当谈论添加错误时,通常将这个过程形象地称为抛出异常。它本质上意味着主动并由意识地防止代码中的不当操作或计划外操作。
使用throw关键字抛出异常,该异常是使用new关键字创建的,后跟指定的异常。C#有很多内置的异常类型,不在这里深入讨论了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值