年度语言之--c#中的委托

1. 引言

如果你是一位有Java背景的开发者,正考虑或已经开始了解C#,这篇文章将帮助你理解委托概念

在Java的开发中,我们习惯于使用接口(Interfaces)和匿名类(Anonymous Classes),特别是在处理事件监听器(Event Listeners)或实现回调(Callbacks)时。
在Java 8版本上,这些常用Lambda表达式来处理。

但当转向C#,会遇到一个新的概念 —— 委托。

委托在C#中扮演了一个类似于Java中接口和Lambda表达式的角色,但它们的工作方式和用法有所不同。

这篇文章将会通过将委托与Java中的相似概念相比较,帮助Java开发者更好地理解和掌握C#中的这一概念。

2. C#中的委托基础

  • 定义委托及其在C#中的作用:
    在C#中,委托是一种引用类型,它可以引用具有特定参数列表和返回类型的方法。
    它类似于Java中的接口,但更具灵活性。
    委托常用于实现事件处理和回调机制。
    例如,在.NET Framework中,许多标准库的类和方法使用委托来处理事件。

    示例:

    // 声明一个委托
    public delegate void DisplayMessage(string message);
    
    // 使用委托引用方法
    public class Program
    {
        static void Main(string[] args)
        {
            DisplayMessage messageTarget;//委托对象
    
            if (DateTime.Now.Hour > 17)
                messageTarget = ShowEveningGreeting;//为委托对象赋值 ShowEveningGreeting
            else
                messageTarget = ShowMorningGreeting;//为委托对象赋值 ShowMorningGreeting
    
            messageTarget("Hello, World!");
        }
    
        static void ShowMorningGreeting(string message)
        {
            Console.WriteLine("Good morning: " + message);
        }
    
        static void ShowEveningGreeting(string message)
        {
            Console.WriteLine("Good evening: " + message);
        }
    }
    
  • 委托的声明和实例化:
    委托的声明类似于方法的签名。
    它定义了可以被委托引用的方法的类型。
    声明后可以实例化委托,并将其指向一个特定的方法。

    示例:

    // 声明一个委托
    delegate int Operation(int x, int y);
    
    // 实例化委托
    Operation add = (x, y) => x + y;
    Operation multiply = (x, y) => x * y;
    
    // 使用委托
    int sum = add(5, 6); // 11
    int product = multiply(5, 6); // 30
    

3. Java中的类比概念

  • 与Java接口和匿名类的比较:
    在Java中,接口定义了一个可以被多个类实现的合约,匿名类则用于快速实现这些接口。
    C#中的委托也提供了类似的功能,允许将方法作为参数传递。
    与Java的接口和匿名类相比,委托提供了一种不同的方法引用机制。

    Java示例:

    interface Greeting {
        void greet(String message);
    }
    
    public class Example {
        public void executeGreeting(String msg, Greeting greeting) {
            greeting.greet(msg);
        }
    }
    
    // 使用
    new Example().executeGreeting("Hello", message -> System.out.println("Java says: " + message));
    

    C#示例:

    public delegate void Greeting(string message);
    
    public class Example {
        public void ExecuteGreeting(string msg, Greeting greeting) {
            greeting(msg);
        }
    }
    
    // 使用
    new Example().ExecuteGreeting("Hello", message => Console.WriteLine("C# says: " + message));
    
  • Java 8 Lambda表达式与C#委托:
    Java 8的Lambda表达式使得开发者能够以简洁的方式实现函数式编程。
    C#中的委托与Lambda表达式在某些方面相似,都允许将函数作为参数传递。

    Java示例:

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
    names.forEach(name -> System.out.println(name));
    

    C#示例:

    List<string> names = new List<string> { "Alice", "Bob", "Charlie" };
    names.ForEach(name => Console.WriteLine(name));
    

4. 委托的实际应用

  • 在C#中使用委托的例子:
    委托可以用于实现类似于Java接口的模式。
    例如,可以使用委托来实现排序算法的自定义。

    示例:

    List<int> numbers = new List<int> { 8, 3, 2, 5, 9 };
    numbers.Sort((a, b) => a.CompareTo(b)); // 使用Lambda表达式作为委托
    
  • 事件处理中委托的应用:
    C#中的事件是基于委托的,提供了一种在发生特定操作时触发和处理这些操作的机制。

    示例:

    public class Button {
        public delegate void ClickHandler(object sender, EventArgs e);
        public event ClickHandler Clicked;
    
        public void Click() {
            Clicked?.Invoke(this, EventArgs.Empty);
        }
    }
    
    // 使用
    var button = new Button();
    button.Clicked += (sender, e) => Console.WriteLine("Button clicked!");
    button.Click();
    
  • 委托用于回调函数:
    委托可以作为回调函数使用,在异步编程或事件驱动的逻辑中常用。

    示例:

    public void ProcessDataAsync(Data data, Action<string> callback) {
        // 数据处理逻辑
        callback("处理完成");
    }
    
    // 使用
    ProcessDataAsync(data, result => Console.WriteLine(result));
    

5. action/function 与 命名委托

C#提供了几种内置的委托类型,主要包括ActionFunction和用户定义的命名委托,这些类型简化了委托的使用。

  • Action和Function:

    • Action是一种不返回值的委托类型,可用于封装一个无返回值的方法。Action可以有0到16个参数。

    • Func是另一种委托类型,用于封装一个返回值的方法。Func的最后一个类型参数是返回类型,它可以有0到16个输入参数。

    示例:

    // 使用Action
    Action<string> greet = name => Console.WriteLine($"Hello, {name}!");
    greet("Alice");
    
    // 使用Func
    Func<int, int, int> add = (x, y) => x + y;
    int result = add(5, 10); // 结果是15
    
  • 命名委托:
    虽然ActionFunc提供了方便的方式来使用委托,但有时候创建一个具有特定签名和含义的命名委托更有用。这对于代码的可读性和自文档化特别重要。

    示例:

    // 声明一个命名委托
    public delegate int BinaryOperation(int a, int b);
    
    // 使用命名委托
    BinaryOperation multiply = (x, y) => x * y;
    int product = multiply(4, 5); // 结果是20
    

    这些委托类型提供了不同的方式来引用和执行方法,使得C#编程更加灵活和表达力更强。特别是在处理复杂的方法签名或需要明确方法意图时,常用命名委托。

6. 委托的高级主题

  • 多播委托的概念和应用:
    多播委托是一种特殊类型的委托,可以持有并调用多个方法,而不仅仅是一个。
    这是通过委托的 “+” 和 “-” 运算符实现的,允许添加或移除方法引用。

    示例:

    Action<string> handler = message => Console.WriteLine($"First handler: {message}");
    handler += message => Console.WriteLine($"Second handler: {message}");
    
    // 调用所有方法 包括First handler 和 Second handler
    handler("Hello, World!");
    
  • 在多线程编程中使用委托:
    在C#中,委托常用于Thread类中,用于指定线程开始时执行的方法。Java则使用Runnable接口来实现类似的功能。

    C# 示例:

    Thread thread = new Thread(new ThreadStart(() => {
        Console.WriteLine("C# 线程执行");
    }));
    thread.Start();
    

    Java 示例:

    Thread thread = new Thread(() -> {
        System.out.println("Java 线程执行");
    });
    thread.start();
    

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值