C# Delegate
In C#, a delegate is a type-safe function pointer that allows methods to be passed as parameters to other methods.
Delegates in C# are similar to function pointers in C or C++.DelegateIs a reference type variable that holds a reference to a method; the reference can be changed at runtime.
Delegates are very common in C# and are used for event handling, callback functions, LINQ, and other operations.
All delegates derive fromSystem.Delegateclass.
Declaring a Delegate
A delegate is a reference type that defines a method signature and can be used to store a method matching that signature. Through a delegate, you can call methods in other classes.
The delegate declaration determines which methods can be referenced by the delegate. A delegate can point to a method with the same signature.
The syntax for declaring a delegate is as follows:
public delegate <return type> <delegate-name> <parameter list>
Chinese format description:
public delegate 返回类型 委托名(参数类型 参数名, ...);
For example, the following code defines a delegate that accepts two integers and returns an integer:
public delegate int MathOperation(int x, int y);
The delegate in the following example can be used to reference any method that has a singlestringa method with parameters and returns aintType variables.
public delegate int MyDelegate (string s);
Instantiate delegate (Delegate)
Once a delegate type is declared, a delegate object must be created using thenewkeyword, and it is associated with a specific method. When creating a delegate, the argument passed to thenewstatement is written like a method call, but without the parameters. For example:
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);
The following example demonstrates the declaration, instantiation, and use of a delegate, which can be used to reference a method that takes an integer parameter and returns an integer value.
Example
delegate int NumberChanger(int n);
namespace DelegateAppl
{
class TestDelegate
{
static int num = 10;
public static int AddNum(int p)
{
num += p;
return num;
}
public static int MultNum(int q)
{
num *= q;
return num;
}
public static int getNum()
{
return num;
}
static void Main(string[] args)
{
// Create a delegate instance
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
// Use delegate object to call method
nc1(25);
Console.WriteLine("Value of Num: {0}", getNum());
nc2(5);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}
When the above code is compiled and executed, it produces the following result:
Value of Num: 35 Value of Num: 175
Multicasting of a Delegate
Delegate objects can be used+are combined using the operator.
A combined delegate invokes the two delegates it combines; only delegates of the same type can be combined.
-The operator can be used to remove a component delegate from a combined delegate.
Using this useful feature of delegates, you can create an invocation list of methods to be called when the delegate is invoked. This is called a delegate'sMulticast (multicasting)also called multicast.
The following program demonstrates delegate multicasting:
Example
delegate int NumberChanger(int n);
namespace DelegateAppl
{
class TestDelegate
{
static int num = 10;
public static int AddNum(int p)
{
num += p;
return num;
}
public static int MultNum(int q)
{
num *= q;
return num;
}
public static int getNum()
{
return num;
}
static void Main(string[] args)
{
// Create a delegate instance
NumberChanger nc;
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
nc = nc1;
nc += nc2;
// Invoke multicast
nc(5);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}
When the above code is compiled and executed, it produces the following result:
Value of Num: 75
The Purpose of Delegate
The following example demonstrates the use of delegates. DelegateprintStringIt can be used to reference a method that takes a string as input and returns nothing.
We use this delegate to call two methods: the first prints the string to the console, and the second prints the string to a file:
Example
using System.IO;
namespace DelegateAppl
{
class PrintString
{
static FileStream fs;
static StreamWriter sw;
// Delegate declaration
public delegate void printString(string s);
// This method prints to the console
public static void WriteToScreen(string str)
{
Console.WriteLine("The String is: {0}", str);
}
// This method prints to a file
public static void WriteToFile(string s)
{
fs = new FileStream("c:\\message.txt", FileMode.Append, FileAccess.Write);
sw = new StreamWriter(fs);
sw.WriteLine(s);
sw.Flush();
sw.Close();
fs.Close();
}
// This method takes a delegate as a parameter and uses it to call a method
public static void sendString(printString ps)
{
ps("Hello World");
}
static void Main(string[] args)
{
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);
sendString(ps1);
sendString(ps2);
Console.ReadKey();
}
}
}
When the above code is compiled and executed, it produces the following result:
The String is: Hello World
Remove delegate
If you no longer need a method, you can use the-=operator to remove the method from the delegate chain.
Example
{
public delegate void PrintMessage(string message);
public static void PrintUpperCase(string message)
{
Console.WriteLine(message.ToUpper());
}
public static void PrintLowerCase(string message)
{
Console.WriteLine(message.ToLower());
}
public static void Main()
{
PrintMessage print = PrintUpperCase;
print += PrintLowerCase;
// Remove the PrintLowerCase method
print -= PrintLowerCase;
// Calling the delegate (only calls PrintUpperCase)
print("Hello, C#"); // Output: HELLO, C#
}
}
Delegates and events
Delegates are often used together with events. An event is a special type of delegate used for the publish/subscribe mechanism.
In C#, an event is essentially a type that encapsulates a delegate, and it is used to respond to certain operations in the program.
Example
{
// Define an event
public event EventHandler Click;
// Method to raise an event
public void OnClick()
{
if (Click != null)
{
Click(this, EventArgs.Empty); // Invoke event
}
}
}
public class Program
{
public static void Main()
{
Button button = new Button();
// Subscribe to event
button.Click += Button_Click;
// Raise event
button.OnClick(); // Output "Button clicked!"
}
private static void Button_Click(object sender, EventArgs e)
{
Console.WriteLine("Button clicked!");
}
}
Delegate types
C# provides several common delegate types:
1、Action
Action: Represents a method that does not return a value. It can accept up to 16 parameters.
Action<string> printMessage = Console.WriteLine;
printMessage("Hello");
2、Func
Func: Represents a method that has a return value. It accepts up to 16 parameters; the first parameter is the input parameter, and the last parameter is the return type.
Func<int, int, int> add = (x, y) => x + y; Console.WriteLine(add(3, 4)); // 输出 7
3、Predicate
Predicate: Represents a method that returns a bool value, usually used for conditional checks.
Predicate<int> isEven = x => x % 2 == 0; Console.WriteLine(isEven(4)); // 输出 True
Delegate notes
Type safety:Delegates are type-safe, meaning that only methods with matching signatures can be assigned to a delegate.
Anonymous methods and lambda expressions: You can use anonymous methods or lambda expressions to create delegate instances, simplifying the code.
Func<int, int, int> add = (x, y) => x + y; Console.WriteLine(add(5, 3)); // 输出 8
Asynchronous invocation: You can use delegates together with the BeginInvoke and EndInvoke methods to perform asynchronous calls.
Delegates are a very powerful and flexible feature in C# that can help implement event-driven programming, callback mechanisms, and functional programming styles. They not only provide the ability to reuse code but also improve the modularity of programs. Understanding and mastering the use of delegates is very important for C# programming.
other extensions