C#語言基礎-03

C#語言基礎-03

寫這兩篇文章的目的是爲了備忘、 C#語言在大學讀書時候學過、當時做過一些東西、但是由於從事的主要工作和C#無關便忘記了。 近來公司增加了Unity業務、 寫Unity主要是C# 和js 想來C# 的語法結構和Java很相似、於是採用了C#語言作爲公司遊戲項目的主要語言。

本系列主要分上中下三篇文章來記錄。 分別牽涉到C# 中的初級、中級、高級內容。

由於本月一直忙於公司的項目、 所以發文就耽擱了, 但是回想五月忙上過去了,還是整理整理髮一篇吧。

本文主要寫一些關於C#語言的高級知識, 如果沒有看過初級的,可以先看上一篇文章,在電腦上敲敲試試,跑一下看看。

1.string相關操作

class Program {
        static void Main(string[] args)
        {
            string s = "www.samuelnotes.com";//我們使用string類型去存儲字符串類型  字符串需要使用雙引號引起來
            int length = s.Length;

            if (s == "www.samuelnotes.com")
            {
                Console.Write("相同");
            }
            else
            {
                Console.Write("不相同");
            }
            Console.Write(length);
            s = "http://" + s;
            Console.Write(s);
            char c = s[3];
            Console.WriteLine(c);
            for (int i = 0; i < s.Length; i++)
            {
                Console.WriteLine(s[i]);
            }

            //string s = "www.samuelnotes.com";//string 是System.String的別名
            //int res = s.CompareTo("saki");//當兩個字符串相等的時候,返回0  當s在字母表中的排序靠前的時候,返回-1, 否則返回1
            //Console.Write(res);
            //string newStr = s.Replace('.', '-');
            //string newStr = s.Replace(".", "----");//把指定的字符換成指定的字符 或者把指定的字符串換成指定的字符串
            //Console.WriteLine(s);
            //Console.WriteLine(newStr);

            //string[] strArray = s.Split('.');
            //foreach (var temp in strArray)
            //{
            //    Console.WriteLine(temp);
            //}

            //string str = s.Substring(4);
            //Console.WriteLine(str);

            //string str = s.ToUpper();
            //Console.Write(str);

            //string str  =s.Trim();
            //Console.WriteLine(str);

            int index = s.IndexOf("samuelnotesdd");//我們可以使用這個方法判斷當前字符串是否包含一個子字符串,如果不包含,返回-1,如果包含會返回第一個字符的索引
            Console.WriteLine(index);

            Console.ReadKey();
        }
    }
  1. stringBuilder
StringBuilder {
    class Program {
        static void Main(string[] args) {
            
            //1,
            //StringBuilder sb = new StringBuilder("www.samuelnotes.com");//利用構造函數創建stringbuilder
            //2
            //StringBuilder sb = new StringBuilder(20);//初始一個空的stringbuilder對象,佔有20個字符的大小
            //3
            //StringBuilder sb = new StringBuilder("www.samuelnotes.com", 100);
            //sb.Append("/xxx.html");
            //當我們需要對一個字符串進行頻繁的刪除添加操作的時候,使用stringbuilder的效率比較高
            //Console.WriteLine(sb.ToString());

            //sb.Insert(0, "http://");
            //Console.WriteLine(sb);

            //sb.Remove(0, 3);
            //Console.WriteLine(sb);
            //sb.Replace(".", "");
            //sb.Replace('.', '-');
            //Console.WriteLine(sb);
             
            //string s = "www.samuelnotes.com";
            //s = s + "/xxx.html";
            //Console.WriteLine(s);

            

            Console.ReadKey();
        }
    }
}

