jiahaipeng

我要飞得更高
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

c# 委托实例

Posted on 2008-10-23 09:10  飞得更高  阅读(2364)  评论(1编辑  收藏  举报

    一:背景资料

    我们知道回调函数(callback)是WINDOWS编程的一个重要的部分。而回调函数实际是就是方法调用的指针,也成为函数指针。但在.NET中是不支持指针的,所以.NET就以委托的形式实现了函数指针的概念,而且这个委托是类型安全的。

    我们知道,一个函数的参数不能是另外一个函数的,当将一个函数传递给另外一个函数的时候,就需要委托,将这个函数的指针传递过去。

    二、问题来由

    冒泡排序算法是排序中的一个基本算法,我们通常会利用这个方法对已知类型(比如值类型)进行排序,算法也比较的简单。如下面的排序代码:
for (int i = 0; i < sortArray.Length; i++)
                
for (int j = i + 1; j < sortArray.Length; j++)
                    
if (sortArray[i]<sortArray[j])
                    
{
                        
object temp = sortArray[i];
                        sortArray[i] 
= sortArray[j];
                        sortArray[j] 
= temp;
                    }

     这个算法非常适合对int类型的排序,但是我们希望这个排序方法能够给任何对像进行排序。而且在代码运行前并不知道所比较的两个对象的类型,知道代码运行期间才知道是对什么类型对象的比较。那排序算法中的sortArray[i]<sortArray[j]的比较算法就有问题了。如何解决这个问题呢?答案是让客户机代码知道类在委托中传递的是什么方法,然后封装这个方法就可以进行比较了。

    三、解决方案。

    1、定义如下委托:

       delegate bool CompareOp(object lhs, object rhs);

     2、给Sort方法指定如下签名:

      public static void Sort(object[] sortArray, CompareOp getCompareMethod)

      3、设置完毕后,定义了如下类

class BubbleSorter
    
{
        
/// <summary>
        
/// 冒泡排序方法
        
/// </summary>
        
/// <param name="sortArray">要排序的一组对象</param>
        
/// <param name="getCompareMethod">判断两个对象大小的方法</param>

        public static void Sort(object[] sortArray, CompareOp getCompareMethod)
        
{
            
for (int i = 0; i < sortArray.Length; i++)
                
for (int j = i + 1; j < sortArray.Length; j++)
                    
if (getCompareMethod(sortArray[i], sortArray[j]))
                    
{
                        
object temp = sortArray[i];
                        sortArray[i] 
= sortArray[j];
                        sortArray[j] 
= temp;
                    }

        }

    }

   将比较两个对象大小的方法以委托的形式传递到排序方法中,就实现了一个冒泡排序针对所有类型的排序方法。

    四、应用实例

    我们定义一个Employee类来应用上面这个排序方法。如下:

 class Employee
    
{
        
private string _Name;
        
private decimal _Salary;
        
/// <summary>
        
/// 取得雇员的姓名
        
/// </summary>

        public string Name
        
{
            
get return _Name; }
            
set { _Name = value; }
        }

        
/// <summary>
        
/// 取得雇员的工资
        
/// </summary>

        public decimal Salary
        
{
            
get return _Salary; }
            
set { _Salary = value; }
        }

        
/// <summary>
        
/// 构造方法
        
/// </summary>
        
/// <param name="name"></param>
        
/// <param name="salary"></param>

        public Employee(string name, decimal salary)
        
{
            
this._Salary = salary;
            
this._Name = name;
        }

        
/// <summary>
        
/// 重写了tostring()方法
        
/// </summary>
        
/// <returns></returns>

        public override string ToString()
        
{
            
return string.Format(_Name + ",{0:C}", _Salary);
        }

        
/// <summary>
        
/// 比较两个对象的大小
        
/// </summary>
        
/// <param name="lhs"></param>
        
/// <param name="rhs"></param>
        
/// <returns></returns>

        public static bool Compare(object lhs, object rhs)
        
{
            Employee empLhs 
= (Employee)lhs;
            Employee empRhs 
= (Employee)rhs;

            
return (empLhs._Salary > empRhs._Salary) ? true : false;
        }

    }

  注意,比较两个对象大小的Compare方法的参数,是object,而不是Employee。这是为了匹配我们之前定义的委托的签名。也是为了实现一个公用化的排序方法。

   客户机代码如下:

namespace DelegatePrograme
{
    
delegate bool CompareOp(object lhs, object rhs);

    
class MainEntryPoint
    
{
        
static void Main(string[] args)
        
{
            Employee[] employees 
=
            
{
                
new Employee("Jone",2000),
                
new Employee("Tom",2500),
                
new Employee("Buddy",2300),
                
new Employee("Wiley",2800),
                
new Employee("Fudd",1900),
            }
;
            CompareOp compareOp 
= new CompareOp(Employee.Compare);
            BubbleSorter.Sort(employees, compareOp);

            
for (int i = 0; i < employees.Length; i++)
                Console.WriteLine(employees[i].ToString());
            Console.ReadLine();
        }

    }

}

   运行折行代码,就可以显示按照薪水排列的Employee。

   五 总结

   这是一个应用委托的一个简单的例子,但描述了如何使用委托来传递函数。委托其实就是一函数指针,我想,记住这一点是最重要的。