【unity之c#专题篇】——进阶知识实践练习

这篇具有很好参考价值的文章主要介绍了【unity之c#专题篇】——进阶知识实践练习。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【unity之c#专题篇】——进阶知识实践练习


👨‍💻个人主页:@元宇宙-秩沅

👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!

👨‍💻 本文由 秩沅 原创

👨‍💻 收录于专栏unityc#专题篇习题

【unity之c#专题篇】——进阶知识实践练习


⭐习题总结专题篇⭐

⭐🅰️系统路线点击跳转⭐


⭐【Unityc#专题篇】之c#核心篇】

⭐【Unityc#专题篇】之c#基础篇】

⭐【Unity-c#专题篇】之c#入门篇)

⭐【Unityc#专题篇】—基础章题单实践练习

【Unityc#专题篇】—核心章题单实践练习



🎶前言

核心章知识点详解入口


🅰️ 题单来自: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.应用于背包,仓库等容器物品的存取系统
    【unity之c#专题篇】——进阶知识实践练习

    /// <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.应用于需要先进后出的情况

【unity之c#专题篇】——进阶知识实践练习

     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类一样

    【unity之c#专题篇】——进阶知识实践练习
 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.应用于某个名字和数据对象的存储应用

【unity之c#专题篇】——进阶知识实践练习

 /// <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.在泛型类中的泛型方法占位符是不一样的,最好手动区分
    【unity之c#专题篇】——进阶知识实践练习

    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
    【unity之c#专题篇】——进阶知识实践练习
    /// <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.继承的时候,子类默认先调用父类的构造函数

【unity之c#专题篇】——进阶知识实践练习

  /// <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
    【unity之c#专题篇】——进阶知识实践练习
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;
            }
        }

【unity之c#专题篇】——进阶知识实践练习

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();
        }

【unity之c#专题篇】——进阶知识实践练习


🎶(L)数据结构存储方式——顺序存储和链式存储


  • 实践经验

    1.最大的应用区别在于顺序存储适合查改,链式存储适合增删
    2.构建链表时要考虑全面,考虑到每个节点相互之间的关系,看代码的逻辑性是否严谨
    【unity之c#专题篇】——进阶知识实践练习
 //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两个类

    【unity之c#专题篇】——进阶知识实践练习

            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)【unity之c#专题篇】——进阶知识实践练习

【unity之c#专题篇】——进阶知识实践练习

 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;

        }
    }
在这里插入代码片

【unity之c#专题篇】——进阶知识实践练习

  #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.让委托更加安全

【unity之c#专题篇】——进阶知识实践练习

    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.要注意委托的那四个对应的有无参和有无返回值

【unity之c#专题篇】——进阶知识实践练习

 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

【unity之c#专题篇】——进阶知识实践练习

  • 形成闭包的条件:
    外层函数包裹的内层函数中用到了外层函数的变量,此时就改变了它原本在栈里面的生命周期,此时的情况称为闭包
  • 闭包的特点
    使用到的那个外部变量,在内部中它的值并不是它创建时的值,而是它在父函数中的最终值
 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.应用于,多规则排序问题,和对于字典(键值对)数据的排序

【unity之c#专题篇】——进阶知识实践练习

 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);
            }
        }
    }

【unity之c#专题篇】——进阶知识实践练习

  • 利用枚举的转换知识点,并且利用第二个放法(继承接口)来进行排序
    //*********************************
    //排序规则:
    //类型:国用 ,军用,民用
    //品质:红,绿,白
    //*********************************
    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 );
            }
        }

【unity之c#专题篇】——进阶知识实践练习


    #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.在历史替换原则中,父类泛型委托和子类泛型委托可以相互装载

【unity之c#专题篇】——进阶知识实践练习

   
      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控制)

    以下贪吃蛇的逻辑如下:
    ①靠光标位置打印
    ②靠光标位置的改变移动
    ③方向靠枚举成员和位置的关系
    ④靠输出空格清除
    ⑤靠多线程来控制

【unity之c#专题篇】——进阶知识实践练习
【unity之c#专题篇】——进阶知识实践练习

//逻辑实现:
    //位置
    //移动:(本质是控制光标位置进行绘图)
    //绘制
    //擦除
    //方向     
    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.宏定义字符和取消定义指令,逻辑处理指令,报错警告指令

    【unity之c#专题篇】——进阶知识实践练习
#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()实例化对象

【unity之c#专题篇】——进阶知识实践练习

//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.修改了类库里面的内容后要重新生成

【unity之c#专题篇】——进阶知识实践练习


//类库
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 实现