3.正則表達式

 class Program {
        static void Main(string[] args)
        {
            //定位元字符 ^ $
            //string s = "I am blue cat.";
            //string res  = Regex.Replace(s, "^", "開始:");//搜索字符串 符合正則表達式的情況,然後把所有符合的位置,替換成後面的字符串
            //Console.WriteLine(res);
            //string res = Regex.Replace(s, "$", "結束");
            //Console.WriteLine(res);

            //string s = Console.ReadLine();
            //bool isMatch = true;//默認標誌位,表示s是一個合法密碼(全部是數字)
            //for (int i = 0; i < s.Length; i++)
            //{
            //    if (s[i] < '0' || s[i] > '9')//當前字符如果不是數字字符
            //    {
            //        isMatch = false;
            //        break;
            //    }
            //}
            //if (isMatch)
            //{
            //    Console.WriteLine("是一個合法密碼");
            //}
            //else
            //{
            //    Console.WriteLine("不是一個合法密碼");
            //}
            //string pattern = @"^\d*$";//正則表達式
            //string pattern = @"\d*";
            //bool isMatch = Regex.IsMatch(s, pattern);
            
            //Console.WriteLine(isMatch);

            //string pattern = @"^\W*$";

            //反義字符
            //string str = "I am a cat.";
            //string pattern = @"[^ahou]";//它代表一個字符, 除了ahou之外的任意一個字符
            //string s = Regex.Replace(str, pattern, "*");
            //Console.WriteLine(s);

            //重複描述字符
            //string qq1 = "234234";
            //string qq2 = "234234234234234";
            //string qq3 = "d4234234234";
            //string pattern = @"^\d{5,12}$";
            //Console.WriteLine( Regex.IsMatch(qq1,pattern) );
            //Console.WriteLine( Regex.IsMatch(qq2,pattern) );
            //Console.WriteLine( Regex.IsMatch(qq3,pattern) );

            //string s = "34 ((*&sdflkj 路口的設計費";
            //string pattern = @"\d|[a-z]";
            //MatchCollection col = Regex.Matches(s, pattern);
            //foreach (Match match in col)
            //{
            //    Console.WriteLine(match.ToString());//調用tostring方法,會輸出match所匹配到的字符串
            //}

            //string s = "zhangsan;lisi,wangwu.zhaoliu";
            ////string pattern = @"[;,.]";
            //string pattern = @"[;]|[,]|[.]";
            //string[] resArray = Regex.Split(s, pattern);
            //foreach (var s1 in resArray)
            //{
            //    Console.WriteLine(s1);
            //}

            //重複 多個字符 使用(abcd){n}進行分組限定
            string inputStr = Console.ReadLine();
            string strGroup2 = @"(ab\w{2}){2}";//  == "ab\w{2}ab\w{2}"
            Console.WriteLine("分組字符重複2兩次替換爲5555,結果爲:" + Regex.Replace(inputStr, strGroup2, "5555"));


            Console.ReadKey();
        }
    }
  1. 委託

我們再來看一下委託, 委託的用法很簡單,

class Program
    {
        private delegate string GetAString();//定義了一個委託類型,這個委託類型的名字叫做GetAString
        static void Main(string[] args)
        {
            //int x = 40;
            ////string s = x.ToString();//tostring 方法用來把數據轉換成字符串
            ////Console.WriteLine(s);
            ////使用委託類型 創建實例
            ////GetAString a = new GetAString(x.ToString);//a指向了x中的tostring方法
            //GetAString a = x.ToString;

            ////string s = a();//通過委託實例去調用 x中的tostring方法
            //string s = a.Invoke();//通過invoke方法調用a所引用的方法
            //Console.WriteLine(s);//通過委託類型是調用一個方法,跟直接調用這個方法 作用是一樣的


            //實例2 使用委託類型作爲方法的參數
            PrintString method = Method1;
            PrintStr(method);
            method = Method2;
            PrintStr(method);
            Console.ReadKey();
        }

        private delegate void PrintString();

        static void PrintStr( PrintString print )
        {
            print();
        }

        static void Method1() {
            Console.WriteLine("method1");
        }
        static void Method2() {
            Console.WriteLine("method2");
        }
    }

打印輸出:

method1
method2

5.委託Action

Action委託 {
    class Program {
        static void PrintString()
        {
            Console.WriteLine("hello world.");
        }

        static void PrintInt(int i)
        {
            Console.WriteLine(i);
        }

        static void PrintString(string str)
        {
            Console.WriteLine(str);
        }

        static void PrintDoubleInt(int i1, int i2)
        {
            Console.WriteLine(i1+i2);
        }
        static void Main(string[] args)
        {
            //Action a = PrintString;//action是系統內置(預定義)的一個委託類型,它可以指向一個沒有返回值,沒有參數的方法
            //a.Invoke();



            Action<int> a = PrintInt;//定義了一個委託類型,這個類型可以指向一個沒有返回值,有一個int參數的方法

            a.Invoke(12312);


            //Action<string> a = PrintString;//定義了一個委託類型,這個類型可以指向一個沒有返回值,有一個string參數的方法 在這裏系統會自動尋找匹配的方法
            //Action<int, int> a = PrintDoubleInt;
            //a(34, 23);
            Console.ReadKey();
            //action可以後面通過泛型去指定action指向的方法的多個參數的類型 ,參數的類型跟action後面聲明的委託類型是對應着的
           
        }
    }
}

6.委託Func

Func委託 {
    class Program {
        static int Test1()
        {
            return 1;
        }

        static int Test2(string str)
        {
            Console.WriteLine(str);
            return 100;
        }

        static int Test3(int i, int j)
        {
            return i + j;
        }
        static void Main(string[] args)
        {
            Func<int> a = Test1;//func中的泛型類型制定的是 方法的返回值類型

            Console.WriteLine(a());

            Func<string, int> a = Test2;//func後面可以跟很多類型,最後一個類型是返回值類型,前面的類型是參數類型,參數類型必須跟指向的方法的參數類型按照順序對應
            Console.WriteLine(a("xxxx"));

            Func<int, int, int> a = Test3;//func後面必須指定一個返回值類型,參數類型可以有0-16個,先寫參數類型,最後一個是返回值類型
            int res = a(1, 5);
            Console.WriteLine(res);

            Console.ReadKey();
        }
    }
}

後邊再來個冒泡排序聯繫一下:

冒泡排序拓展 {
    class Program {
        static void Sort(int[] sortArray)
        {
            bool swapped = true;
            do
            {
                swapped = false;
                for (int i = 0; i < sortArray.Length - 1; i++)
                {
                    if (sortArray[i] > sortArray[i + 1])
                    {
                        int temp = sortArray[i];
                        sortArray[i] = sortArray[i + 1];
                        sortArray[i + 1] = temp;
                        swapped = true;
                    }
                }
            } while (swapped);
        }

        static void CommonSort<T>(T[] sortArray, Func<T,T,bool>  compareMethod)
        {
            bool swapped = true;
            do {
                swapped = false;
                for (int i = 0; i < sortArray.Length - 1; i++) {
                    if (compareMethod(sortArray[i],sortArray[i+1])) {
                        T temp = sortArray[i];
                        sortArray[i] = sortArray[i + 1];
                        sortArray[i + 1] = temp;
                        swapped = true;
                    }
                }
            } while (swapped);
        }
        static void Main(string[] args) {
            int[] sortArray = new int[] { 123, 23, 12, 3, 345, 43, 53, 4 };
            Sort(sortArray);
            foreach (var temp in sortArray)
            {
                Console.Write(temp + " ");
            }

            //Employee[] employees = new Employee[]
            //{
            //    new Employee("dsf",12), 
            //    new Employee("435dsf",234), 
            //    new Employee("234dsf",14), 
            //    new Employee("ds234f",234), 
            //    new Employee("dssfdf",90)
            //};
            //CommonSort<Employee>(employees,Employee.Compare);
            //foreach (Employee em in employees)
            //{
            //    Console.WriteLine(em);
            //}
            Console.ReadKey();
        }
    }
    
    
    class Employee {
        public string Name { get; private set; }
        public int Salary { get; private set; }

        public Employee(string name, int salary)
        {
            this.Name = name;
            this.Salary = salary;
        }
        //如果e1大於e2的話,返回true,否則返回false
        public static bool Compare(Employee e1, Employee e2)
        {
            if (e1.Salary > e2.Salary) return true;
            return false;
        }

        public override string ToString()
        {
            return Name + ":" + Salary;
        }
    }
    
    

7.多播委託

 class Program {
        static void Test1()
        {
            Console.WriteLine("test1");
            //throw new Exception();
        }

        static void Test2()
        {
            Console.WriteLine("test2");
        }
        static void Main(string[] args) {
            //多播委託
            Action a = Test1;
            //a = Test2;
            a += Test2;//表示添加一個委託的引用 
            //a -= Test1;
            //a -= Test2;
            //if(a!=null)
            //    a();//當一個委託沒有指向任何方法的時候,調用的話會出現異常null

            Delegate[] delegates = a.GetInvocationList();
            foreach (Delegate de in delegates)
            {
                de.DynamicInvoke();
            }
            Console.ReadKey();
        }
    }

這樣就可以同時調用a所指向所有的方法。

8.匿名方法

namespace 匿名方法 {
    class Program {
        static int Test1(int arg1, int arg2)
        {
            return arg1 + arg2;
        }
        static void Main(string[] args)
        {
            //Func<int, int, int> plus = Test1;

            //修改成匿名方法的形式
            Func<int, int, int> plus = delegate(int arg1, int arg2)
            {
                return arg1 + arg2;
            };
            //匿名方法 本質上是一個方法,只是沒有名字,任何使用委託變量的地方都可以使用匿名方法賦值


            Console.ReadKey();
        }
    }

9.lambda 表達式


namespace _09_Lambda表達式 {
    class Program {
        static void Main(string[] args) {
            //lambda表達式用來代替匿名方法,所以一個lambda表達式也是定義了一個方法
            //Func<int, int, int> plus = delegate(int arg1, int arg2) {
            //    return arg1 + arg2;
            //};

            Func<int, int, int> plus = (arg1, arg2) =>// lambda表達式的參數是不需要聲明類型的
            {
                return arg1 + arg2;
            };

            Console.WriteLine(plus(90, 60));

            Func<int, int> test2 = a => a + 1;//lambda表示的參數只有一個的時候,可以不加上括號  當函數體的語句只有一句的時候,我們可以不加上大括號 也可以不加上return語句
            Func<int, int> test3 = (a) =>
            {
                return a + 1;
            };
            Console.WriteLine(test2(34));
            Console.WriteLine(test3(34));
            Console.ReadKey();
        }
    }
}

  1. 事件

namespace 事件 {//Event
    class Program
    {
        public delegate void MyDelegate();

        //public MyDelegate mydelgate;  //聲明瞭一個委託類型的變量,作爲類的成員

        public event MyDelegate mydelgate;//聲明瞭一個委託類型的變量,作爲類的成員

        static void Main(string[] args)
        {
        
            Program p = new Program();
            p.mydelgate = Test1;
            p.mydelgate();
            Console.ReadKey();
        }

        static void Test1()
        {
            Console.WriteLine("test1");
        }
    }
}

  1. 觀察者設計者模式

namespace _012_觀察者設計模式_貓捉老鼠 {
    class Program {
        static void Main(string[] args) {
            Cat cat = new Cat("加菲貓","黃色");
            Mouse mouse1 = new Mouse("米奇","黑色",cat);
            //cat.catCome += mouse1.RunAway;
            //Mouse mouse2 = new Mouse("唐老鴨", "紅色",cat);
            //cat.catCome += mouse2.RunAway;
            //Mouse mouse3 = new Mouse("xx", "紅色",cat);
            //cat.catCome += mouse3.RunAway;
            Mouse mouse4 = new Mouse("水", "紅色",cat);
            //cat.catCome += mouse4.RunAway;
            //cat.CatComing(mouse1,mouse2,mouse3);//貓的狀態發生改變  在cat中調用了觀察者的方法,當觀察者發生改變的時候,需要同時修改被觀察者的代碼
            cat.CatComing();
            //cat.catCome();//事件不能再類的外部觸發,只能在類的內部觸發
            Console.ReadKey();
        }
    }
}

namespace _011_觀察者設計模式_貓捉老鼠 {
    /// <summary>
    /// 觀察者類:老鼠
    /// </summary>
    class Mouse
    {
        private string name;
        private string color;

        public Mouse(string name, string color,Cat cat)
        {
            this.name = name;
            this.color = color;
            cat.catCome += this.RunAway;//把自身的逃跑方法 註冊進 貓裏面  訂閱消息
        }
        /// <summary>
        /// 逃跑功能
        /// </summary>
        public void RunAway()
        {
            Console.WriteLine(color+"的老鼠"+name+"說: 老貓來, 趕緊跑, 我跑, 我使勁跑,我加速使勁跑 ...");
        }
    }
}

namespace _011_觀察者設計模式_貓捉老鼠 {
    /// <summary>
    /// 貓類
    /// </summary>
    class Cat
    {
        private string name;
        private string color;

        public Cat(string name, string color)
        {
            this.name = name;
            this.color = color;
        }

        /// <summary>
        /// 貓進屋(貓的狀態發生改變)(被觀察者的狀態發生改變)
        /// </summary>
        //public void CatComing(Mouse mouse1,Mouse mouse2,Mouse mouse3)
        public void CatComing()
        {
            Console.WriteLine(color+"的貓"+name+"過來了,喵喵喵 ...");

            //mouse1.RunAway();
            //mouse2.RunAway();
            //mouse3.RunAway();
            if(catCome!=null)
                catCome();
        }

        public event Action catCome;//聲明一個事件 發佈了一個消息
    }
}

  1. 反射

namespace _012_反射和特性 {
    class Program {
        static void Main(string[] args) {
            //每一個類對應一個type對象,這個type對象存儲了這個類 有哪些方法跟哪些數據 哪些成員
            //MyClass my = new MyClass();//一個類中的數據 是存儲在對象中的, 但是type對象只存儲類的成員
            //Type type = my.GetType();//通過對象獲取這個對象所屬類 的Type對象
            //Console.WriteLine(type.Name);//獲取類的名字
            //Console.WriteLine(type.Namespace);//獲取所在的命名空間
            //Console.WriteLine(type.Assembly);
            //FieldInfo[] array= type.GetFields();//只能獲取public 字段
            //foreach (FieldInfo info in array)
            //{
            //    Console.Write(info.Name+" ");
            //}
            //PropertyInfo[] array2 = type.GetProperties();
            //foreach (PropertyInfo info in array2)
            //{
            //    Console.Write(info.Name+" ");
            //}
            //MethodInfo[] array3 = type.GetMethods();
            //foreach (MethodInfo info in array3)
            //{
            //    Console.Write(info.Name+" ");
            //}
            //通過type對象可以獲取它對應的類的所有成員(public)

            MyClass my = new MyClass();
            Assembly assem =  my.GetType().Assembly;//通過類的type對象獲取它所在的程序集 Assembly
            Console.WriteLine(assem.FullName);
            Type[] types = assem.GetTypes();
            foreach (var type in types)
            {
                Console.WriteLine(type);
            }
            Console.ReadKey();
        }
    }
}

  class MyClass
    {
        private int id;
        private int age;
        public int number;
        public string Name { get; set; }
        public string Name2 { get; set; }
        public string Name3 { get; set; }

        public void Test1() {

        }
        public void Test2() {

        }
    }
    

  1. 特性

namespace _013_特性 {
    //通過制定屬性的名字,給屬性賦值,這種事命名參數
    [MyTest("簡單的特性類",ID = 100)]//當我們使用特性的時候,後面的Attribute不需要寫
    class Program {
        [Obsolete("這個方法過時了,使用NewMethod代替")] //obsolete特性用來表示一個方法被棄用了
        static void OldMethod()
        {
            Console.WriteLine("Oldmethod");
        }

        static void NewMethod()
        {
            
        }
        [Conditional("IsTest")]
        static void Test1() {
            Console.WriteLine("test1");
        }
        static void Test2() {
            Console.WriteLine("test2");
        }

        [DebuggerStepThrough]//可以跳過debugger 的單步調試 不讓進入該方法(當我們確定這個方法沒有任何錯誤的時候,可以使用這個)
        static void PrintOut(string str,[CallerFilePath] string fileName="",[CallerLineNumber] int lineNumber=0,[CallerMemberName] string methodName ="")
        {
            Console.WriteLine(str);
            Console.WriteLine(fileName);
            Console.WriteLine(lineNumber);
            Console.WriteLine(methodName);
        }
        static void Main(string[] args) {
            //NewMethod();
            //OldMethod();
            //Console.ReadKey();

            //Test1();
            //Test2();
            //Test1();

            //PrintOut("123");
            //
            Type type = typeof(Program);//通過typeof+類名也可以獲取type對象
            object[] array = type.GetCustomAttributes(false);
            MyTestAttribute mytest = array[0] as MyTestAttribute;
            Console.WriteLine(mytest.Description);
            Console.WriteLine(mytest.ID);
            Console.ReadKey();
        }
    }
}

namespace _013_特性 {
    //1, 特性類的後綴以Attribute結尾 
    //2, 需要繼承自System.Attribute
    //3, 一般情況下聲明爲 sealed
    //4, 一般情況下 特性類用來表示目標結構的一些狀態(定義一些字段或者屬性, 一般不定義方法)
    [AttributeUsage(AttributeTargets.Class)]//表示該特性類可以應用到的程序結構有哪些
    sealed class MyTestAttribute : System.Attribute {
        public string Description { get; set; }
        public string VersionNumber { get; set; }
        public int ID { get; set; }

        public MyTestAttribute(string des)
        {
            this.Description = des;
        }
    }
}

14.總結

還是那句話、多思考、上手敲代碼、 調試調試、多試試。 如果有問題可以評論區留言共同學習進步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章