欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報(bào)激活碼778899分享:開發(fā)語言 C# 委托

柚子快報(bào)激活碼778899分享:開發(fā)語言 C# 委托

http://yzkb.51969.com/

文章目錄

1. Delegate 委托委托 vs 接口事件模式 / 委托模式委托組合委托中的協(xié)變和逆變

2. Func & Action 委托對Func和Action泛型委托使用變體Func 與 Action 中異常處理

3. 其他委托:Predicate & Comparison & Converter

1. Delegate 委托

在C#中,委托是一種引用類型,表示對具有特定參數(shù)列表和返回類型的方法的引用,即委托就是一種用來指向一個(gè)方法的類型變量,可以通過委托實(shí)例調(diào)用方法,關(guān)鍵字是 delegate。

// 聲明一個(gè)委托

public delegate void MyDelegate(string message);

public class Program

{

static void Main(string[] args)

{

// 創(chuàng)建委托實(shí)例,綁定到具體的方法

MyDelegate myDelegate = new MyDelegate(DisplayMessage);

// 使用委托

myDelegate("Hello, World!");

}

// 與委托具有相同簽名的方法

static void DisplayMessage(string message)

{

Console.WriteLine(message);

}

}

現(xiàn)在我們可以更簡單的方式使用委托:

public class Program

{

static void Main(string[] args)

{

MyDelegate myDelegate = message => Console.WriteLine(message);

myDelegate("Hello, World!");

}

}

委托 vs 接口

委托和接口是不是感覺很類似?都是分離類型的聲明和實(shí)現(xiàn),且都可以由不了解實(shí)現(xiàn)該接口或委托的類對象使用,那么這兩個(gè)使用場景有什么區(qū)別呢?

C# 官方給出的建議, 以下情況請使用委托:(后面 事件模式/委托模式 舉例說明)

當(dāng)使用事件設(shè)計(jì)模式時(shí)當(dāng)封裝靜態(tài)方法可取時(shí)當(dāng)調(diào)用方不需要訪問實(shí)現(xiàn)該方法的對象中的其他屬性、方法或接口時(shí)需要方便的組合當(dāng)類可能需要該方法的多個(gè)實(shí)現(xiàn)時(shí)

以下情況請使用接口:

當(dāng)存在一組可能被調(diào)用的相關(guān)方法時(shí)當(dāng)類只需要方法的單個(gè)實(shí)現(xiàn)時(shí)當(dāng)使用接口的類想要將該接口強(qiáng)制轉(zhuǎn)換為其它接口或類類型時(shí)當(dāng)正在實(shí)現(xiàn)的方法鏈接到類的類型或標(biāo)識(shí)時(shí),例如比較方法

事件模式 / 委托模式

也可能翻譯有偏差,并沒有搜索到事件設(shè)計(jì)模式(eventing design pattern)。我們說的委托模式,是否可以認(rèn)為是這里指的事件設(shè)計(jì)模式? 委托模式解耦了委托者與被委托者,同時(shí)又需要委托者與被委托者協(xié)同完成同一個(gè)事件。

如下代碼示例,#1 事件模式時(shí),委托者即事件發(fā)布類(publisher),被委托者即訂閱類(subscriber),同時(shí)由于**#5 訂閱類的多樣性**,對于同一事件會(huì)有不同的訂閱處理,且**#3 委托者只需要發(fā)布事件,而不需要關(guān)心訂閱者任何其他細(xì)節(jié)**:

interface ISubscriber

{

// 事件處理程序

public void HandleSimpleEvent(object sender, EventArgs e);

}

public abstract class BaseSubscriber : ISubscriber

{

public void Subscribe(SimplePublisher publisher)

{

publisher.SimpleEvent += HandleSimpleEvent;

}

public abstract void HandleSimpleEvent(object sender, EventArgs e);

}

// 訂閱事件類1

public class SimpleSubscriber : BaseSubscriber

{

public override void HandleSimpleEvent(object sender, EventArgs e)

{

Console.WriteLine("SimpleEvent is raised.");

}

}

// 訂閱事件類2

public class ComplexSubscriber : BaseSubscriber

{

public override void HandleSimpleEvent(object sender, EventArgs e)

{

Console.WriteLine("Do complex work in ComplexSubscriber.");

Console.WriteLine("ComplexEvent is raised.");

}

}

