.NET基礎學習(委托)


最近學習C#基礎,特此做筆記,請不要

委托和類一樣,是一種用戶自定義的類型。類表示的是數據的集合,而委托保存的是一個或多個方法。

1、申明委托類型

delegate void MyDel(int x)

上面代碼申明了MyDel類型的委托,指明了這種類型的委托只會接受不返回值並且只有單個int參數的方法。

2、創建委托對象

委托是引用類型,因此有引用和對象。在委托類型申明之后,我們可以申明變量並創建類型的對象。

class del
{
public del()
{
MyDel delVar = new MyDel(b.GetB);//實例方法,創建委托並保存引用
}
delegate void MyDel(int x);//申明委托類型
B b = new B();
MyDel dVar = new MyDel(B.GetA);//實例方法,創建委托並保存引用
}

public class B
{
static public void GetA(int y)
{
Console.WriteLine("靜態方法!輸出值為:" + y);
}
public void GetB(int z)
{
Console.WriteLine("成員方法!輸出值為:" + z);
}
}

上面代碼創建了2個委托對象,一個具有實例方法,一個具有靜態方法。b為類B的對象,它有一個叫做GetB實例方法,該方法接收一個int類型的參數,不返回值;B類有一個GetA靜態方法,該方法具有與MyDel委托想匹配的返回類型和簽名。

3、賦值托管

MyDel delVar;
delVar=b.GetB;//創建並給委托對象賦值
……
delVar=B.GetA;//創建並給新的委托對象賦值

由於委托是引用類型,我們可以通過給它賦值來改變包含在委托變量中的引用,舊的委托對象會被垃圾回收器回收。

4、組合委托

MyDel delA=A.GetA;
MyDel delB=B.GetB;
MyDel delC=delA+delB;//組合調用列表

盡管術語組合委托讓我們覺得好像操作委托被修改了,其實它們並沒有被修改。事實上,委托是恆定的,委托被創建后不會再被改變。

5、為委托增加方法

MyDel delVar=A.GetA;//創建並初始化
delVar+=B.GetB;//增加方法
delVar+=C.GetC;//增加方法

委托是不可變的,所以委托的調用列表增加3個方法后的結果其實是變量指向一個全新的委托。

6、從委托移除方法

delVar-=C.GetC;//從委托移除方法

與為委托增加方法一樣,其實是創建了一個新的委托,新委托是就委托的一個副本,只是沒有了已移除方法的引用。

1.如果在調用列表中的方法有多個實例,-=運算符將從列表最后開始搜索,並且移除第一個與方法匹配的實例。

2.試圖刪除委托中不存在的方法沒有結果。

3.視圖調用空委托會拋出異常。

4.如果調用列表為空,則委托是null。

7、調用委托

 delegate void printFunction();//定義一個沒有返回值和參數的委托類型
class Program
{
static void Main(string[] args)
{
Test t = new Test();//創建測試類實例
printFunction pf;//創建一個空委托
pf = t.Print1;//實例化並初始化該委托
//給委托增加3個另外的方法
pf += Test.Print2;
pf += t.Print1;
pf += Test.Print2;
if (null != pf)//確認委托有方法
pf();//調用委托
else
Console.WriteLine("Delegage is empty");
}
}
class Test
{
public void Print1()
{ Console.WriteLine("Print1--instance"); }
static public void Print2()
{ Console.WriteLine("Print2--static"); }
}

Test類定義了兩個打印函數,一個是實例成員函數一個是靜態成員函數,在調用委托之前,檢測是否為null,程序打印結果如下圖

8、調用帶返回值的委托

如果委托有返回值並且在調用列表中有一個以上的方法,調用列表中最后一個方法返回的值就是委托調用返回的值,調用列表中所有其他方法的返回值都會被忽略。

 delegate int Add();//定義一個有回值和無參數的委托類型
class Program
{
static void Main(string[] args)
{
Test t = new Test();//創建測試類實例
Add add = t.Add1;
add += t.Add2;
add += t.Add1;
Console.WriteLine(add());
}
}
class Test
{
int val = 5;
public int Add1()
{ val += 2; return val; }
public int Add2()
{ val += 3; return val; }
}

add();->Add1();返回值7被忽略->Add2();返回值10被忽略->Add1();使用,返回值為12

上面代碼申明了返回int值的委托,然后調用委托打印出值,運行結果如圖所示:

9、調用帶引用參數的委托

如果委托有引用參數,參數值會根據調用列表的的一個或者多個方法的返回值而改變。

在調用委托列表下的方法時,參數的新值(不是初始值)會傳給下一個方法。

delegate void MyDel(ref int x);//定義一個有回值和無參數的委托類型
class Program
{
public void Add1(ref int x) { x += 2; }
public void Add2(ref int x) { x += 3; }
static void Main(string[] args)
{
Program p=new Program();
MyDel mDel = p.Add1;
mDel += p.Add2;
mDel += p.Add1;
int x = 5;
mDel(ref x);
Console.WriteLine(x);
}
}

mDel();->Add1(X=5);引用x的初始值->Add2(X=7);引用x新的輸入值->Add1(x=10);引用x的新的輸入值

打印如圖所示:

10、匿名方法

匿名方法:是子初始化委托時內聯申明的方法。

delegate int MyDel(int x);//定義一個有回值和無參數的委托類型
class Program
{
static void Main(string[] args)
{
MyDel del = delegate(int x)
{
return x += 20;
};
Console.WriteLine(del(123));
Console.WriteLine(del(1234));
}
}

如果匿名方法申明的參數列表中包含了params參數,那么parmas關鍵字就會被匿名方法的參數列表忽略

delegate int MyDel(int x,params int[] y);//定義一個有回值和參數的委托類型
class Program
{
static void Main(string[] args)
{
MyDel del = delegate(int x,int[] y)
{
return x + y.Length;
};
Console.WriteLine(del(1,1,2,3,4));
}
}

打印結果如下圖示:

11、Lambda表達式

在匿名方法的語法中,delegate關鍵字是有點多余的,因為編譯器已經知道我們將在方法賦值給委托,下面把匿名方法轉換為lambda表達式

 delegate int MyDel(int x);
class Program
{
static void Main(string[] args)
{
MyDel del = delegate(int x) { return x + 1; };//匿名函數
MyDel del1 = (int x) => { return x + 1; };//lambad表達式
MyDel del2 = (x) => { return x + 1; };
MyDel del3 = x => { return x + 1; };
MyDel del4 = x => x + 1;
Console.WriteLine(del(12));
Console.WriteLine(del1(12));
Console.WriteLine(del2(12));
Console.WriteLine(del3(12));
Console.WriteLine(del4(12));
}
}

版權所有,轉載請注明出處!

一切偉大的行動和思想,都有一個微不足道的開始。微不足道的我,正在吸取知識的土壤,希望能取得成功!不嫌棄我微不足道的,願交天下好友!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM