最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#中的委托數(shù)據(jù)類型簡介

 更新時間:2016年03月17日 11:00:13   作者:崎嶇行者  
委托是一個類型安全的對象,它指向程序中另一個以后會被調(diào)用的方法(或多個方法)。通過本文給大家介紹C#中的委托數(shù)據(jù)類型簡介,對c委托類型相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧

什么是委托?

委托是一個類型安全的對象,它指向程序中另一個以后會被調(diào)用的方法(或多個方法)。通俗的說,委托是一個可以引用方法的對象,當(dāng)創(chuàng)建一個委托,也就創(chuàng)建一個引用方法的對象,進(jìn)而就可以調(diào)用那個方法,即委托可以調(diào)用它所指的方法。

來看下面的例子,類deleMthod定義了3個方法,add、minus和multi,他們都具有相同的輸入?yún)?shù)列表(int x,int y)和輸出參數(shù)類型int,那么我們就說這三個方法具有相同的方法簽名。開發(fā)者可以抽象地用 int 某名稱(int x,int y) 的一種類型對方法進(jìn)行封裝,在c#中這種抽象的數(shù)據(jù)類型叫委托,針對上述的幾個方法我們可以定義委托 : public delegate int Handler(int x ,int y),public 是一個訪問修飾符,delegate關(guān)鍵字表示這是一個委托,int Hander(int x,int y)表示這個委托的名稱。

class deleMethod
{
public int add(int x, int y)
{
return x + y;
}
public int minus(int x, int y)
{
return x - y;
}
public int multi(int x, int y)
{
return x * y;
}
}

怎么使用委托

使用委托大體有四個步驟:

•定義一個委托,上節(jié)已經(jīng)提及。

•定義委托方法,上節(jié)deleMethod類中add、minus、multi都是委托方法,定義的目的就是為了使用它,講專業(yè)點就是為了方法的調(diào)用

•委托變量及賦值,和類型一樣,在使用前需要對變量賦值。

•委托變量的使用。

怎樣定義委托變量,還是接著上面的例子。我們已經(jīng)定義了一個委托類型 public delegate int Handler(int x,int y),和c#語法規(guī)范一樣定義一個變量并賦值語法是:“類型名 變量名 = new 類型名(方法);”,如上例

“Handler deleCall = new Handler(方法名);“,在.net2.0后對于委托的實例化可以簡化為” Handler deleCall = 方法名;“。

委托變量的使用,也就是對委托方法的調(diào)用。其語法是”int result1 = deleCall(10,20);“或者使用委托調(diào)用方法 Invoke,“int result2 = deleCall.Invoke(10,20);”。

具體如何使用可以看看下面的示例:

class Program
{
public delegate int Handler(int x, int y); //---定義委托的類型,可以將委托看成一種特殊的數(shù)據(jù)類型
static void Main(string[] args)
{ 
deleMethod dm = new deleMethod(); //---實例化包含委托方法的類型
Handler deleCall = new Handler(dm.add); //---定義委托變量delCall,并出示化賦值
int result1 = deleCall(10, 20); //---實例方法的調(diào)用invoke
Console.WriteLine("the add resutl is:{0}", result1);
deleCall = dm.minus;
int result2 = deleCall.Invoke(12, 6);
Console.WriteLine("the minus result is:{0}", result2);
Console.ReadLine();
}
} 

如上例所示,定義一個簡單的加、減功能如此的復(fù)雜,攪來攪去讓人頭,真是無語,難怪很多朋友談委托色變暈。在實際使用的過程中,c#還是有很多方式幫我們簡化代碼。

簡化委托

預(yù)定義的泛型委托

c#系統(tǒng)最常見的預(yù)定義的委托類型有三種,F(xiàn)unc<>委托、Action<>委托、Predicate<>委托,F(xiàn)unc<>委托是一個有返回值的委托,輸入?yún)?shù)可以多達(dá)16個;而Action<>委托是一個沒有返回值的委托,它的輸入?yún)?shù)也可以多達(dá)16個;而Predicate<>是一個具有bool返回類型的委托,它只運行一個輸入?yún)?shù)。對于有上例的委托類型,我們可以使用預(yù)定義的委托類型Fun<int,int,int>來代替,省去我們自己定義一個什么鬼東西 public delegate int Handler(int x,int y)類型,其代碼其實可以簡化為如下例所示:

namespace DelegateDemo1
{
class Program
{
static void Main(string[] args)
{
deleMethod dm = new deleMethod();
Func<int, int, int> fun = dm.add; //---使用預(yù)定義的委托類型Func<>
int result4 = fun(8, 10);
Func<int, int, int> fun1 = dm.minus;
int result5 = fun1(12, 8);
Console.WriteLine("預(yù)定義的委托輸出{0},{1}", result4, result5);
Console.ReadLine();
}
}
class deleMethod
{
public int add(int x, int y)
{
return x + y;
}
public int minus(int x, int y)
{
return x - y;
}
public int multi(int x, int y)
{
return x * y;
}
}
}

