👨💻个人主页:@元宇宙-秩沅
👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!
👨💻 本文由 秩沅 原创
👨💻 收录于专栏:unityc#专题篇习题
⭐习题总结专题篇⭐
⭐🅰️系统路线点击跳转⭐
⭐【Unityc#专题篇】之c#核心篇】
⭐【Unityc#专题篇】之c#基础篇】
⭐【Unity-c#专题篇】之c#入门篇)
⭐【Unityc#专题篇】—基础章题单实践练习
⭐【Unityc#专题篇】—核心章题单实践练习文章来源:https://www.toymoban.com/news/detail-468446.html
🎶前言
核心章知识点详解入口
🅰️ 题单来自:B站唐老狮
🎶(A) 数组基类——Array类
-
实践经验:
1.掌握三个常见的方法: 排序Sort,反转Reverser,复制Copy,清除Clear
int[] a = { 1,4,2,5,3,8,6,7};
//排序
Array.Sort(a);
foreach (int item in a)
{
Console.Write(" " + item);
}
Console.WriteLine();
//反转
string[] B = { "aa", "ss", "c" };
Array.Reverse(a);
Array.Reverse(B);
foreach (int item in a)
{
Console.Write(" " + item);
}
Console.WriteLine();
//复制
int[] b=new int[8];
Array.Copy(a,b,8); //把a数组复制b中
foreach (int item in b)
{
Console.Write(" " + item);
}
Console.WriteLine();
//清除
Array.Clear(a,0,a.Length );
foreach (int item in a)
{
Console.Write(" " + item);
}
Console.WriteLine();
🎶(B) 数据集合——ArrayList类
-
实践经验:
1.ArrayList和Array的 区别:
①ArrayList是集合,Array是数组
②ArrayList长度不固定自动扩容,Array长度固定
③ArrayList可存储不同类型object,Array类型单一固定
④ArraList封装了增删等便捷方法,Array得手动操作
⑤ArrayList的长度是count,Array是Length
2.当需要存储多个类型的数据,需要动态变化长度的时候用ArrayLIst
3.增加Add,删除Remove,查找Indexof,长度Count,容量capacity
4.应用于背包,仓库等容器物品的存取系统
/// <summary>
/// 背包管理类
/// </summary>
class Knapsack
{
ArrayList knapsack = new ArrayList(10); //初始化容量
private int money = 2000;
/// <summary>
/// 存储物品功能
/// </summary>
/// <param name="goods"></param>
public void Save(Object goods )
{
knapsack.Add(goods);
money += 50;
}
/// <summary>
/// 卖出物品的功能
/// </summary>
/// <param name="goods"></param>
public void Sell(Object goods)
{
knapsack.Remove(goods);
money -= 50;
}
public void Show()
{
for (int i = 0; i<knapsack.Count ; i++)
{
if (knapsack[i] is Food)
{
Food fruit = knapsack[i] as Food;
Console.WriteLine(fruit.Name);
Console.WriteLine(money);
}
}
}
}
class Food
{
public string Name { get; set; } = "苹果";
public void Show() { Console.WriteLine("我是子类里面的方法"); }
}
class Program
{
static void Main(string[] args)
{
Food apple = new Food();
Knapsack bag = new Knapsack();
bag.Save(apple);
bag.Show();
}
}
🎶(C)数据集合——Stack类
-
实践经验:
1.十进制转二进制的原理: 除2取余
2.Stack类里面没有单个删除和修改的方法
3.应用于需要先进后出的情况
class Program
{
public Stack stack = new Stack();
//栈的存取规则:先进后出
/// <summary>
/// 二进制方法转换
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public void Form( int num) //原理除2取余
{
while(num > 1)
{
stack.Push (num%2);
num /=2;
}
stack.Push(num % 2);
}
static void Main(string[] args)
{
try
{
Program text = new Program();
Console.WriteLine("请输入任意一个整形数");
int num = int.Parse(Console.ReadLine());
text.Form(num);
Console.WriteLine("栈现在的长度为:" + text.stack.Count );
while(text .stack.Count !=0)
{ Console.Write(text.stack.Pop()); }
}
catch
{
Console.WriteLine("请输入整形数字!");
}
}
}
🎶(D)数据集合——Queue类
-
实践经验:
1.采用了线程的停顿方法1000帧1秒
2.其他和Stack类一样
class Program
{
//Queue的存取规则是先进先出
static void Main(string[] args)
{
int num = 10;
Queue queue = new Queue();
do
{
queue.Enqueue(num);
} while (num-- != 0);
Console.WriteLine("数据存取成功!打印如下:");
try
{
while (queue != null)
{
Console.WriteLine(queue.Dequeue());
Thread.Sleep(1000);
}
}
catch
{
Console.WriteLine("队列已空");
}
}
}
🎶(E)数据集合——Hashtable类散列表
-
实践经验:
1.最大作用就是采用键值对的形式提高查询的效率
2.应用于某个名字和数据对象的存储应用
/// <summary>
/// 怪物对象
/// </summary>
class Monster
{
public string name;
public int attack;
public Monster(string name , int attack)
{
this.name = name;
this.attack = attack;
}
}
/// <summary>
/// 怪物管理器对象
/// </summary>
class MonsterControl
{
public Hashtable hashtable = new Hashtable();
/// <summary>
/// 创建怪物
/// </summary>
/// <param name="name"></param>
/// <param name="attack"></param>
public void CreatMonster(Monster boss)
{
hashtable.Add(boss.name, boss.attack);
}
/// <summary>
/// 移除怪物
/// </summary>
/// <param name="name"></param>
public void RemoveMonster(string name)
{
hashtable.Remove(name);
}
/// <summary>
/// 遍历怪物管理器
/// </summary>
public void Traverse()
{
foreach (DictionaryEntry item in hashtable )
{
Console.WriteLine("怪物名称为{0},攻击力为{1}", item.Key, item.Value);
}
}
static void Main(string[] args)
{
//hashtable 采用键值存取
Monster boss1 = new Monster("Rovanna", 999);
Monster boss2 = new Monster("皮蛋", 666);
Monster boss3 = new Monster("张三", 555);
MonsterControl control = new MonsterControl();
control.CreatMonster(boss1);
control.CreatMonster(boss2);
control.CreatMonster(boss3);
control.Traverse();
}
}
🎶(F)泛型
-
实践经验:
1.基础万物之父的类型返回方法typeof()
2.返回类型占用的字节方法sizeof()
3.在泛型类中的泛型方法占位符是不一样的,最好手动区分
class Program
{
/// <summary>
/// 判断返回的类型及其对应的字节
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <returns></returns>
public string BankBit<K>()
{
// is判断的是地址id || == 判断的是值
if (typeof(K) == typeof(int)) return "整形"+sizeof(int)+ "字节";
else if (typeof(K) == typeof(char)) return "字符型" + sizeof(char ) + "字节";
else if (typeof(K) == typeof(float )) return "单精浮点型" + sizeof(float ) + "字节";
else if (typeof(K) == typeof(string )) return "字符型" ;
else return "其他类型";
}
static void Main(string[] args)
{
int a =1;
Program type = new Program();
Console.WriteLine (type.BankBit<int>());
Console.WriteLine(type.BankBit<char>());
Console.WriteLine(type.BankBit<float >());
Console.WriteLine(type.BankBit<string>());
}
}
🎶(G)泛型约束
-
实践经验:
1.泛型约束实现单例模式基类被继承
2.单例模式适用于一个项目中国只有一个实例对象
3.可被忽略的缺点是在继承虽然可以限制成只有一个对象,但是还是可以new
/// <summary>
/// 用泛型实现一个单例模式基类
/// </summary>
/// <typeparam name="T"></typeparam>
class SingleBase<T> where T:new()
{
//private SingleBase(){ } //这个可以不用写,要被继承
static private T instance = new T();
static public T Instance
{
get
{
return instance ;
}
}
}
class Text : SingleBase<Text>
{
//继承单例基类时,构造函数一定要有公共无参的
public string Name { get; set; } = "俺是测试类";
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine ( Text.Instance.Name );
🎶(H)常用泛型数据结构类——List类
-
实践经验:
1.构造函数中调用自身对象用this
2.LIst的函数和ArrryList的函数基本一致
3.List和ArraryList最大的区别就是前者的本质是泛型数组,后者的本质是Object数组
4.继承的时候,子类默认先调用父类的构造函数
/// <summary>
/// 13.List的删除和存取
/// </summary>
//class Program
// {
//List和ArrayList的区别:前者结合了泛型,避免了拆箱装箱,效率更加优化
//static void Main(string[] args)
//{
// List<int> text = new List<int>();
// int[] arrary = new int[10]{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
// int i = 0;
// while (i<arrary.Length)
// {
// text.Add(arrary[i++]);
// }
// text.RemoveAt(5);
// foreach (int item in text)
// {
// Console.WriteLine(item);
// }
//}
//}
///在构造函数中用List存取元素
class Monster
{
static public List<Monster> control = new List<Monster>();
public Monster()
{
control.Add(this);
}
virtual public void attack() { }
}
class Boss : Monster
{
public override void attack()
{
Console.WriteLine("放大招");
}
}
class Gablin : Monster
{
public override void attack()
{
Console.WriteLine("哥布林的技能");
}
}
class Program
{
static void Main(string[] args)
{
Boss boss1 = new Boss();
Gablin boss2 = new Gablin();
Monster text = new Monster();
foreach (Monster item in Monster .control )
{
item.attack();
}
}
}
🎶(J)常用泛型数据结构类——Dictionary类
-
实践经验:
1.不能再foreach迭代器里面修改键值不然会报错
2.只要存在从一个数据获得另一个数据就可以应用Dictionary
private Dictionary<int, string> text = new Dictionary<int, string>();
public Program()
{
string[] upperArrary = { "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖", "拾" };
for (int i = 0; i < upperArrary.Length; i++)
{
text.Add(i + 1, upperArrary[i]);
}
}
public void Upper( string num )
{
for (int i = 0; i < num.Length; i++)
{
int index = num[i] - '0';
Console.Write(text[index]);
}
}
static void Main(string[] args)
{
Program Exam = new Program();
Console.WriteLine(Exam.text[3]);
try
{
Console.WriteLine("请输入一个不超过三位数的整数");
int num = int.Parse(Console.ReadLine());
Exam.Upper(num.ToString());
}
catch (Exception)
{
throw;
}
}
Dictionary<char, int> text = new Dictionary<char, int>();
public void Multiplay(string arrray )
{
for (int i = 0; i < arrray.Length; i++)
{
if(text.ContainsKey(arrray[i]))
{
text[arrray[i]] += 1;
}
else
{
text.Add(arrray[i],1);
}
}
}
public void Print()
{
foreach (KeyValuePair<char ,int> item in text)
{
Console.WriteLine(item);
}
}
static void Main(string[] args)
{
Program text = new Program();
string arrary = "Welcome to Unity World";
string Arrary = arrary.ToUpper();
text.Multiplay(Arrary);
text.Print();
}
🎶(L)数据结构存储方式——顺序存储和链式存储
-
实践经验:
1.最大的应用区别在于顺序存储适合查改,链式存储适合增删
2.构建链表时要考虑全面,考虑到每个节点相互之间的关系,看代码的逻辑性是否严谨
//1.
//顺序存储是一组连续的存储单元依次存储在线性表中的存储 方式(连续存储)
//链式存储是将一组任意不连续的存储单元存储在线性表中存储方式(任意存储)
//2.
//顺序存储的查改效率大于链式存储
//链式存储的增删效率大于顺序存储
//3.
//常用的数据结构有:数组,链表,栈,队列,数,图,堆,散列表
class LinkedNode<T>
{
public T vaule;
public LinkedNode(T Vaule)
{
this.vaule = Vaule;
}
public LinkedNode<T> peakLink = null;
public LinkedNode<T> nextLink = null;
}
class Link<T>
{
private int count = 0;
private LinkedNode<T> head;
private LinkedNode<T> last;
public int Count { get => count; }
public LinkedNode<T> Peak { get => head; }
public LinkedNode<T> Last { get => last; }
public void Add(LinkedNode<T> node) //添加节点
{
if (head == null)
{
head = node;
last = node;
count++;
}
else
{
//尾插法
LinkedNode<T> temp = last; ;
last.nextLink = node;
last = node;
last.peakLink = temp;
count++;
}
}
public void RemoveAt(int index) //删除节点
{
LinkedNode<T> Lnode = head ;
int temp = 1;
if (index > count || index < 1)
{
Console.WriteLine("超出链表规定范围,请输入正确范围进行移除操作!");
return;
}
else if (index == 1)
{
Console.WriteLine("指令为删除头节点");
head = head.nextLink;
}
else if (index == count)
{
Console.WriteLine("指令为删除尾节点");
last = last.peakLink;
Console.WriteLine("此时尾节点为:" + last.vaule);
last.nextLink = null;
}
else
{
while (true)
{
if (temp == index)
{
if (Lnode.peakLink != null)
Lnode.peakLink.nextLink = Lnode.nextLink;
if (Lnode.nextLink != null)
Lnode.nextLink.peakLink = Lnode.peakLink;
break;
}
temp++;
count--;
Lnode = Lnode.nextLink;
}
}
}
public void Print() //遍历所有节点
{
LinkedNode<T> Lnode = head;
while(Lnode != null )
{
Console.WriteLine("节点的值为:"+Lnode.vaule );
Lnode = Lnode.nextLink;
}
}
}
class Program
{
static void Main(string[] args)
{
Program text = new Program();
LinkedNode<int> node1 = new LinkedNode<int>(1);
LinkedNode<int> node2 = new LinkedNode<int>(2);
LinkedNode<int> node3 = new LinkedNode<int>(3);
Link<int> list = new Link<int>();
list.Add(node1);
list.Add(node2);
list.Add(node3);
Console.WriteLine("此时链表的长度为:" + list.Count);
list.RemoveAt(2);
list.Print();
}
}
🎶(M)常用泛型数据结构类——LinkedList类
-
实践经验:
1.本质上就是泛型的双向链表
2.当需要进行节点操作的时候,才用到节点类的API
3.所以需要掌握LinkedList 和LinkedListNode两个类
LinkedList<int> list = new LinkedList<int>();
Random rand = new Random();
int temp = 10;
while(temp-->=1)
{
list.AddFirst(rand.Next(101));
}
//foreach遍历
//foreach (var item in list)
//{
// Console.WriteLine(item);
//}
LinkedListNode<int> node = list.First;
//节点遍历——头节点遍历
Console.WriteLine("从头部开始 遍历了");
while(node!= null )
{
Console.WriteLine(node.Value);
node = node.Next;
}
//节点遍历 ——尾节点遍历\
Console.WriteLine("从尾部开始 遍历了");
node = list.Last;
while (node != null)
{
Console.WriteLine(node.Value);
node = node.Previous ;
}
🎶(N)常见的数据容器的应用范围
总结数组,list,Dectionary,Stack,Queue,LinkedList等存储容器。我们怎么来使用
- 数组:简单的数据类型存储的时候,或者只需要查改数据的时候
- List:它是ArraryList的泛型升级,适合一切对象的存储
- LinkeList:它是泛型双向链表,适合频繁增删的数据对象的情况下使用
- Dectionary:它是Hashtable的泛型升级,适合键值对象的存储
- Stack:适合先进后出的情况下使用
- Queue:适合先进先出的情况下使用
🎶(O)委托和事件——委托
-
实践经验:
1.委托有两种调用得方式:xx() 和 xx.Invoke();
2.if 和委托调用的简便写法:XX?.Invoke();
3.委托可以理解为,把工作或者一系列工作安排给谁做。做工作是行为,那么也就是方法,所以是将方法或一系列方法进行传递
4.c#中自定义的两种类型的委托(无返回值 Action ,有返回值Fun)
class Person
{
virtual public void Eat()
{
Console.WriteLine("吃饭");
}
}
class Mother:Person
{
public Action Cook;
public Mother()
{
Cook = cook;
Cook += OpenEat;
Cook += Eat;
}
public void cook()
{
Console.WriteLine("今天妈妈做饭");
}
public void OpenEat()
{
Console.WriteLine("开吃");
}
public override void Eat()
{
Console.WriteLine("我是妈妈我吃饭了");
}
}
class Father:Person
{
public override void Eat()
{
Console.WriteLine("我是爸爸我吃饭了");
}
}
class Children:Person
{
public override void Eat()
{
Console.WriteLine("我是儿子我吃饭了");
}
}
class Program
{
static void Main(string[] args)
{
Mother mother = new Mother();
Father father = new Father();
Children children = new Children();
mother.Cook += father.Eat;
mother.Cook += children.Eat;
mother.Cook();
//委托增加后也伴随着减,多的话全部清空
mother.Cook = null;
}
}
在这里插入代码片
#region 怪物死亡的逻辑
class Monster
{
public Action<Monster> BossDeadDo;
public int selfMoney = 10;
public void Dead()
{
Console.WriteLine("怪物已经死亡");
BossDeadDo?.Invoke(this);
//死亡后直接调用委托
//委托调用的第二种方式——简化代码
BossDeadDo = null;
//委托增加过后也得删除,或者清空
}
}
class Player
{
public int money = 0 ;
public void AddMoney(Monster boss) //增加怪物掉下来的金币
{
money += boss.selfMoney;
Console.WriteLine("您得财产为{0}",money );
}
}
class GUI
{
public int money = 0;
public void UpdateGui(Monster boss) //更新获得得金币分数
{
money += boss.selfMoney;
Console.WriteLine("您已获得{0}个金币", money);
}
}
class Result
{
public int num = 0;
public void Addnum(Monster boss)
{
num++;
Console.WriteLine("您已击败{0}个怪物",num);
}
}
class Progranm
{
static void Main(string[] args)
{
GUI gui = new GUI();
Player player = new Player();
Result result = new Result();
Monster monster = new Monster();
monster.BossDeadDo += player.AddMoney;
monster.BossDeadDo += result.Addnum;
monster.BossDeadDo += gui.UpdateGui;
monster.Dead();
monster.Dead();
}
🎶(P)委托和事件——事件
-
实践经验:
1.事件就是为了防止委托在外部被调用或赋值,防止被置空
(只能作为类,接口,结构体中的成员变量)
2.延时显示while(true)if(xx%99999)——关键是被除数多大,越大显示的越慢(当然这是未学线程之前的简单做法)
3.让委托更加安全
class AddHotMachine //加热器
{
public event Action<int> WarmDoEvent;
public int temperature = 0;
public void charge()
{
Console.WriteLine("已通电");
int Index = 0;
while(true) //让加热有间隔时间
{
if (Index % 99999999== 0) //简单的时间间隔器
{
temperature++;
Console.WriteLine("此时水温为" + temperature);
Index = 0;
if (temperature >= 100) break;
else if (temperature > 95)
{
WarmDoEvent(temperature);
}
}
++Index;
}
}
}
class WarmMachine //报警器
{
public void Worm(int temp)
{
Console.WriteLine("报警!此时水温为:"+temp);
}
}
class ShowMachine //显示器
{
public void show(int temp)
{
Console.WriteLine("水已经烧开");
}
}
class Program
{
static void Main(string[] args)
{
WarmMachine warm = new WarmMachine();
ShowMachine show = new ShowMachine();
AddHotMachine addHot = new AddHotMachine();
addHot.WarmDoEvent += warm.Worm;
addHot.WarmDoEvent += show.show;
addHot.charge();
}
}
}
🎶(Q)委托和事件——匿名函数
-
实践经验:
1.匿名函数的好处就是不用声明,直接写出方法体使用
2.委托函数的返回函数的写法更改了函数局部变量的生命周期 —闭包
3.两个使用: 委托(或事件)作为函数参数是用匿名函数,委托做为返回值类型的时候用
4.要注意委托的那四个对应的有无参和有无返回值
class Program
{
//委托函数返回函数的写法 ——>
static public Func<int,int> print( int m)
{
return delegate (int v) { return m * v; };
}
static void Main(string[] args)
{
//委托函数返回函数的调用
Func<int, int> text = print(4);
Console .WriteLine(text(25));
}
}
}
- API练习
class Program
{
//1,当委托作为返回值传递的时候,比如函数参数
//类型有参有返回值的委托函数
static public Func<string ,int > Print( int c ) //Print的参数和匿名函数没有半毛钱关系
{
return delegate (string a ) { return 2; };
//Lambda表达式写法:return (string a) => { return 2; };
//string 是参数类型 , int 是返回值类型
}
// 2。当委托作为参数传递的时候
static public int Print2( int a ,Action<int> b)
{
return a;
}
static void Main(string[] args)
{
Program.Print(3);
Program.Print2(2, delegate (int aC) { });
//Lambda表达式写法: Program.Print2(2, (int aC) => { });
//未一步到位的写法
Func<string, int> a = Print(2);
a("2");
//一步到位的写法
Print(2)("2");
}
🎶(R)委托和事件——Lambda表达式
-
实践经验:
1.改题目就是解决闭包时局部变量在父类函数范围内为最终值得情况
2.解决方法就是声明一个中间变量Index
-
形成闭包的条件:
外层函数包裹的内层函数中用到了外层函数的变量,此时就改变了它原本在栈里面的生命周期,此时的情况称为闭包 -
闭包的特点
使用到的那个外部变量,在内部中它的值并不是它创建时的值,而是它在父函数中的最终值
class Program
{
//题目就是为了解决闭包的第二个特点,在父类函数中的局部变量是范围内的最终值
static public Action Print()
{
Action action = null;
for (int i = 1; i <= 10; i++)
{
int index = i;
action += () => {
Console.WriteLine(index);
};
}
return action;
}
static void Main(string[] args)
{
Action text = Print();
text();
}
}
🎶(S)委托和事件——List排序的三个方法
-
实践经验:
1.排序的这几个方法,第三个(利用参数是委托的Sort方法重载)最为简便,当然第二个利用继承接口自定义规则函数也可以
2.第二个题目,利用了枚举的成员和数字的对象方法,进行了规则判断
3.应用于,多规则排序问题,和对于字典(键值对)数据的排序
class Monster
{
public string name;
public int attack;
public int defence;
public int blood;
public Monster(string name, int a, int d, int b)
{
this.name = name;
attack = a;
defence = d;
blood = b;
}
}
class Program
{
static void Main(string[] args)
{
List<Monster> boss = new List<Monster>();
boss.Add(new Monster("boss2", 33, 44, 66));
boss.Add(new Monster("boss3", 44, 55, 77));
boss.Add(new Monster("boss1", 66, 33, 55));
Console.WriteLine("请输入以下数字来选择您饲养怪物的战力排名");
try
{
int selection = int.Parse(Console.ReadLine());
switch (selection)
{
case 1://攻击排序
boss.Sort(
(Monster a, Monster b) =>
{
return a.attack < b.attack ? 1 : -1;
});
break;
case 2://防御排序
boss.Sort(
(Monster a, Monster b) =>
{
return a.defence < b.defence ? 1 : -1;
});
break;
case 3://血量排序
boss.Sort(
(Monster a, Monster b) =>
{
return a.blood < b.blood ? 1 : -1;
});
break;
case 4://反转
boss.Reverse();
break;
default:
break;
}
}
catch
{
Console.WriteLine("您的输入无效请按规定输入");
}
foreach (Monster item in boss)
{
Console.WriteLine(item.name);
}
}
}
- 利用枚举的转换知识点,并且利用第二个放法(继承接口)来进行排序
//*********************************
//排序规则:
//类型:国用 ,军用,民用
//品质:红,绿,白
//*********************************
enum Quality
{
红 = 1,
绿,
白
}
enum Type
{
国用 = 1,
军用,
民用
}
class Goods : IComparable<Goods>
{
public string type;
public string name;
public string quality;
public Goods( string type,string name ,string quality)
{
this.name = name;
this.quality = quality;
this.type = type;
}
public int CompareTo(Goods other)
{
// 当类型不同先比类型
if (other.type != this.type)
{
Type a ,b;
Enum.TryParse(other.type, out a);
Enum.TryParse(this.type, out b);
return (int)a >(int)b ? -1 : 1;
}
else if (other.quality != this.quality)
{
Quality a, b;
Enum.TryParse(other.quality , out a);
Enum.TryParse(this .quality, out b);
return (int)a > (int)b ? -1 : 1;
}
else if (other.name.Length < this.name.Length)
return - 1;
return 1;
}
}
class Program
{
static void Main(string[] args)
{
List<Goods> goods = new List<Goods>();
Goods knif1 = new Goods("民用","民用小刀1","绿");
Goods knif2 = new Goods("民用", "民用小刀2", "红");
Goods knif3 = new Goods("军用", "军用尼泊尔", "绿");
Goods knif4 = new Goods("国用", "国剑", "白");
Goods knif5 = new Goods("国用", "国剑", "红");
Goods knif6 = new Goods("军用", "军用尼泊尔", "红");
goods.Add(knif1);
goods.Add(knif2);
goods.Add(knif3);
goods.Add(knif4);
goods.Add(knif5);
goods.Add(knif6);
goods.Sort();
foreach (Goods item in goods)
{
Console.WriteLine(item.name+" "+item.type +" "+item .quality );
}
}
#region List对dictionary进行排序
class Program
{
static void Main(string[] args)
{
Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary.Add("火娃", 1);
dictionary.Add("金娃", 4);
dictionary.Add("木娃", 5);
dictionary.Add("土娃", 3);
dictionary.Add("水娃", 2);
List<KeyValuePair<string, int>> ssssot = new List<KeyValuePair<string, int>>();
foreach(KeyValuePair<string, int> item in dictionary )
{
ssssot.Add(item);
}
ssssot.Sort((a,b) => {
if (a.Value < b.Value)
return -1;
return 1;
});
foreach (KeyValuePair<string, int> item in ssssot )
{
Console.WriteLine(item );
}
}
🎶(T)协变和逆变
-
实践经验:
1.协变可以使泛型占位符只作为返回值使用
2.逆变可以使泛型占位符只作为参数使用
3.它们只适用于泛型委托和泛型接口
4.Action用的就是In
5.Func用的就是Out
6.在历史替换原则中,父类泛型委托和子类泛型委托可以相互装载
public delegate T TextOut<out T>(); //T只能作为返回值
public delegate void TextIn<in T>(T t); //T只能作为参数
public class BossFather
{
public void print()
{
Console.WriteLine("我是爸爸");
}
}
public class BossSon:BossFather
{
public void prints()
{
Console.WriteLine("我是儿子");
}
}
static void Main(string[] args)
{
//协变的体现
TextOut<BossSon> contorl1 = () =>
{
return new BossSon() ;
};
//父类装子类
TextOut<BossFather> father = contorl1;
father().print();
//逆变的体现
TextIn<BossFather> contorl2 = (value) =>
{
};
//子类装父类
TextIn<BossSon> Son = contorl2;
Son(new BossSon());
}
}
🎶(U)多线程
-
实践经验:
1.多线程用来处理同步发生并且稍微复杂的逻辑事件
2.当发生多个线程共用一个资源时加锁 lock(引用对象)
3.前台线程的循环影响期望的主进程时设置为后台线程
4.线程的开启和关闭(Start(),Abort()/bool控制)
以下贪吃蛇的逻辑如下:
①靠光标位置打印
②靠光标位置的改变移动
③方向靠枚举成员和位置的关系
④靠输出空格清除
⑤靠多线程来控制
//逻辑实现:
//位置
//移动:(本质是控制光标位置进行绘图)
//绘制
//擦除
//方向
enum E_Dection
{
up,
down,
left,
right
}
public struct Position
{
public int x;
public int y;
};
class Boss
{
Position position = new Position();
static E_Dection derection ;
static public E_Dection Derection
{
get
{
return derection;
}
set
{
derection = value;
}
}
//---构造函数 初始化---
public Boss(int x ,int y,E_Dection dection )
{
Console.CursorVisible = false;
position.x = x;
position.y = y;
derection = dection;
}
//---传入方向函数修改移动逻辑---
public void Move()
{
switch (derection)
{
case E_Dection.up:
position.y +=- 1;
break;
case E_Dection.down:
position.y += 1;
break;
case E_Dection.left:
position.x += -1;
break;
case E_Dection.right:
position.x += 1;
break;
default:
break;
}
}
//---绘制出来(打印)---
public void Show()
{
Console.SetCursorPosition(position.x, position.y);
Console.WriteLine("■");
}
//---擦除(打印空)---
public void Clear()
{
Console.SetCursorPosition(position.x, position.y);
Console.WriteLine(" ");
}
}
class Program
{
static public void Control()
{
while (true)
{
switch (Console.ReadKey(true).Key)
{
case ConsoleKey.W:
Boss.Derection = E_Dection.up;
break;
case ConsoleKey.S:
Boss.Derection = E_Dection.down;
break;
case ConsoleKey.A:
Boss.Derection = E_Dection.left;
break;
case ConsoleKey.D:
Boss.Derection = E_Dection.right;
break;
default:
break;
}
}
}
static void Main(string[] args)
{
Boss boss = new Boss(10,20,E_Dection.right );
Thread thread = new Thread(Control);
thread.Start();
while (true)
{
Thread.Sleep(500);
boss.Clear();
boss.Move();
boss.Show();
}
}
}
}
🎶(R)预处理指令
-
实践经验:
1.宏定义字符和取消定义指令,逻辑处理指令,报错警告指令
#define Unity2017
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
public int Mutiplay(int a, int b)
{
#if Unity5
return a + b ;
#elif Unity2017
return a * b ; //用预处理#define Unity2017后会执行该逻辑
#elif Unity2020
return a - b;
#else
return 0;
#endif
}
}
}
🎶(W)反射
-
实践经验:
1.当我们加载其他文件的程序的元数据时,首先用Assembly.LoadForm()去加载程序集
2.用Type来获取得到程序集中的对象
3.若要实例化获得的对象我们需要用Activator.CreatInstance()实例化对象
//Net.Framwork 库文件工程创建
namespace _反射_类库工程
{
public class Player
{
public string name;
public int blood;
public int attack;
public int defent;
public int position;
public Player()
{
Console.WriteLine("我是无参构造");
}
}
}
//控制台工程创建
class Program
{
static void Main(string[] args)
{
Assembly assembly = Assembly.LoadFrom(@"C:\Users\24158\source\repos\_复盘实践——进阶篇\_反射-类库工程\bin\Debug\_反射-类库工程.dll");
Type type = assembly.GetType("_反射-类库工程.Player");
Object player = Activator.CreateInstance(type);
}
}
🎶(X)特性
-
实践经验:
1.当要获取其他程序中对象的成员时,首先要保证它被实例化了Activator.CreatInstance()
2.修改了类库里面的内容后要重新生成
//类库
namespace _反射_类库工程
{
class ConstormAttribute:Attribute
{
}
public class Player
{
[Constorm()]
public string name ="张三";
[Obsolete("你干嘛,不能改哦")]
public int blood;
public int attack;
public int defent;
public int position;
public Player()
{
Console.WriteLine("实例化成功,我是无参构造");
}
}
}
//控制台
namespace _特性练习
{
class Program
{
class SelfAttribute:Attribute
{
public SelfAttribute()
{ }
}
static void Main(string[] args)
{
Assembly assembly = Assembly.LoadFrom(@"C:\Users\24158\source\repos\_复盘实践——进阶篇\_反射-类库工程\bin\Debug\_反射-类库工程.dll");
//---------打印程序集中的成员---------
Type [] all = assembly.GetTypes();
for (int i = 0; i < all.Length; i++)
{
Console.WriteLine(all[i]);
}
Console.WriteLine();
Type type = assembly.GetType("_反射_类库工程.Player");
object player = Activator.CreateInstance(type);
//---------打印Player类中的成员---------
FieldInfo[] num = type.GetFields();
for (int i = 0; i < num.Length; i++)
{
Console.WriteLine(num[i]);
}
Console.WriteLine();
//--------获取程序集中的特性---------
object [] attribute = type.GetCustomAttributes(false );
Attribute neAtrributel;
foreach (object item in attribute )
{
if(item is Attribute )
{
neAtrributel = item as Attribute;
Console.WriteLine(neAtrributel);
}
}
//--------获取Player类中的成员name---------
FieldInfo name = type.GetField("name");
FieldInfo blood = type.GetField("blood");
Console.WriteLine ( name.GetValue(player));
//-------判断Player类中的成员是否有特性---------
if (name.IsDefined(typeof(Attribute ))==true)
{
Console.WriteLine("非法操作,随意修改name成员");
}
}
}
}
🎶(Z)迭代器
-
实践经验:
所以如果要使自定义的类能够使用foreach遍历,就需要继承迭代器接口通过两个方法实现:
1.自定义迭代器实现
2.语法糖yeild return 实现
- 语法糖实现
class DDQ : IEnumerable
{
int[] arrary;
public DDQ()
{
arrary = new int[] { 1, 2, 3, 4, 5, 6 };
}
public IEnumerator GetEnumerator()
{
for (int i = 0; i < arrary.Length; i++)
{
yield return arrary[i]; //直接省去了IEnumreable接口下的几个成员方法,一步到位
}
}
}
class Program
{
static void Main(string[] args)
{
DDQ ddq = new DDQ();
foreach (int item in ddq)
{
Console.WriteLine(item);
}
}
}
- 自定义迭代器实现原理
class DDQ : IEnumerable, IEnumerator
{
int[] arrary;
int curionPosition ;
public DDQ()
{
arrary = new int[] { 1, 2, 3, 4, 5, 6 };
}
public IEnumerator GetEnumerator()
{
Reset();
return this;
}
//使用foreach的时候会自动调用 Current属性来返回值
public object Current
{
get
{
return arrary[curionPosition];
}
}
public bool MoveNext()
{
curionPosition++;
//当光标位置小于数组长度时返回true
return curionPosition < arrary .Length ;
}
//重置光标的作用
public void Reset()
{
curionPosition = -1;
}
}
class Program
{
static void Main(string[] args)
{
DDQ ddq = new DDQ();
foreach (int item in ddq)
{
Console.WriteLine(item);
}
}
}
}
⭐相关文章⭐
⭐【Unityc#专题篇】之c#核心篇】
⭐【Unityc#专题篇】之c#基础篇】
⭐【Unityc#专题篇】之c#入门篇】
⭐【Unityc#专题篇】—基础章题单实践练习
⭐【Unityc#专题篇】—核心章题单实践练习
你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!文章来源地址https://www.toymoban.com/news/detail-468446.html
到了这里,关于【unity之c#专题篇】——进阶知识实践练习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!