天天看點

C#學習之C#面向對象程式設計(委托(1))

委托

​ 委托是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";
			}
		}
	}
}
           

​ 事件本身包含一個調用清單,在事件産生時,按照清單的順序執行指定的方法。

​ 事件委托和一般委托是很相似的,不同點就在于這個調用清單,事件委托的調用清單隻能通過"+=“運算符和”-=“運算符來改變,而一般委托可以使用”="運算符,直接使用一個調用清單給委托指派。事件委托的這種指派方式,在一定程度上,避免了事件調用清單的方法被某段程式代碼完全替換。