委托
委托是C#程式設計語言新提出的面向對象概念。委托其實就是把程式的某些功能交給其他地方的代碼來實作。因為有些時候程式的流程并不确定,是以不自己實作,這些不确定的調用隻能通過其他的外部程式來确定。
這時候我們就需要委托,在外部程式中指定應該調用的方法來完成這個功能。委托類似于C++中的函數指針,當并不完全相同。因為委托概念是面向對象的,是以委托必須封裝在類内部。委托能夠對應多個方法,可以在程式運作時動态加減。
1. 委托的定義
C#程式設計語言要求開發人員非常熟悉委托,并且能夠根據代碼實作的場景,聲明和使用委托。委托常用的場合大緻分為以下4個方面。
- 一個類中需要調用不确定的方法時
- 在類中聲明事件時
- 在類中調用不應在類中實作的方法時
- 在接口中調用其他接口的方法時
面向對象程式設計,需要使用類将事物封裝成相對獨立的單元,減少了外部程式對類所包含資料的幹擾,但是事物與事物之間總是由各種各樣的關系,是以封裝在一定程度上為程式設計帶來了麻煩,委托就是為了處理此類的問題。
使用委托的好處是當外部條件改變時,不用修改每個調用類的定義。委托降低了類與類之間互相調用的耦合程度。
委托的定義包括三個方面,首先使用delegate關鍵字表示将要聲明一個委托,接着是委托的資料類型,最後是委托的名稱和參數清單。
public delegate decimal Price Adjustment(Order AdjustmentOrder);
委托代碼案例:
using System;
namespace cn.wellswang
{
public class Order
{
public string CoffeeName { get; set; }
public int AreaID { get; set; }
public decimal BasePrice { get; set; }
// 聲明價格調整的委托
public delegate decimal PriceAdjustmentDelegate(Order AdjustmentOrder);
// Order類的委托執行個體變量
public PriceAdjustmentDelegate PriceAdjustment;
public decimal FinalPrice
{
get
{
return BasePrice + PriceAdjustment(this);
}
}
}
public class Adjustment
{
private decimal Addition = 0;
public decimal BikePrice(Order AdjustmentOrder)
{
Addition += 5m;
return Addition;
}
public decimal CarPrice(Order AdjustmentOrder)
{
Addition += 10m;
return Addition;
}
public decimal Foam(Order AdjustmentOrder)
{
Addition += 0.5m;
return Addition;
}
public decimal Heat(Order AdjustmentOrder)
{
Addition += 1m;
return Addition;
}
}
public class Sale
{
public Order SaleOrder { get; set; }
public Adjustment SaleAdjsutment { get; set; }
public void DoSale()
{
switch (SaleOrder.AreaID)
{
case 1:
SaleOrder.PriceAdjustment +=
new Order.PriceAdjustmentDelegate
(SaleAdjsutment.BikePrice);
SaleOrder.PriceAdjustment +=
new Order.PriceAdjustmentDelegate
(SaleAdjsutment.Foam);
break;
case 2:
SaleOrder.PriceAdjustment +=
new Order.PriceAdjustmentDelegate
(SaleAdjsutment.CarPrice);
SaleOrder.PriceAdjustment +=
new Order.PriceAdjustmentDelegate
(SaleAdjsutment.Foam);
break;
case 3:
SaleOrder.PriceAdjustment +=
new Order.PriceAdjustmentDelegate
(SaleAdjsutment.CarPrice);
SaleOrder.PriceAdjustment +=
new Order.PriceAdjustmentDelegate
(SaleAdjsutment.Heat);
break;
}
}
}
public class Test
{
public static void Main(string[] args)
{
Sale MySale = new Sale();
MySale.SaleOrder = new Order();
MySale.SaleOrder.BasePrice = 30;
MySale.SaleOrder.AreaID = 3;
MySale.SaleAdjsutment = new Adjustment();
MySale.DoSale();
Console.Write("最終價格:" + MySale.SaleOrder.FinalPrice.ToString()); // 41
}
}
}
2. 事件委托
在C#程式設計語言中,事件必須聲明為委托類型,沒有聲明方法的事件是沒有意義的。事件,相當于委托執行個體變量,說不同的是聲明事件的代碼中多了一個event關鍵字。
事件與委托類的執行個體變量很相似,在這個執行個體變量中可以添加、移除符合委托聲明的方法。這也意味着可以用多種方法處理一個事件。最為常見的是一個事件對應一個處理方法。
using System;
namespace cn.wellswang
{
public class LoginEvent : EventArgs
{
public string UserName { get; set; }
public string PassWord { get; set; }
public LoginEvent(string username, string password)
{
UserName = username;
PassWord = password;
}
}
public class Login
{
public string UserName { get; set; }
public string PassWord { get; set; }
public delegate void LoginHandler(LoginEvent e);
public event LoginHandler OnLogin;
public void ActiveLogin()
{
OnLogin(LoginEvent(UserName, PassWord));
}
}
public class LoginPage
{
private Login UserLogin = new Login();
private bool IfLogined = false;
public string URLToShow;
public void DoLogin()
{
UserLogin.UserName = "Wells";
UserLogin.PassWord = "001005";
UserLogin.OnLogin += new Login.LoginHandler(VerifyUser);
UserLogin.OnLogin += new Login.LoginHandler(ShowOrders);
UserLogin.ActiveLogin();
}
void VerifyUser(LoginEvent e)
{
if (e.UserName == "Wells" && e.PassWord == "001005")
{
IfLogined = true;
}
}
void ShowOrders(LoginEvent e)
{
if(IfLogined)
{
URLToShow = "報帳單稽核情況.aspx";
}
}
}
}
事件本身包含一個調用清單,在事件産生時,按照清單的順序執行指定的方法。
事件委托和一般委托是很相似的,不同點就在于這個調用清單,事件委托的調用清單隻能通過"+=“運算符和”-=“運算符來改變,而一般委托可以使用”="運算符,直接使用一個調用清單給委托指派。事件委托的這種指派方式,在一定程度上,避免了事件調用清單的方法被某段程式代碼完全替換。