我把委托的方法定義和委托的調(diào)用放在一起看,是不是比原先自己定義的一個委托類型簡單方便一些?但是這樣使用委托還是不怎么清爽,估計在實際應(yīng)用中很少人會怎么寫代碼,太不方便了。

匿名委托

當(dāng)委托實例的調(diào)用和委托方法的定義分開處理,碼農(nóng)們在讀程序代碼的時候需要來回的去找委托方法去匹配委托變量,看看參數(shù)列表和返回值是否正確,這樣的程序代碼的可讀性很差。其實c#還是有方法讓我們簡化代碼:那就是匿名委托,將方法體直接在委托的實例化時給出,之所以叫匿名委托就是再定義委托的時候省略掉委托的名稱,它的定義語法是delegate(參數(shù)1,參數(shù)2) 后面直接就給出方法體,用大括號將方法體括起。剛看起來比較怪異,接觸多了也就習(xí)慣了,莫有辦法只能去適應(yīng)c#的語法規(guī)范。話說多了是水,還不如看代碼來得直接。

namespace DelegateDemo1
{
class Program
{
static void Main(string[] args)
{
Func<int, int, int> fun = delegate(int x, int y) { return x + y; };
Func<int, int, int> fun1 = delegate(int x, int y) { return x - y; };
int result4 = fun(8, 10);
int result5 = fun1(12, 8);
Console.WriteLine("預(yù)定義的委托輸出{0},{1}", result4, result5);
Console.ReadLine();
}
}
} 

看看是不是在原來的基礎(chǔ)上大幅度減少了代碼量,腫么辦,是否代碼量已經(jīng)減少到極致了?

lambda表達(dá)式

其實對于委托的定義還可以進(jìn)一步簡化,那就是使用lambda表達(dá)式,lambda表達(dá)式的定義是(參數(shù)列表)=>{方法體},=>讀作goes to。lambda表達(dá)式對參數(shù)列表和方法表達(dá)式的精簡達(dá)到極致,對于上面的例子,用λ表達(dá)式可以省略掉匿名委托的關(guān)鍵字和參數(shù)類型,系統(tǒng)可以進(jìn)行類型推斷,不影響運行,其簡化的代碼如下。對.net 1.0,2.0最傳統(tǒng)的委托定義和使用,是一個巨大的簡化,它剔除了所有多余的語句達(dá)到極致。

namespace DelegateDemo1
{
class Program
{
static void Main(string[] args)
{
Func<int, int, int> fun = (x, y) => x + y;
Func<int, int, int> fun1 = (x, y) => x - y; 
int result4 = fun(8, 10);
int result5 = fun1(12, 8);
Console.WriteLine("預(yù)定義的委托輸出{0},{1}", result4, result5);
Console.ReadLine();
}
}
} 

委托鏈

前面講過,委托在本質(zhì)上仍然是一個類,我們用delegate關(guān)鍵字聲明的所有委托都繼承自System.MulticastDelegate。后者又是繼承自System.Delegate類,System.Delegate類則繼承自System.Object。一個委托可以綁定若干相同簽名的方法形成一個委托鏈,委托鏈?zhǔn)且粋€委托實例的集合,它允許我們調(diào)用這個集合中的委托實例所代表的所有方法(對于有返回值的方法,委托鏈的返回值為鏈表中最后一個方法的返回值),在下面的例子我們定義的委托方法都沒有返回值。我們可以用 GetInvocationList()方法獲取委托鏈。

class Program
{
static void Main(string[] args)
{
//Action 表示沒有返回值的一類方法
Action<int, int> actionA = (x, y) =>
{
Console.WriteLine("x是{0},y是{1},他們的平方和是{2}", x, y, x * x + y * y);
};
actionA += (x, y) =>
{
Console.WriteLine("x是{0},y是{1},他們的平方差是{2}", x, y, x * x - y * y);
};
actionA(10, 5); 
foreach (var item in actionA.GetInvocationList())
Console.WriteLine(item.Method);
Console.ReadLine();
}
} 

什么是事件

經(jīng)??吹揭环N定義是:事件是一種特殊的委托,是對委托的封裝。其實這種定義是很不嚴(yán)謹(jǐn)?shù)?。委托是一種數(shù)據(jù)類型,但是事件只是委托的實例,不能算是一種數(shù)據(jù)類型,所以說事件是一種特殊的委托是不準(zhǔn)確的。如果這樣定義:事件是一種特殊的委托實例,是對委托的封裝。那么在C#中事件是如何定義并被使用的呢?其實事件從定義到使用要經(jīng)過四個階段。