public class SimplePublisher

{

// 定義委托類型

public delegate void EventHandler(object sender, EventArgs e);

// 定義事件

public event EventHandler SimpleEvent;

// 觸發(fā)事件的方法

public void RaiseEvent()

{

// 事件可能為null,所以先檢查

EventHandler handler = SimpleEvent;

if (handler != null)

{

handler(this, EventArgs.Empty);

}

}

}

// 使用示例

public class Program

{

public static void Main()

{

var subscribers = GetAllSubscribers();

if (!subscribers.Any())

{

Console.WriteLine("No subscriber found!");

return;

}

SimplePublisher publisher = new SimplePublisher();

foreach (var subscriber in subscribers)

{

subscriber.Subscribe(publisher);

// 觸發(fā)事件

publisher.RaiseEvent();

}

}

// 通過反射獲取所有訂閱者

private static List GetAllSubscribers()

{

var pluginTypes = Assembly.GetExecutingAssembly().GetTypes()

.Where(t => t.IsClass && !t.IsAbstract && typeof(BaseSubscriber).IsAssignableFrom(t));

List subscribers = new List();

foreach (var pluginType in pluginTypes)

{

var instance = Activator.CreateInstance(pluginType) as BaseSubscriber;

if (instance != null)

{

subscribers.Add(instance);

}

}

return subscribers;

}

}

}

------------------Output-----------------------

Do complex work in ComplexSubscriber.

ComplexEvent is raised.

SimpleEvent is raised.

委托組合

c# 允許我們用 + 將多個(gè)委托組合成一個(gè)新的委托,組合的委托可以調(diào)用組成它的所有委托,但是注意,只有相同類型的委托才可以組合。運(yùn)算符 - 可以從組合的委托中移除某個(gè)委托。

delegate void Del(string s);

class TestClass

{

static void Hello(string s)

{

System.Console.WriteLine(" Hello, {0}!", s);

}

static void Goodbye(string s)

{

System.Console.WriteLine(" Goodbye, {0}!", s);

}

static void Main()

{

Del a, b, c, d;

// Create the delegate object a that references

// the method Hello:

a = Hello;

// Create the delegate object b that references

// the method Goodbye:

b = Goodbye;

// The two delegates, a and b, are composed to form c:

c = a + b;

// Remove a from the composed delegate, leaving d,

// which calls only the method Goodbye:

d = c - a;

System.Console.WriteLine("Invoking delegate a:");

a("A");

System.Console.WriteLine("Invoking delegate b:");

b("B");

System.Console.WriteLine("Invoking delegate c:");

c("C");

System.Console.WriteLine("Invoking delegate d:");

d("D");

}

}

/* Output:

Invoking delegate a:

Hello, A!

Invoking delegate b:

Goodbye, B!

Invoking delegate c:

Hello, C!

Goodbye, C!

Invoking delegate d:

Goodbye, D!

*/

委托中的協(xié)變和逆變

協(xié)變:下面官方示例種 Dogs 集成 Mammals,所以 DogsHandler 可以分配給 HandlerMethod 委托。

class Mammals {}

class Dogs : Mammals {}

class Program

{

// Define the delegate.

public delegate Mammals HandlerMethod();

public static Mammals MammalsHandler()

{

return null;

}

public static Dogs DogsHandler()

{

return null;

}

static void Test()

{

HandlerMethod handlerMammals = MammalsHandler;

// Covariance enables this assignment.

HandlerMethod handlerDogs = DogsHandler;

}

}

逆變:逆變可以使用一個(gè)事件處理程序而不是多個(gè)單獨(dú)的處理程序,如下 MultiHandler 中的第二個(gè)參數(shù) System.EventArgs 是 KeyEventhandler 和 MouseEventHandler 的基類,因此這兩個(gè)委托都可以作為MultiHandler 入?yún)ⅰ?/p>

public delegate void KeyEventHandler(object sender, KeyEventArgs e);

public delegate void MouseEventHandler(object sender, MouseEventArgs e);

// Event handler that accepts a parameter of the EventArgs type.

private void MultiHandler(object sender, System.EventArgs e)

{

label1.Text = System.DateTime.Now.ToString();

}

public Form1()

{

InitializeComponent();

// You can use a method that has an EventArgs parameter,

// although the event expects the KeyEventArgs parameter.

this.button1.KeyDown += this.MultiHandler;

// You can use the same method

// for an event that expects the MouseEventArgs parameter.

this.button1.MouseClick += this.MultiHandler;

}

