委托:比较什么时候用委托好
下课案例:不用下课铃
1、ClassManager需要拿到所有教室的引用,课堂管理者应该只负责计时并告知每间教室
2、每间教室应该是由当班老师负责是否需要下课,而课堂管理者应该负责告知时间到,并不应该强制执行下课方法
3、每间教室的类可能不是同一个程序员写的,下课方法也不一定一样,比如有100间教室,每间教室下课方法都不一样
使用下课铃(广播)的好处:
1、ClassManager并不需要知道每间教室的地址
2、只负责告知每间教室时间到了,并没有强制要求下课,具体下不下课,是由ClassManager类里面的方法决定的
3、谁想要接收下课的广播就接收,发送者并不需要知道谁在接收,接收到之后具体要干什么,自己说了算
public delegate 返回值类型 类型名 (参数列表)
public 类型名 委托变量名;//相当于一个函数的大容器
发送广播的方式:
委托变量名();//函数指针
监听广播的方式:
委托变量名 += 我收到广播之后的行为
单例:
二十三种设计模式中的一种
整个游戏进程中或者过程中,只有一个实例化出来的类对象,这种设计模式叫单一实例化或单例。
实例化:把类变成实体对象
只需要实例化一次,也只有一个类对象:玩家1个,玩家管理器1个,
静态类,外部可以直接使用类名来使用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerManager : MonoBehaviour {
//PlayerManager只有一个实例化
private static PlayerManager _instance;//用private把-instance隐藏掉
public static PlayerManager GetIntance//声明一个GetIntance属性,保护-instance,只有get
{
get
{
if (_instance == null)
{
_instance = new PlayerManager();//GetIntance 保证每次使用,都是第一次new出来的对象-instance
}
return _instance;
}
}
private PlayerManager()//隐藏构造函数,防止使用new PlayerManager,只能使用GetIntance
{
}
}
但是多线程,存在安全问题,会同时执行GetIntance,生成两个-instance,需要线程锁
单例第二种写法
下次访问类名.对象,直接把自己拿过去
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RedisTest.Test
{
[Serializable]
public class TestClass
{
public string Name = "";
public TestClass(string n)
{
Name = n;
}
public override bool Equals(object obj)
{
TestClass other = obj as TestClass;
if (other == null)
return false;
if (!base.GetType().Equals(obj.GetType()))
return false;
return (this.Name.Equals(other.Name));
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
public static explicit operator TestClass(string jsonString)
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<TestClass>(jsonString);
}
public override string ToString()
{
return Newtonsoft.Json.JsonConvert.SerializeObject(this);
}
}
}
教室1
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ClassRoom_1 : MonoBehaviour {
//public ClassManager manager;
// Use this for initialization
void Start () {
//manager.classOver += ClassOver;
//ClassManager._instance.classOver += ClassOver;
}
// Update is called once per frame
void Update () { }
public void ClassOver()
{
Debug.Log("教室1下课了");
//manager.classOver += ClassOver;
//ClassManager._instance.classOver -= ClassOver;
}
}
教室2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ClassRoom_2 : MonoBehaviour {
// Use this for initialization
void Start () { } // Update is called once per frame
void Update () { }
public void ClassOver()
{
Debug.Log("教室2下课了");
}
}
考试复习
C#基础:
、下列有关基本类的大小不正确的是 D
A、int类型是4个字节
B、bool类型是1个字节
C、long类型是8个字节
D、char类型是一个字节 //char类型占两个字节 、关于定义数组定义不正确的是 C
A、int[] numbers={,,,,,};
B、int[] numbers=new int[];
C、int[][] numbers=new int[][];//定义二维数组的正确方法:int[,] a =new int [3,5];
D、var a=new[]{,,,,,}; 、有关数组说法不正确的是 A
A、数组的内存是分配在栈中//堆
B、数组的索引从零开始的
C、数组是一种数据结构,它包含若干相同的类型的变量
D、数组可以是一维、多维、交错的 、有关结构体说法不正确的是 D
A、在结构体声明中,除非字段被声明为const或static,否则无法初始化
B、结构体不能声明默认的构造函数(没有参数的构造函数)或析构函数
C、结构体不能从类或其他结构体继承
D、结构体是引用类型的//结构体是值类型,类是引用类型 、有关结构体和类的说法不正确的是 B
A、结构是值类型的,而类是引用类型的
B、结构体不可以声明构造函数//不能声明无参构造,可以声明有参构造
C、结构体直接继承System.ValueType类型
D、结构体可以继承接口//结构体不能继承类,可以继承接口 、关于静态类说法不正确的是 C
A、声明静态类,该类不能使用new关键字创建实例
B、静态仅包含静态成员//const常量
C、静态类不能包含常量成员
D、静态类是密封的//不能被继承,隐含密封 、有关委托的说法不正确的是 C
A、一旦为委托分配了方法,委托与该方法具有完全相同的行为
B、委托是一种引用方法的类型
C、委托可以链接在一起,方法不必与委托签名完全匹配//必须和委托签名匹配 、delegate void Del(int x); C
void DoWork(int k);
下列关于委托订阅不正确的是
A、Del d=DoWork;
B、Del d=new Del(DoWork);
C、Del d+=DoWork//还未创建,不可订阅
D、Del d=delegate(int x){DoWork(x);}; //看匿名委托和委托的签名是否一致 、有关静态构造函数说法不正确的是 C
A、静态构造函数既没有访问修饰符,也没有参数
B、在创建第一个实例前或引用任何静态成员之前,将自动调用静态构造函数来初始化。//初始化静态成员
C、在程序中,用户可以控制何时执行静态构造函数//间接执行:调用静态成员,实例化对象
D、无法直接调用静态构造函数 、有关继承需要用的关键字说法正确的是 ACD
A、virtual用于修饰方法、属性、索引器或事件,并使它们可以在派生类中被重写。
B、virtual可以和static、abstract、private、override修饰符一起使用。//都不可以
C、override关键字提供从基类继承的成员的新的实现,重写的基类方法必须是virtual、abstract、或override关键字修饰的。
D、Sealed用于修饰类时,将会阻止其他类从该类派生//修饰方法,禁止被重写 、以下c#代码:
using System.Threading;
class App
{
public static void Main()
{
Timer timer = new Timer(new TimerCallback(CheckStatus), null, , );
Console.Read();
}
static void CheckSatus(Object state)
{
Console.WriteLine("正在进行检查...");
}
}
在使用代码创建定时器对象的时候,同时指定了定时器的事件,运行时将每隔两秒打印一行“正在运行检查...”,因此,TimerCallback是一个( ) A
A.委托//目前只有委托可以把方法当做参数传递
B.结构
C.函数
D.类名 、 阅读以下的C#代码:
public class TEApp
{
public static void ThrowException()
{
throw new Exception();
}
public static void Main()
{
try
{
Console.WriteLine("try");
ThrowException();
}
catch (Exception e)
{
Console.WriteLine("catch");
}
finally
{
Console.WriteLine("finally");
}
}
}
请问代码运行结果是( )。(选择一项) A
A.try catch finally
B.try
C.try catch
D.try finally
抛异常的用法:
try:包含异常的语句
try不能单独使用,要搭配catch和finally使用
catch:捕获异常,可以填参数
catch(Exception e){},(Exception是所有异常的基类)
finally:最后都会执行,作为替补收尾工作,
无论如何都会执行,即使前面有return
结果:输出“捕获到了异常”,而“”不会输出 、在C#中,一个类( ).(选择一项) B
A.可以继承多个类//类的单根性,只能有一个父类
B.可以实现多个接口
C.在一个程序中只能有一个子类
D.只能实现一个接口 、程序运行过程中发生的错误,叫作( ).(选择一项) C
A.版本
B.断点
C.异常
D.属性 、针对下面的C#代码:
using System;
delegate void D(int i);
class P
{
public static void Main()
{
V(new D(R));
}
public static void R(int t)
{
V();
}
public static void V(int i)
{
Console.WriteLine(i.ToString());
Console.ReadLine();
}
}
以下说法正确的是( )(选择一项) B
A.代码中存在错误,delegate voidD(int i);不能定义在名称空间或者类之外//可以定义在类之外
B.代码中存在错误,代码行V(new D(R));使用委托错误//V方法需要整形参数,却传了委托
C.程序正常运行,输出为0
D.程序正常运行,输出为21 、被volatile关键字修饰字段的作用是( ) B
A、提供给子类使用,不提供给其他类使用
B、禁止对字段的访问施加优化
C、表示只读字段,只能赋值一次
D、只能在本程序集中使用
变量修饰符,在多线程中使用,对于值类型的变量,禁止多次拷贝,只能有一份,避免数据不同步(禁止将变量的值存在cache缓存里,只能从内存里拿) 、在C#中,可以通过装箱和拆箱实现值类型与引用类型之间相互转换,在下列代码中,有( )处实现了拆箱。(选择一项) B
装箱:把值类型的数据放到引用类型的变量里
拆箱:把引用类型的数据放到值类型的变量里(强转)
装箱和拆箱的条件:需要有继承关系
string a = “”; //不是装箱,String和int没有继承关系
object o = string; //不是装箱,String是引用类型
int age = ;
object o= age; //装箱:子类对象存放在父类里,里氏转换
o=; //装箱
age=(int)o; //拆箱
object oAge =age; //装箱
A.
B.
C.
D. 、在C#中,接口与抽象基类的区别在于( )。(选择一项) A
A.抽象基类可以包含非抽象方法,而接口只能包含抽象方法//抽象类什么都可以放,接口:属性(get和set方法),方法,索引器(属性),事件(委托-方法),本质都是方法
B.抽象基类可以被实例化,而接口不能被实例化
C.抽象基类不能被实例化,而接口可以被实例化//抽象类不可以被实例化,而接口不能被实例化
D.抽象基类能够被继承,而接口不能被继承//接口可以继承 、下列关于 C# 中索引器理解正确的是 ( ) C
A、索引器的参数必须是两个或两个以上 //个数任意,但不能无
B、索引器的参数类型必须是整数型 //字符串,枚举
C、索引器没有名字 //this[ in index]
D、以上皆非 、以下关于 ref 和 out 的描述哪些项是正确的? ( 多选 ) ( ) ACD
A、使用 ref 参数,传递到 ref 参数的参数必须最先初始化。
B、使用 out 参数,传递到 out 参数的参数必须最先初始化。//可以放在方法内部
C、使用 ref 参数,必须将参数作为 ref 参数显式传递到方法。
D、使用 out 参数,必须将参数作为 out 参数显式传递到方法 算法题
、一个笼子里面关了鸡和兔子(鸡有2 只脚,兔子有4 只脚,没有例外)。已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物?请用C#语言实现这个计算过程;
、有一个数组 “int a[]” 使用冒泡排序实现数组内的排序(C#语言实现):
、获得一个int型的数中二进制中的1的个数(C#语言实现)
using System;
class Program
{
static void Main(string[] args)
{
int x = ;
for (int i = ; i < ; i++)
{
Console.WriteLine("位{0} = {1}", i, GetBit(x, i));
}
Console.ReadKey();
}
// 获取指定位的值
static int GetBit(int x, int bit)
{
return (x >> bit) & ;
}
}
、输入一个数组,实现一个函数,让所有奇数都在偶数前面(C#语言实现) Unity3D方面
、Unity3D引擎中最基本的计量单位是什么?米
、Unity3D中实现运动组件的位置变化的两种方法?(请用C#语言实现)
transform.Translate(Vector3.forward);
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddForce(Vector3.forward, ForceMode.Force);
、一个GameObject对象最基本的组件是什么?请描述这个组件的基本功能!
、请用C#代码实现给一个游戏个体添加上刚体组件,并且需要这个游戏对象可以支持碰撞和穿透效果;
Rigidbody rb = gameObject.AddComponent<Rigidbody>();
BoxCollider box = gameObject.AddComponent<BoxCollider>();
、如何获取一个对象上的”MyTestScript.cs”脚本?(请用C#语言实现)
MyTestScript myScript = gameObject.GetComponent<MyTestScript>();
、请用Unity中的四元数绕一个点(20.0f, 30.0f, 0.1f)的X轴顺时针旋转20度。(请用C#语言实现)
Void Start()
{
}
voie MyRotateAround(Vector3 pos, Vector3 axis, float angle)
{
Quaternion q = Quaternion.AngleAxis(angle, axis);
Vector3 dir = transfor.position - pos;
Vector3 projectV = (Vector3.Dot(axis, dir) / axis.magnitude) * axis.normalized;
Vector3 n = dir - projectV;
Vector3 newN = q * n;
Vector3 newPos = pos + projectV + newN;
transform.position = newPos;
transform.rotation *= q;
}
、请阐述:如果我们创建了一个游戏对象后后我们需要添加哪些的组件才能使Unity引擎将其渲染出来。(请用C#实现组件的添加代码)