委托回调函数的妙用(c# code )

   //person类
  public  class Person
    {
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        private int age;

        public int Age
        {
            get { return age; }
            set { age = value; }
        }
        private string role;

        public string Role
        {
            get { return role; }
            set { role = value; }
        } 
    }
//
 public class DelegateClass
    {
        private List Psersons;
        ///

        /// 待筛选的person集合
        ///
        public List Persons
        {
            get { return Psersons; }
            set { Psersons = value; }
        }
        public List FindPerson(Predicate condition)
        {
            List list = new List();
            foreach (var p in Persons)
            {
                if (condition(p))
                         list.Add(p);
            }
            return list;
        }
    }//委托函数调用
 class Program
    {
        static void Main(string[] args)
        {
            List list = new List();
            Person people = new Person();
            people.Name = "FrankPeng";
            people.Age = 25;
            people.Role = "软件工程师";
            list.Add(people);

            Person people1 = new Person();
            people1.Name = "Jack";
            people1.Age = 30;
            people1.Role = "项目主管";
            list.Add(people1);

            Person people2 = new Person();
            people2.Name = "James";
            people2.Age = 36;
            people2.Role = "总监";
            list.Add(people2);
           
            DelegateClass deleCall = new DelegateClass();
            deleCall.Persons = list;
            //查找名字叫张三的人。
            list = deleCall.FindPerson(delegate(Person p) { return p.Name == "张三"; });
            foreach (var item in list)
            {
                Console.WriteLine("姓名为张三的人:");
                Console.WriteLine(item.Name);
                Console.WriteLine(item.Age);
                Console.WriteLine(item.Role);
                Console.WriteLine("============================");
            }
            //查找年龄在20~30岁的人。
            list = deleCall.FindPerson(delegate(Person p) { return p.Age >= 20 && p.Age <= 30; });
            foreach (var item in list)
            {
                Console.WriteLine("年龄在20~30岁的人:");
                Console.WriteLine(item.Name);
                Console.WriteLine(item.Age);
                Console.WriteLine(item.Role);
                Console.WriteLine("============================");
            }
            查找职务角色是总监

            list = deleCall.FindPerson(delegate(Person p) { return p.Role == "总监"; });
            foreach (var item in list)
            {
                Console.WriteLine("职位为总监的人是:");
                Console.WriteLine(item.Name);
                Console.WriteLine(item.Age);
                Console.WriteLine(item.Role);
                Console.WriteLine("============================");
            }
        }
    }

 

在这段代码中,调用者提前定义行为(筛选什么样的数据),而算法(查找人员的方法),它只管遍历。
如果没有委托,你怎么写?
你得写
FindPersonByName(string Name)
FindPersonByAge(int MinAge, int MaxAge)
FindPersonByRole(RoleType type)
FindPersonByXXX(...)
...
这些函数在遍历算法上相同,但是筛选的依据不同,于是相同的程序就要写很多次。
你有什么办法把这些方法写入一个函数,同时具有无限扩展性呢?比如有人提出,我查找年龄不这么找,我找年龄是偶数的人(好奇怪的需求)。用委托的代码很简单,查找函数不用改,用如下调用即可:
你得写
FindPersonByName(string Name)
FindPersonByAge(int MinAge, int MaxAge)
FindPersonByRole(RoleType type)
FindPersonByXXX(...)
...
这些函数在遍历算法上相同,但是筛选的依据不同,于是相同的程序就要写很多次。
你有什么办法把这些方法写入一个函数,同时具有无限扩展性呢?
比如有人提出,我查找年龄不这么找,我找年龄是偶数的人(好奇怪的需求)。
用委托的代码很简单,查找函数不用改,用如下调用即可:
C# code
    list = FindPerson(delegate(Person p) 
  {
    return p.Age % 2 == 0; }); 
    foreach (var item in list) 
    { 
       Console.WriteLine(item); 
    }
随着功能的增多,不使用委托的代码要么出现很多很多重复的方法,或者是一个很复杂的 switch case 分支,而且每次新的需求都要修改函数实现。
### Python 调用 C# 类库中的事件、委托和回调机制 在 Python 中调用 C# 的事件、委托和回调功能,主要依赖于 `pythonnet` 提供的 `clr` 模块。此模块允许 Python 访问 .NET 环境中的各种特性,包括事件、委托和回调逻辑。 以下是一些详细的实现方法及其示例代码: #### 1. **Python 调用 C# 委托** C# 委托是一种类型安全的函数指针,可以在运行时绑定到任何匹配签名的方法。通过 `clr` 模块,可以从 Python 定义一个适配器函数,并将其赋值给 C# 委托实例。 ##### 示例代码 假设有一个名为 `MyCSharpLibrary.dll` 的 C# 库,其中包含以下定义: ```csharp // C# Code in MyCSharpLibrary.csproj using System; namespace MyCSharpLibrary { public delegate void SimpleDelegate(string message); public class DelegateExample { public event SimpleDelegate OnMessage; public void TriggerEvent(string msg) { OnMessage?.Invoke(msg); } } } ``` 在 Python 中可以这样使用该委托: ```python import clr # 加载 C# 编译生成的程序集 clr.AddReference('path/to/MyCSharpLibrary.dll') from MyCSharpLibrary import DelegateExample, SimpleDelegate def callback(message): """Python 函数作为 C# 委托的目标""" print(f"Callback received: {message}") # 创建 C# 类的实例 delegate_example = DelegateExample() # 注册 Python 回调函数C# 委托 callback_delegate = SimpleDelegate(callback) delegate_example.OnMessage += callback_delegate # 触发 C# 事件 delegate_example.TriggerEvent("Hello from C#!") # 移除回调(可选) delegate_example.OnMessage -= callback_delegate ``` 此处展示了如何将 Python 方法注册为 C# 委托的目标[^1]。 --- #### 2. **Python 调用 C# 事件** C# 事件本质上是封装了多播委托的一种特殊用途。Python 可以像处理普通委托一样订阅这些事件。 ##### 示例代码 延续上面的例子,在触发事件部分稍作调整即可: ```python # 订阅 C# 事件 delegate_example.OnMessage += callback # 触发事件 delegate_example.TriggerEvent("Firing an event!") # 解绑事件监听器 delegate_example.OnMessage -= callback ``` 需要注意的是,虽然 Python 可以成功订阅 C# 事件,但在多线程环境下可能存在竞态条件问题[^3]。因此建议谨慎管理线程安全性。 --- #### 3. **Python 实现 C# 回调** 当需要从 C# 主动调用 Python 方法时,通常会涉及回调模式。这可以通过设置委托来完成。 ##### 示例代码 假设有这样一个 C# 接口: ```csharp public interface ICallbackHandler { void HandleResult(int result); } public class CallbackInvoker { private readonly ICallbackHandler _handler; public CallbackInvoker(ICallbackHandler handler) { _handler = handler; } public void PerformOperation() { int result = 42; // Simulated operation result _handler.HandleResult(result); // Call back into Python code } } ``` 在 Python 中可以创建一个实现了该接口的对象: ```python class PythonCallbackHandler: def HandleResult(self, result): print(f"C# called back with result: {result}") # 将 Python 类注册为 C# 接口的实现者 python_handler = PythonCallbackHandler() callback_invoker = CallbackInvoker(python_handler) # 执行操作并接收回调 callback_invoker.PerformOperation() ``` 这种模式非常适合构建双向通信管道[^2]。 --- ### 注意事项 - **线程安全**:正如前面提到的那样,标准的 C# 事件和多播委托在线程竞争条件下并非完全可靠。如果应用涉及到高并发场景,请考虑引入锁或其他同步手段。 - **性能开销**:频繁跨越托管边界(Managed Boundary)可能导致显著的性能下降。优化策略包括减少交互次数或将批量数据一次性传输完毕。 - **异常传播**:未捕获的异常可能会破坏整个应用程序稳定性。务必妥善处理可能出现的各种错误状况。 --- ### 结论 通过合理运用 `pythonnet` 提供的能力,完全可以使 Python 和 C# 协同工作起来。无论是简单的委托还是复杂的事件模型都能得到良好支持。不过也要牢记潜在的风险因素,并采取相应措施加以规避。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值