2. Func & Action 委托

Func 是接受任意數(shù)量的參數(shù)并且有返回值的委托.

public delegate TResult Func();

// Func 的 TResult前可以定義任意多個(gè)入?yún)?T1, T2 ... ...

public delegate TResult Func(T arg);

Action 是接受任意數(shù)量的參數(shù)且沒有返回值的委托。

public delegate void Action(T obj);

對Func和Action泛型委托使用變體

這里給出官方示例,使用具有協(xié)變類型參數(shù)的委托:當(dāng)一個(gè)方法的返回值類型 TResult 繼承了某個(gè)類A,那么就可以將這個(gè)方法分配給 Func / Func 委托。

// Simple hierarchy of classes.

public class Person { }

public class Employee : Person { }

class Program

{

static Employee FindByTitle(String title)

{

return new Employee();

}

static void Test()

{

Func findEmployee = FindByTitle;

Func findPerson = FindByTitle;

findPerson = findEmployee;

}

}

使用具有逆變類型參數(shù)的委托

public class Person { }

public class Employee : Person { }

class Program

{

static void AddToContacts(Person person)

{

// do something

}

static void Test()

{

Action addPersonToContacts = AddToContacts;

Action addEmployeeToContacts = AddToContacts;

addEmployeeToContacts = addPersonToContacts;

}

}

Func 與 Action 中異常處理

在業(yè)務(wù)實(shí)現(xiàn)的時(shí)候,很多場景需要保證數(shù)據(jù)的原子性,例如帶有數(shù)據(jù)庫操作的、一系列動(dòng)作組成的場景,一旦中間某個(gè)動(dòng)作失敗,我們需要將所有狀態(tài)恢復(fù)。

假如這種場景選擇使用委托模式,并且在委托方法中拋出異常,由于委托者并不知道被委托者實(shí)際的代碼流程,即使出現(xiàn)異常,委托者也無法確定要回滾的內(nèi)容。

如一個(gè)簡單下單場景:

用戶下訂單庫存有效并預(yù)約庫存創(chuàng)建訂單調(diào)用支付進(jìn)行支付實(shí)際扣減庫存訂單生效狀態(tài)更新

假使拋出了一個(gè)非常精確的異常,例如訂單在扣減庫存階段失敗,并需要委托者處理,那么委托者就必然需要了解被委托者內(nèi)部實(shí)現(xiàn)細(xì)節(jié),也就違背了我們使用委托模式的初衷。

所以我們應(yīng)避免在 Func 和 Action 中拋出異常,或者說對于有原子性要求的業(yè)務(wù),應(yīng)避免使用委托模式。如果場景貼合委托模式,卻沒有辦法保證相關(guān)的表達(dá)式絕對不拋出異常,那么必須采用其他開銷更大的防護(hù)措施,即把異常情況頁考慮進(jìn)來。例如:

拷貝源數(shù)據(jù),并在源數(shù)據(jù)上進(jìn)行操作,整個(gè)委托執(zhí)行成功時(shí),才會(huì)真正覆蓋源數(shù)據(jù)。添加異常處理邏輯和額外的數(shù)據(jù)恢復(fù)流程,例如可以設(shè)計(jì)整個(gè)流程能多次重復(fù)執(zhí)行,每個(gè)步驟的中間結(jié)果都保存下來,通過不同的flag來判斷當(dāng)前流程是否執(zhí)行成功,如果成功則跳過直接執(zhí)行下一個(gè)步驟,如果不成功則嘗試重試。對于始終無法成功的場景,采用其他流程用來恢復(fù)數(shù)據(jù)(可能就需要人工參與)。

3. 其他委托:Predicate & Comparison & Converter

Predicate 是用來判斷某個(gè)條件是否成立的布爾委托。

public delegate bool Predicate(T obj);

Comparison 是比較兩個(gè)同類型對象的委托。

public delegate int Comparison(T x, T y);

Converter 是將對象從一種類型轉(zhuǎn)換為另一種類型的委托。

public delegate TOutput Converter(TInput input);

柚子快報(bào)激活碼778899分享:開發(fā)語言 C# 委托

http://yzkb.51969.com/

參考閱讀

評(píng)論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19133486.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