C#基础 --委托

委托常常和事件在一起使用,可以理解委托是方法的容器,事件则是委托的另一种表现形式。

1.一个简单的小例子

class Program
    {
        static void Main(string[] args)
        {
            People people = new People();
            people.StartEat("吃");
            Console.ReadLine();
        }
    }
    class People
    {
        public void EatApple(string s)
        {
            Console.WriteLine(s+"苹果");
        }
        public void EatPear(string s)
        {
            Console.WriteLine(s+"梨子");
        }
        public void StartEat(string str)
        {
            EatApple(str);
        }
    }

上面的代码应该很好理解,但是在StartEat方法并不知道什么时候该调用哪个方法进行输出,因此在调用之前还需要定义一个枚举EatWhat来进行判断,也就是StartEat(string str,EatWhat eatWhat)。传入的eatWhat枚举判断是吃苹果还是梨子。但是这种写法扩展性太差了,如果再加一个吃西瓜的方法,那么还要更新枚举,这样反复的增加方法和枚举显然不是一个很好的做法。

  显然这里要使用委托,为什么要使用委托?最本质的原因是利用委托可使StartEat得到一个参数,而这个参数是方法,这样我们想调用什么就可以调用什么了。
  

class Program
    {
        static void Main(string[] args)
        {
            People people = new People();
            people.StartEat("吃", people.EatApple);
            people.StartEat("吃", people.EatPear);
            Console.ReadLine();
        }
    }
    public delegate void EatDelegate(string name);
    class People
    {
        public void EatApple(string s)
        {
            Console.WriteLine(s+"苹果");
        }
        public void EatPear(string s)
        {
            Console.WriteLine(s + "梨子");
        }
        public void StartEat(string str,EatDelegate eatDelegate)
        {
            eatDelegate(str);
        }
   }

2.多播委托

  委托的特殊之处在于,我们以前定义的所有对象都包含数据,而委托包含的只是方法的地址。在上面例子的基础上,我们还可以实现多播委托。多播委托就是讲多个方法赋给同一个委托,当调用这个委托的时候,将依次调用其绑定的方法。下面是对Program类的改动。
  

class Program
    {
        static void Main(string[] args)
        {
            People people = new People();
            EatDelegate del = people.EatPear;
            del += people.EatApple;
            people.StartEat("吃", del);
            //既然可以对委托添加方法,那么也可以对委托取消方法的绑定
            del -= people.EatPear;
            Console.ReadLine();
        }
    }

3.委托和事件

  在上面的例子中,我们给StartEat方法传参时需要传入2个参数,而且还需要在Main方法中得到委托对象。因此我们可以将委托封装到People类里面,使传参时只传入一个参数,这就是用到了封装的思想。
  

class Program
    {
        static void Main(string[] args)
        {
            People people = new People();
            people.del = people.EatPear;
            people.del += people.EatApple;
            people.StartEat("吃");
            Console.ReadLine();
        }
    }
    class People
    {
        public EatDelegate del;
        public void EatApple(string s)
        {
            Console.WriteLine(s+"苹果");
        }
        public void EatPear(string s)
        {
            Console.WriteLine(s + "梨子");
        }
        public void StartEat(string str)
        {
            if (del != null)
            {
                del(str);
            }
        }
    }

现在我们的委托对象和一般的变量没有什么区别,外部类访问到People对象就可以拿到这个委托变量。假如现在在类里面声明一个字段,一般我们会封装字段采用属性。同样的,对于委托我们也要封装,这样在类的内部,委托变量总是私有,但是在外部,依旧可以使用+=和-=的访问操作。接下来我们对代码进行改写。

static void Main(string[] args)
        {
            People people = new People();
            //现在已经不能使用=来给事件对象赋值,而只能使用+=和-=来进行操作
            people.eventDelegate += people.EatApple;
            people.eventDelegate+=people.EatPear;
            people.StartEat("吃");
            Console.ReadLine();
        }
    }
    class People
    {
        //简单点理解,事件其实就可以理解为一个封装了委托的变量
        //如果去看代码执行的源码,会发现eventDelegate变量,其实就是一个委托对象,只不过它是私有的,修饰符为private
        //这个委托变量有2个方法 ,且只有2个方法,+=对应addon,-=对应于removeon方法。
        public event EatDelegate eventDelegate;
        public void EatApple(string s)
        {
            Console.WriteLine(s+"苹果");
        }
        public void EatPear(string s)
        {
            Console.WriteLine(s + "梨子");
        }
        public void StartEat(string str)
        {
            eventDelegate(str);
        }
    }

猜你喜欢

转载自blog.csdn.net/q764424567/article/details/80604330