我在理解C#代表如何工作時遇到了一些麻煩。我有很多代碼示例,但我仍然無法正確掌握它。C代表中的代表#
有人可以用「純英文」向我解釋嗎?當然!代碼示例將有所幫助,但我想我需要更多的描述它的工作方式/原因。
編輯:
好了,問題是:爲什麼代表工作?什麼是整個過程的「流程圖」?
使用代表的先決條件是什麼?
我希望這可以讓問題更清楚。
我在理解C#代表如何工作時遇到了一些麻煩。我有很多代碼示例,但我仍然無法正確掌握它。C代表中的代表#
有人可以用「純英文」向我解釋嗎?當然!代碼示例將有所幫助,但我想我需要更多的描述它的工作方式/原因。
編輯:
好了,問題是:爲什麼代表工作?什麼是整個過程的「流程圖」?
使用代表的先決條件是什麼?
我希望這可以讓問題更清楚。
思考委託的一種方法就像是對功能的引用。例如,假設您在窗口中有一個按鈕,並且您希望點擊該按鈕時發生某些事情。您可以將委託附加到按鈕的Click事件,並且每當用戶單擊此按鈕時,您的功能將被執行。
class MyWindow : Window
{
Button _button;
public MyWindow()
{
_button = new Button();
// place the button in the window
_button.Click += MyWindow.ButtonClicked;
}
static void ButtonClicked(object sender, RoutedEventArgs e)
{
MessageBox.Show("Button Clicked");
}
}
請注意我是如何讓ButtonClicked成爲一個靜態函數 - 接下來我想對非靜態函數做一個說明。假設而不是ButtonClicked是一個非靜態成員:
class MyWindow : Window
{
Button _button;
int _numClicked = 0;
public MyWindow()
{
this._button = new Button();
// place the button in the window
this._button.Click += this.ButtonClicked;
}
void ButtonClicked(object sender, RoutedEventArgs e)
{
this._numClicked += 1;
MessageBox.Show("Button Clicked " + this._numClicked + " times");
}
}
現在委託既包含的功能「ButtonClicked」和實例,「這」,該方法被調用的參考。 MyWindow構造函數中的「this」和ButtonClicked中的「this」是相同的。
這是一個被稱爲關閉的特定情況,它允許在創建委託時「保存」狀態 - 當前對象,局部變量等。在上面的例子中,我們使用了委託中構造函數中的「this」。我們可以做更多的事:
class MyWindow : Window
{
Button _button;
int _numClicked = 0;
public MyWindow(string localStringParam)
{
string localStringVar = "a local variable";
this._button = new Button();
// place the button in the window
this._button.Click += new RoutedEventHandler(
delegate(object sender, RoutedEventArgs args)
{
this._numClicked += 1;
MessageBox.Show("Param was: " + localStringParam +
" and local var " + localStringVar +
" button clicked " + this._numClicked + " times");
});
}
}
在這裏,我們創建了一個匿名委託 - 它沒有給出一個明確的名稱的功能。引用此函數的唯一方法是使用RoutedEventHandler委託對象。而且,這個函數存在於MyWindow構造函數的範圍內,因此它可以訪問所有本地參數,變量和成員實例「this」。即使在MyWindow構造函數退出後,它仍將繼續保持對局部變量和參數的引用。
作爲一個方面說明,委託人還將持有對該對象實例的引用 - 「this」 - 即使刪除了所有其他對該類的引用。因此,爲了確保類是垃圾收集,應該刪除所有到非靜態成員方法的委託(或在其範圍內創建的委託)。
所有數據都是有用的和互補的。感謝大家。 我會小心閱讀所有答案並繼續嘗試。再次感謝:D – 2009-11-14 19:55:33
那麼,委託是一種類型。委託類型的變量可以引用或指向一個函數。
這給你一個間接的方法來調用一個方法,所以可以在運行時選擇方法。因此,您可以擁有包含方法的變量,參數和屬性。這些屬性稱爲事件。
再多一次的代碼示例,是完整的:
delegate void ADelegate(); // the delegate type
void Foo() { ... } // a compatible method
void Bar() { ... } // a compatible method
void Main()
{
ADelegate funcPtr; // a delegate variable
if (aCondition)
funcPtr = Foo; // note: _not_ Foo(), Foo is not executed here
else
funcPtr = Bar;
funcPtr(); // calls Foo or Bar depending on aCondition
}
使用委託變量是不常見的。但是您可以使用委託參數來實例化Sort方法來選擇升序或降序排序。
delegate int Compare(MyClass a, MyClass b); // the delegate type
void int CompareUp(MyClass a, MyClass b) { ... }
void int CompareDn(MyClass a, MyClass b) { ... }
void Sort(MyClass[] data, Compare comparer) { ... }
而且您可能知道事件,這些事件是基於代表的(特殊類型的)屬性。
它是一種倒置原理。通常情況下,您會編寫調用方法的代碼,並且您在編寫代碼時調用的方法是已知的。代表允許您匿名調用方法。那就是你不知道程序運行時調用的實際方法。
它有助於區分應用程序不同部分的問題。所以你可以有一些代碼在數據存儲上執行任務。您可能有其他處理數據的代碼。數據上的進程無需知道數據存儲的結構,數據存儲不應該依賴於數據的使用。
可以寫入處理代碼,以假定某些與數據存儲結構無關的數據。這樣,我們可以更改數據存儲的結構,而不用擔心影響數據上的進程。
您可以將委託視爲將代碼視爲數據的方式。如果你創建一個委託,它是一個類型。這種類型的變量可能指向特定的方法(符合委託定義)。
這意味着您可以將一段代碼視爲數據並將其傳遞給方法。由於代表指向代碼(或null),因此您也可以通過變量調用它指向的代碼。
這允許一些非常有用的模式。典型的例子是如何對一個集合進行排序。通過允許調用者提供一個委託來實現對特定元素進行排序的意義,排序方法不需要知道任何有關這方面的信息。
同樣的想法被廣泛用於LINQ的很多方法。即你傳入一個委託(或更常見的lambda)來處理一些特定的任務,並且LINQ方法將會調用它來完成任務。
委託是通過委託實例調用單個/多個方法的引用類型。它擁有方法的引用.Delegates可用於處理(調用/調用)單個事件上的多個方法。代表可以用來定義異步方法。 這裏是一個代表的例子 首先我們創建一個類。其中我們聲明瞭delegate.and我們在該類中創建了一個方法來調用委託。
public class simpleinterest
{
public delegate void intcal(double i); //declare delegate
public event intcal interest; //create delegate object
public void calculate(double p, double n,double r)
{
interest(p*n*r/100); //invoke delegate
}
}
在我們的程序中我們做了映射。那就是我們指定調用委託時觸發哪個事件。
private void btn_Click(object sender, RoutedEventArgs e)
{
simpleinterest s1 = new simpleinterest();
s1.interest+=new simpleinterest.intcal(s1_interest);//mapping
s1.calculate(1000,3,10);
}
void s1_interest(double r)
{
MessageBox.Show("Amount:" + r.ToString());
}
委託是函數指針到某處定義的方法。
假設你有一個的BankAccount類,你必須發送電子郵件給客戶,只要他/她的餘額小於$ 100。然後,自然的趨勢是在餘額屬性設置器中添加一個支票,以查看客戶的餘額是否低於100美元,如果是,則觸發電子郵件。但是這種設計並不靈活。上述辦法的
缺點:
將來,肯定會以發送短信而不是電子郵件的客戶的要求。很少有客戶選擇電子郵件和短信。因此,無論何時您需要通知客戶有任何更改,您都會去修改BankAccount類。這是違反的開放式擴展和關閉修改堅實的設計原則。
替代使用溶液代表們的:
定義NotifyCustomer()方法,其與發送通知客戶有關低平衡,的BankAccount類以外的交易。
修改BankAccount類來定義委託並在構造函數中接受它的值。
在創建的BankAccount類,通過在步驟1中
在的BankAccount的類餘額設置器創建的NotifyCustomer()方法,檢查是否餘額小於$ 100。如果是這樣,請調用委託。
的的BankAccount類外定義的NotifyCustomer()方法被調用,導致發送所定義的通知。
在未來,如果有通知客戶的一種新的方式,那麼不需要改變在的BankAccount類。使用委託設計的
優點:
鬆耦合:本的BankAccount類不知道的硬編碼邏輯通知客戶。
遵循改性原理對擴展開放和關閉:無論何時,你並不需要通知客戶變化的介質改變的BankAccount類。所以現在你會很自豪地說你的BankAccount類設計遵循設計原則。
如果您想了解更多關於委託的一個例子,讀What are delegates and why we need them.
委託是引用類型,委託是指方法。這被稱爲封裝方法。當您創建一個委託時,您可以指定一個方法簽名和返回類型。您可以使用該委託封裝任何匹配的方法。創建與委託關鍵字的委託,然後返回類型和可轉授的方法的簽名,如下所示:
public delegate void HelloFunctionDelegate(string message);
class Program
{
static void Main()
{
HelloFunctionDelegate del = new HelloFunctionDelegate(Hello);
del("Hello from Delegate");
}
public static void Hello(string strMessage)
{
Console.WriteLine(strMessage);
}
}
輸出是爲你好,從代表
Delegate是一個引用類型變量,它指向方法的引用。所有委託都來自System.Delegate類。例如,在Windows窗體或WPF中,方法事件與代理的概念一起工作。 這是在c#使用delagates在C#Introduction to delegates in C#
Delagates的例子:它定義該方法的其它可invoke.In換句話說,我們可以說,它包裝的方法的參考簽名它可以呼叫。 下面是代表用途:
它支持靜態方法和實例方法。
下面是它在內部的工作原理。
//下面是代表的聲明。
public delegate void DisplayNamme(string name);
運行時CLR爲代表創建一個類,如下所示。
public class DisplayNamme : System.MulticastDelegate{
// It is a contructor
public DisplayNamme(Object @object, IntPtr method);
// It is the method with the same prototype as defined in the source code.
public void Invoke(String name);
// This method allowing the callback to be asynchronouslly.
public virtual IAsyncResult BeginInvoke(String name,
AsyncCallback callback, Object @object);
public virtual void EndInvoke(IAsyncResult result);
}
我們可以看到它通過程序Ildasm.exe工具。 使用此工具可以中斷DLL。
構造函數有兩個參數:IntPrt引用傳遞給函數的方法的名稱,而@object引用隱式傳遞給構造函數的對象的引用。
CLR使用委託的Invoke方法來調用回調方法。
下面是使用委託的回調方法的實現。
// Declare Delegates
public delegate void DisplayNamme(string name);
class Program
{
public static void getName(string name)
{
Console.WriteLine(name);
}
public static void ShowName(DisplayNamme dn, string name)
{
// callback method calling. We can call it in two ways.
dn(name);
// or explicitly
dn.Invoke(name);
}
static void Main(string[] args)
{
DisplayNamme delDN = getName;
Program.ShowName(delDN, "CallBack");
Console.ReadLine();
}
}
1)首先你要明白爲什麼/當你需要一個代表,什麼是它解決的問題。
以我的經驗我主要用它們來允許用戶自定義一個對象的行爲。
Immagine a Grid組件允許開發人員定製每列的渲染方式。 例如,如果您想在紅色值爲零以下時寫入紅色值。
創建網格的開發人員不知道用戶如何定製輸出,因此它需要一種機制讓組件的用戶將某些邏輯注入組件。
2)然後,你必須要了解的委託是如何工作的
什麼是混淆是你必須寫這樣做奇怪代碼,你必須做同樣的許多方面事情。
這是網格類:
// the grid let the programmer that will use it to customize the output
public class Grid{
// 1) First I declare only the interface of the delegate
public delegate String ValueFormatterDelegate(String v);
// 2) I declare a handler of the implementation of the delegate
public ValueFormatterDelegate ValueFormatterHandler;
// 3) I call the handler inside the Print method
public void Print(String x){
Console.WriteLine(ValueFormatterHandler.Invoke(x));
}
}
// 1)首先我聲明僅委託 公共代表字符串ValueFormatterDelegate(字符串V)的接口;
注意,是像一個正常的方法,但是:
這樣我說:「格式化輸出的方法有這個接口:它將採取一個字符串作爲輸入,它會輸出一個字符串」
它記得我接口方法的定義。
// 2)本人聲明委託 公共ValueFormatterDelegate ValueFormatterHandler執行的處理程序;
現在我必須創建一個委託類型的屬性來處理此方法的實現。
// 3)I調用打印方法 公共無效打印(串x){Console.WriteLine (ValueFormatterHandler內的處理程序。調用(x)); }
在打印方法中,我可以使用處理程序,它將鏈接真正的實現。
ValueFormatterHandler的類型是ValueFormatterDelegate 和ValueFormatterDelegate是廣告代理 和.Invoke是委託類型
的方法,這是用我的網類,並且是能夠將其在飛行個性化的程序。 這裏的問題是你需要做很多事情。
using System;
public class Program{
public static void Main(){
var printer = new Printer();
// METHOD 1 : link to a named method
// here i link the handler of the delegate to a real method
// the FormatXXX is a static method defined at the ed of this code
printer.ValueFormatter = FormatXXX;
// when i call Print("hello")
printer.Print("hello"); // XXhelloXX
// METHOD 2 : anonimous method
// think at this like a method but without a name
// FormatYY (String x){ return "YY"+x+"YY"; };
// become
// delegate (String x){ return "YY"+x+"YY"; };
printer.ValueFormatter = delegate (String x){ return "YY"+x+"YY"; };
printer.Print("hello"); // YYhelloYY
// METHOD 3 : anonimous method using lambda
// as you can note the type of parameter x is inferred from the delegate declaration
// public delegate String ValueFormatterDelegate(String v);
printer.ValueFormatter = (x)=>"KK" + x + "KK";
}
public static String FormatXXX(String y){
return "XX"+ y +"XX";
}
}
您能否澄清一下:您是在問如何使用代表,或者您在問C#如何讓委託可能? – Anton 2009-11-14 18:58:52
你的問題不清楚!你能更清楚一點嗎? – 2009-11-14 18:59:57