【unity之c#专题篇】——进阶知识实践练习

  • 语法糖实现
  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模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity之c#专题篇——【不动如山核心章】

    👨‍💻个人主页 :@元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏 : unity之c#专题篇 ⭐[【Unityc#专题篇】之c#进阶篇】 ⭐【Unityc#专题篇】之c#核心篇】 ⭐【Unityc#专题篇】之c#基础篇】 ⭐【Unity-c#专题篇】之

    2023年04月23日
    浏览(36)
  • 【Unity之c#专题篇】——【不动如山核心章—掌握核心只需这一篇】

    👨‍💻个人主页 :@元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏 : unity之c#专题篇 ⭐[【Unityc#专题篇】之c#进阶篇】 ⭐【Unityc#专题篇】之c#核心篇】 ⭐【Unityc#专题篇】之c#基础篇】 ⭐【Unity-c#专题篇】之

    2023年04月24日
    浏览(40)
  • 2023-06-10 Untiy进阶 C#知识补充1——.Net介绍

    一、.Net 介绍 ​ 微软的 .Net 既不是编程语言也不是框架,是类似于互联网时代、次时代、21世纪、信息时代之类的宣传口号 ​ 它是一整套技术体系的统称,或者说它是微软提供的技术平台的代号。包含的内容有: 框架体系: .Net Framework .Net Core Mono 等等 开发语言: C#(C# 是

    2024年02月09日
    浏览(51)
  • C#学习笔记--数据结构、泛型、委托事件等进阶知识点

    ArrayList 元素类型以Object类型存储,支持增删查改的数组容器。 因而存在装箱拆箱操作,谨慎使用。 ArrayList和数组区别? ArrayList使用不用说明固定长度,数组则需要 数组存储的是指定类型的,ArrayList是Object ArrayList存在装箱拆箱,数组不存在 ArrayList数组长度用Count获取 而数组

    2024年02月08日
    浏览(50)
  • 2023-08-15 Untiy进阶 C#知识补充5——C#6主要功能与语法

    ​ 注意:在此仅提及 Unity 开发中会用到的一些功能和特性,对于不适合在 Unity 中使用的内容会忽略。 一、概述 ​ C#6 的新增功能和语法主要包含: =运算符(C# 进阶内容) Null 传播器(C# 进阶内容) 字符串内插(C# 进阶内容) 静态导入 异常筛选器 nameof 运算符 二、静态导

    2024年02月12日
    浏览(35)
  • 2023-08-04 Untiy进阶 C#知识补充4——C#5主要功能与语法

    ​ 注意:在此仅提及 Unity 开发中会用到的一些功能和特性,对于不适合在 Unity 中使用的内容会忽略。 一、概述 C# 5 调用方信息特性(C# 进阶内容) 异步方法 async 和 await 二、回顾——线程 Unity 支持多线程 Unity 中开启的多线程不能使用主线程中的对象 Unity 中开启多线程后一

    2024年02月14日
    浏览(35)
  • 【C#】知识点实践序列之Lock的输出多线程信息

    大家好,我是全栈小5,欢迎来到《小5讲堂之知识点实践序列》文章。 2024年第2篇文章,此篇文章是C#知识点实践序列之Lock知识点,博主能力有限,理解水平有限,若有不对之处望指正! 本篇在Lock锁定代码块输出多线程信息,用于判断是否是同一个线程还是不同线程。 上篇

    2024年02月03日
    浏览(48)
  • 【运维知识高级篇】34道Shell编程练习题及答案(从基础到实战:基础+计算+判断+循环+控制与数组+实战进阶)

    ​本篇文章几乎涵盖了绝大部分的Shell语法练习,用一个个实战练习,巩固Shell的学习,话不多说,直接开始。 练习1:按照时间生成文件\\\"2018-05-22.log\\\"将每天的磁盘使用状态写入到对应日期的文件 练习2:统计Nginx日志中每个IP的访问量有多少,日志格式如下 练习3:写一个脚本

    2024年02月14日
    浏览(62)
  • 2023-06-19 Untiy进阶 C#知识补充3——C#1-4主要功能与语法

    ​ 注意:在此仅提及 Unity 开发中会用到的一些功能和特性,对于不适合在 Unity 中使用的内容会忽略。 一、概述 C# 1(C# 进阶内容) 委托 事件 C# 2(C# 进阶内容) 泛型 匿名方法 迭代器 可空类型 C# 3 隐式类型(C# 进阶内容) 对象集合初始化(C# 进阶内容) Lambda 表达式(C

    2024年02月10日
    浏览(49)
  • 【ASP.NET Core 基础知识】--最佳实践和进阶主题--微服务和容器化

    Tip:想要了解并学习微服务和容器化的知识,请跳转到《Docker极简教程》 一、微服务概述 1.1 什么是微服务? 微服务(Microservices)是一种软件架构风格,其中软件系统被划分为一组小型、自治的服务单元,这些服务单元围绕着业务能力进行组织,并通过轻量级的通信机制相

    2024年02月19日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包