C#易忘點

下面是本身總結的一些C#語言方面用的少容易忘的地方,總結一下,在用的時候看一下。(僅針對本人)數組

 

參數數組

定義一個函數,用來取得數字的和,可是數字的個數不肯定。app

解決方案: 1,定義一個函數,參數傳遞過來一個數組; 2,定義一個參數個數不肯定的函數,這個時候咱們就要使用參數數組。ide

參數數組相比於數組參數的區別:params函數

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace _050_參數數組__定義一個參數個數不肯定的函數_ {
 8     class Program {
 9         //若是一個函數定義了參數,那麼在調用這個函數的時候,必定要傳遞對應類型的參數,不然沒法調用(編譯器編譯不經過)
10         static int Sum(int[] array)
11         {
12             int sum = 0;
13             for (int i = 0; i < array.Length; i++)
14             {
15                 sum += array[i];
16             }
17             return sum;
18         }
19 
20         //這裏定義了一個int類型的參數數組,參數數組和數組參數(上面的)的不一樣,
21         //在於函數的調用,調用參數數組的函數的時候,咱們能夠傳遞過來任意多個參數,
22         //而後編譯器會幫咱們自動組拼成一個數組,參數若是是上面的數組參數,那麼這個數組咱們本身去手動建立
23         static int Plus(params int[] array)
24         {
25             int sum = 0;
26             for (int i = 0; i < array.Length; i++) {
27                 sum += array[i];
28             }
29             return sum;
30         }
31         static void Main(string[] args)
32         {
33             int sum = Sum(new int[] {23, 4, 34, 32, 32, 42, 4});
34             Console.WriteLine(sum);
35             int sum2 = Plus(23, 4, 5, 5, 5, 32, 423, 42, 43,23,42,3);//參數數組就是幫咱們 減小了一個建立數組的過程 
36             Console.WriteLine(sum2);
37             Console.ReadKey();
38         }
39     }
40 }

 

 

委託

委託(delegate)是一種存儲函數引用的類型。this

委託的定義很簡單,聲明一個函數,而後在前面加上 delegate 關鍵字,這樣就聲明瞭一個委託spa

委託的使用分兩步:聲明,定義3d

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _053_委託的使用 {
    //定義一個委託跟函數差很少,區別在於
    //1,定義委託須要加上delegate關鍵字
    //2,委託的定義不須要函數體
    public delegate double MyDelegate(double param1, double param2);
    class Program {
        static double Multiply(double param1, double param2)
        {
            return param1*param2;
        }

        static double Divide(double param1, double param2)
        {
            return param1/param2;
        }
        static void Main(string[] args)
        {
            MyDelegate de;//利用咱們定義的委託類型聲明瞭一個新的變量 
            de = Multiply;//當咱們給一個委託的變量賦值的時候,返回值跟參數列表必須同樣,不然沒法賦值

            Console.WriteLine(de(2.0, 34.1));
            de = Divide;
            Console.WriteLine( de(2.0,34.1) );
            Console.ReadKey();
        }
    }
}

 Action委託:返回值爲void,參數能夠爲0個或多個   Action[<param...>] xxx = 某函數code

Func委託:有一個返回值,參數能夠爲0個或多個    Func<[param...],returnType> xxx = 某函數對象

多播委託:就是定義一個委託後,不止綁定某一個函數,使用+=,-=符號來添加刪除綁定的函數。要注意的是,多播委託中,中間若是某一個函數執行出錯,後面的都不會執行blog

 