•定義事件依賴的委托,并定義事件以及引發(fā)事件的方法,該步驟可以定義在事件發(fā)布器類中

•定義事件所依賴的事件方法,該步驟可以定義在事件訂閱者類中

•如果有事件參數(shù),該步驟可以定義在事件參數(shù)類中

•注冊事件并引發(fā)事件,該步驟一般寫在主程序中

一般來講在事件定義過程中,各個方法的命名沒有統(tǒng)一的標(biāo)準(zhǔn),但我們可以參考微軟在c#中的命名規(guī)范進(jìn)行命名

建議事件委托命名為:事件+EventHandler。如果有額外的參數(shù)傳遞需定義自己的參數(shù)類型,參數(shù)類型的命名規(guī)范 :事件+EventHandler。比如,可以定義一個事件委托 public delegate void calcEventHandler(object sender,calcEventArgs e); 。

定義一個事件變量如:public event calcEventHandler calc;

定義一個引發(fā)事件的方法如:public void onCalc(object sender,calcEventArgs e){}

建議方法名為 on+事件,就如同我們在開發(fā)web程序時,綁定的事件名有onClick,onLoad等一樣。

參考看下面的例子,了解定義一個事件的一般過程,如果不需要傳遞事件的參數(shù)可以省去事件參數(shù)類的定義,使用系統(tǒng)預(yù)定義的EventArgs就可以了。

/// <summary>
/// 主程序類
/// </summary>
class Program
{
static void Main(string[] args)
{
eventPublish myEvent = new eventPublish();
eventSubscription myMethod = new eventSubscription();
//綁定方法 add 和 subtract,又稱為對事件方法的注冊 -=稱為對事件方法的注銷
myEvent.calc += myMethod.add;
myEvent.calc += myMethod.substract;
while (true)
{
try
{
Console.WriteLine("請輸入第一個整數(shù)數(shù)");
int numA = Convert.ToInt16(Console.ReadLine());
Console.WriteLine("請輸入第二個整數(shù)");
int numB = Convert.ToInt16(Console.ReadLine());
calcEventArgs e = new calcEventArgs(numA, numB);
//在本例不需要sender參數(shù),隨意傳遞了字符串"sender"
myEvent.onCalc("sender", e); 
}
catch (Exception ex)
{
Console.WriteLine("出現(xiàn)錯誤," + ex.Message);
}
}
}
}
/// <summary>
/// 定義一個事件發(fā)布器類
/// </summary>
class eventPublish
{
//定義一個委托類型,委托名一般是 事件變量名+EventHandler
public delegate void calcEventHander(object sender,calcEventArgs e);
//定義一個事件變量,其變量名為calc
public event calcEventHander calc;
//封裝事件,對外定義了引發(fā)事件的方法,定義的引發(fā)方法名一般是 on+事件變量名
public void onCalc(object sender, calcEventArgs e)
{
if (calc != null)
calc(sender,e);
}
}
/// <summary>
/// 定義一個事件訂閱者類(事件方法類)
/// </summary>
class eventSubscription
{
public void add(object sender, calcEventArgs e)
{
Console.WriteLine("兩數(shù)相加等于{0}", e.X + e.Y );
}
public void substract(object sender, calcEventArgs e)
{
Console.WriteLine("兩數(shù)相減等于{0}", e.X - e.Y);
}
}
/// <summary>
/// 定義一個事件參數(shù)類
/// </summary>
class calcEventArgs : EventArgs
{
private int _x;
private int _y;
public calcEventArgs(int x, int y)
{
this._x = x;
this._y = y;
}
public int X
{
get { return _x; }
}
public int Y
{
get { return _y; }
}
}

我們將事件是對委托的封裝,如果用ILDAS反編譯可執(zhí)行文件查看中間代碼就可以非常明了的看出事件運行機(jī)制


如上圖所示,事件calc,經(jīng).net運行時編譯為中間語言后產(chǎn)生了一個private 的calc屬性,同時也自動生成了add_calc和remove_calc方法,用于注冊和注銷訂閱者方法。因為事件是被封裝的,盡管calc屬性是private,但在所以在發(fā)布器類內(nèi)部可以用 calc(sender,e)這樣的方法直接調(diào)用;但在主程序中如果這樣使用就會出錯,只能通過onCalc方法進(jìn)行間接調(diào)用。