委託的使用:好比要定義一個針對學生名及學生成績的排序(也多是其它狀況),之前的排序方法,須要咱們針對不一樣的狀況寫不一樣的排序方法。如今有了委託後,咱們能夠傳入一個類型不定的數組,傳入一個委託類型的排序方法,在這個排序方法中寫好排序就行。

 1 namespace _007_冒泡排序拓展 {
 2     class Employee {
 3         public string Name { get; private set; }
 4         public int Salary { get; private set; }
 5 
 6         public Employee(string name, int salary)
 7         {
 8             this.Name = name;
 9             this.Salary = salary;
10         }
11         //這裏定義了一個針對Employee的比較方法
12         public static bool Compare(Employee e1, Employee e2)
13         {
14             if (e1.Salary > e2.Salary) return true;
15             return false;
16         }
17 
18         public override string ToString()
19         {
20             return Name + ":" + Salary;
21         }
22     }
23 }
 1 namespace _007_冒泡排序拓展 {
 2     class Program {
       //這裏定義了一個通用的排序方法
3 static void CommonSort<T>(T[] sortArray, Func<T,T,bool> compareMethod) 4 { 5 bool swapped = true; 6 do { 7 swapped = false; 8 for (int i = 0; i < sortArray.Length - 1; i++) { 9 if (compareMethod(sortArray[i],sortArray[i+1])) { 10 T temp = sortArray[i]; 11 sortArray[i] = sortArray[i + 1]; 12 sortArray[i + 1] = temp; 13 swapped = true; 14 } 15 } 16 } while (swapped); 17 } 18 static void Main(string[] args) { 19 Employee[] employees = new Employee[] 20 { 21 new Employee("dsf",12), 22 new Employee("435dsf",234), 23 new Employee("234dsf",14), 24 new Employee("ds234f",234), 25 new Employee("dssfdf",90) 26 }; 27 CommonSort<Employee>(employees,Employee.Compare); 28 foreach (Employee em in employees) 29 { 30 Console.WriteLine(em); 31 } 32 Console.ReadKey(); 33 } 34 } 35 }

 

Lambda表達式:凡是能用委託表達的都能使用Lambda表達式來表達,反正式子中有這玩意"=>",也沒見用這玩意咋樣,還要難理解些,不用,誰用誰煞筆

 

事件:事件是基於委託的,有了委託纔會有事件。下面舉一個例子,有兩個類,丈夫和妻子,妻子類有個方法是看丈夫在玩遊戲沒,丈夫類有個方法是觀察妻子的動向。在以往的寫法中,每當妻子調用她的方法後,丈夫也要調用自身的方法,這樣在本例中還算好的,若是換成其它的一對多的關係,那麼代碼量會很大,且維護起來很麻煩。有了委託後(注意,這裏說的仍是委託,尚未用到事件),咱們在建立丈夫後,將丈夫的方法綁定到妻子的一個委託上,這樣妻子每次檢查時丈夫都會觀察到並執行相應函數。

 1 namespace ConsoleApp1
 2 {
 3     class Wife//妻子
 4     {
 5         //這裏聲明一個委託用來綁定丈夫的觀察函數
 6         public Action bindfunc;
 7         public void Coming()
 8         {
 9             Console.WriteLine("妻子:去看看老公在玩遊戲沒");
10             if(bindfunc != null)
11             {
12                 bindfunc();
13             }
14         }
15     }
16 }
 1 namespace ConsoleApp1
 2 {
 3     class Husband//丈夫
 4     {
 5         public Husband(Wife wife)
 6         {
 7             // 在構造丈夫的時候,就把自身的函數綁定到妻子的delegate上
 8             wife.bindfunc = See;
 9         }
10 
11         public void See()
12         {
13             Console.WriteLine("丈夫:盯到看到,媳婦來老");
14         }
15     }
16 }
 1 namespace ConsoleApp1
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             Wife wife = new Wife();
 8             Husband husband = new Husband(wife);
 9             wife.Coming();
10         }
11     }
12 }

 

嗯嗯,關於事件event,它就是把上面在妻子中聲明的委託  public Action bindfunc 改爲 public event Action bindfunc,就是加了個event表示而已,那它有啥做用呢。若是不用event標識,那妻子中的委託bindfunc咱們可使用妻子的實例隨手調用,用event聲明後,它就是一個事件,不能隨手用。

 

 

屬性

咱們習慣上把類中的字段設置爲私有的,這樣外接不可以修改字段的值,而後咱們經過定義屬性來設置和取得字段中的值

1 private int age;
2 public int Age
3 {
4     set{age = value;}
5     get{return age;}    
6 }

從上面能夠看到,屬性包含兩個塊,get塊和set塊。訪問屬性和訪問字段同樣,當取得屬性的值的時候,就會調用屬性中的get塊,因此get塊,當咱們去給屬性設置值的時候,就會調用屬性中的set塊

屬性須要注意的地方:

1:、另外,set塊和get塊能夠只提供一個(兩個都不提供也行,那至關於該屬性沒有用),若是隻提供set塊表示只寫,只提供get塊表示只讀

二、set塊和get塊能夠設置爲私有的,設置爲私有的塊只能在類的內部訪問(固然該屬性也能夠設置爲私有,這樣該屬性只能在類的內部使用)

1 public string name
2 {
3     private set{name = value;}
4     get{return name;}
5 }

三、咱們也能夠不用建立字段,直接設置屬性,這樣編譯器會幫咱們自動建立

1 public int Age{get;set;}

四、屬性相對於之前單首創建函數來設置和獲取字段值,不一樣是它能夠在設置的時候,作一些須要的操做,好比判斷

1 public int Age
2 {
3      set
4     {
5          if(value > 0)
6             age = value;   
7     }  
8 }

 

 

虛方法和隱藏方法

虛方法:在父類中使用virtual關鍵字聲明函數,在子類中使用override關鍵字聲明該函數

隱藏方法:不適用virtual關鍵字和override關鍵字聲明

定義2個類,Enemy和Boss,Boss繼承自Enemy

 1 class Enemy
 2 {
 3     public void Run()
 4     {
 5         print("父類Run");
 6     }
 7     public virtual void Eat()
 8     {
 9         print("父類Eat");
10     }
11 }
 1 class Boss:Enemy
 2 {
 3     public void Run()
 4     {
 5         print("子類Run");
 6     }
 7     public override void Eat()
 8     {
 9         print("子類Eat");
10     }
11 }
 1 class Test
 2 {
 3     static void Main(string[] args) {
 4         Enemy e1 = new Boss();
 5         e1.Run();    //父類Run
 6         e1.Eat();    //子類Eat
 7         
 8         Boss b1 = new Boss();
 9         b1.Run();    //子類Run
10         b1.Eat();    //子類Eat
11     }
12 }

能夠看到,若是是隱藏方法,那麼若是使用父類聲明子對象,調用的方法仍是父類的方法。由於,隱藏方法只是隱藏,父類中的方法還在。

若是是虛方法,那麼調用後都是執行子類中的代碼。由於,虛方法重寫後父類中的方法就不存在了。

使用虛方法還有一個重要的做用,那就是當聲明一個函數的時候,若是當時並不知道具體的實現,只知道之後子類會用到它,那麼咱們能夠先把它聲明爲虛方法,等着之後子類去實現。

 1 class Test
 2 {
 3     public void Use()
 4     {
 5         UseThis();
 6     }
 7     public virtual void UseThis()
 8     {
 9     }
10 }

 

 

抽象類

抽象類其實和前邊說的虛方法有關。虛方法中,用virtual關鍵字聲明後,在子類中能夠重寫也能夠不重寫。抽象類使用abstract關鍵字聲明函數(注意:函數使用abstract聲明後,那麼類自動稱爲抽象類,也須要使用abstract聲明,編譯器會提示的),子類中必須使用關鍵字override實現該函數。

注意,抽象類能夠聲明子類對象,可是不能直接使用抽象類實例化對象。

1 abstract class Test
2 {
3     public abstract void Use();
4 }

 

 

接口

接口是特殊的抽象類,在抽象類中能夠定義字段和普通的方法,可是在接口中只能定義方法,且不容許提供接口中任何成員的實現方式,不容許聲明成員修飾符,接口中的成員都是共有的。

說白了,接口中就是聲明瞭一些公有方法,讓繼承該接口的子類本身去實現。

1 public interface Test
2 {
3     public void Use();
4     public void Do();
5     ...
6 }
相關文章
相關標籤/搜索