后記

  本篇文章,一開始提出了什么是委托的疑問,通過引入幾個方法來講述委托是什么以加強(qiáng)對委托概念的理解。第二部分講述了使用委托的四個步驟,并通過示例闡述了這幾個步驟。第三部分講述了委托使用的簡化問題,通過使用泛型委托簡化自定義委托,通過使用匿名委托可以簡化定義委托方法。匿名委托是在定義委托的時候直接給出方法體,通過使用lambda表達(dá)式的類型推斷可進(jìn)一步簡化委托的使用。第四部分講述了委托鏈,通過綁定方法初始化委托,并通過+=綁定更多的委托方法。第五部分講述了事件的定義和使用的四個步驟。當(dāng)然委托的使用場景還有很多,比如通過BeginInvoke和EndInvoke進(jìn)行異步調(diào)用,因不是本篇文章的重點,所以文章中沒有提及。

以上內(nèi)容是小編給大家介紹的C#中的委托數(shù)據(jù)類型簡介,希望對大家有所幫助!

相關(guān)文章

  • C#中類的異常處理詳解

    C#中類的異常處理詳解

    大家好,本篇文章主要講的是C#中類的異常處理詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-02-02
  • WPF的ListView控件自定義布局用法實例

    WPF的ListView控件自定義布局用法實例

    這篇文章主要介紹了WPF的ListView控件自定義布局的方法,結(jié)合實例形式分析了WPF中ListView控件的布局方法,需要的朋友可以參考下
    2016-07-07
  • C#開發(fā)紐曼USB來電小秘書客戶端總結(jié)

    C#開發(fā)紐曼USB來電小秘書客戶端總結(jié)

    這篇文章主要介紹了C#開發(fā)紐曼USB來電小秘書客戶端總結(jié),對于C#項目開發(fā)來說有一定的參考借鑒價值,需要的朋友可以參考下
    2014-08-08
  • c# 使用異步編程的方法

    c# 使用異步編程的方法

    這篇文章主要介紹了c# 使用異步編程的方法,文中講解非常細(xì)致,幫助大家更好的理解c# 異步編程,感興趣的朋友可以了解下
    2020-08-08
  • C#實現(xiàn)windows form拷貝內(nèi)容到剪貼板的方法

    C#實現(xiàn)windows form拷貝內(nèi)容到剪貼板的方法

    這篇文章主要介紹了C#實現(xiàn)windows form拷貝內(nèi)容到剪貼板的方法,涉及C#操作Clipboard的相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • C# WinForm中禁止改變窗口大小的方法

    C# WinForm中禁止改變窗口大小的方法

    這篇文章主要介紹了C# WinForm中禁止改變窗口大小的方法,需要把FormBorderStyle和MaximizeBox的值固定即可,需要的朋友可以參考下
    2014-08-08
  • C#?異步多線程入門到精通之Thread篇

    C#?異步多線程入門到精通之Thread篇

    Thread?是?1.0?時代的產(chǎn)物,當(dāng)時?C#?就考慮到了多線程,于是就設(shè)計了?Thread?。其實現(xiàn)在不推薦使用,除非在維護(hù)老的項目已經(jīng)用了的。Thread?也是比較雞肋的,有很多缺陷,但也并不是一無是處
    2021-11-11
  • C#中重載與重寫區(qū)別分析

    C#中重載與重寫區(qū)別分析

    這篇文章主要為大家詳細(xì)介紹了C#中重載與重寫的區(qū)別,感興趣的小伙伴們可以參考一下
    2016-02-02
  • C# winform實現(xiàn)登陸次數(shù)限制

    C# winform實現(xiàn)登陸次數(shù)限制

    這篇文章主要介紹了C# winform實現(xiàn)登陸次數(shù)限制,相信大家都遇到過網(wǎng)站在用戶多次輸錯密碼之后會自動把賬戶凍結(jié)的情況,這種功能如何實現(xiàn),下面小編為大家分享實現(xiàn)方法
    2016-05-05
  • 詳解C#應(yīng)用程序如何實現(xiàn)多屏顯示

    詳解C#應(yīng)用程序如何實現(xiàn)多屏顯示

    這篇文章主要為大家詳細(xì)介紹了C#如何實現(xiàn)把主屏運行程序中多個窗體移動到各個擴(kuò)展屏幕位置顯示,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-05-05

最新評論

榆社县| 北碚区| 湘阴县| 邢台县| 射阳县| 绩溪县| 仁寿县| 都江堰市| 正宁县| 玉龙| 济南市| 南华县| 三亚市| 兴义市| 新丰县| 慈利县| 池州市| 湘潭县| 莱芜市| 新邵县| 调兵山市| 关岭| 饶平县| 莱阳市| 朔州市| 剑川县| 新余市| 安达市| 四会市| 沙田区| 禹城市| 三穗县| 五大连池市| 湄潭县| 邮箱| 惠州市| 报价| 临武县| 平山县| 颍上县| 元江|