C# Event在.Net规则下由接口定义的实现

最近在学C#(教材《C# in a nutshell》很不错的说),看完delegate(委托)以后,紧接着就是event(事件)了,个人对跟.Net相关的东西并没有什么兴趣(毕竟是会增加代码复杂度的玩意),可是后面没准用得到,而且讲完.Net那套定义规则之后紧接着就是“接口内定义事件如何实现”,遂想试试写例子看看。

.Net框架下,对于事件对应的委托有三条规则:

1.返回值必须为void——就是没有返回值;

2.参数必须有一个为object——用于转移额外信息(convey extra information),这里也可以用System.EventHandler,但其实EventHandler的说明是“没有额外信息时使用”;

3.名称必须以EventHandler结尾,个人很讨厌Handle这个词,难以解释这是个什么东西,别问,问就句柄,可是句柄又是个什么鬼?(windowsAPI PTSD)

因为没有什么C#的代码经验,所以,并不清楚接口内定义事件的具体应用场合。在不符合以上规则的情况下,

using System;

namespace ForPractise
{
    public delegate void MathematicFunc<T>(T e);

    public interface IFoo { event MathematicFunc<int> InterfaceEvent; } // if .Net use subclass of EventArgs instead of int

    public class Foo : IFoo
    {
        private int counter;
        private MathematicFunc<int> _field; // private field of delegate
        public event MathematicFunc<int> InterfaceEvent // explictly declare add & remove of interface IFoo
        {
            // ... there could have multiple fields
            add { _field += value; }
            remove { _field -= value; }
        }

        private void OnBraodcast(int counts) // fire events
        {
            _field?.Invoke(counts);
        }

        public int Counter
        {
            get { return counter; }
            set
            {
                if (counter == value)
                {
                    return;
                }
                counter = value;
                OnBraodcast(counter);
            }
        }
    }

    class Program
    {
        static int Main()
        {
            Foo foo = new Foo();
            foo.Counter = 21;
            foo.InterfaceEvent += Multiple;
            foo.InterfaceEvent += Ratio;
            foo.Counter = 23;
            foo.InterfaceEvent -= Ratio;
            foo.Counter = 12;
            foo.InterfaceEvent -= Ratio;
            foo.InterfaceEvent += Ratio;
            foo.Counter = 1;

            Console.Read();

            return 0;
        }

        static void Multiple(int num)
        {
            Console.WriteLine("{0} multiply itself {1}", num, num * num);
        }

        static void Ratio(int num)
        {
            Console.WriteLine("{0} divide 0.1 {1}", num, num / 0.1d);
        }
    }
}

以上代码中,显示定义event.add跟event.remove可以省略——非必要的(即便显式定义了,在外部也只能通过"+="跟"-="进行订阅),直接写为"public event MathematicFunc<int> interfaceEvent; // 可以加上=null"即可。

下面则是应用.Net规则的代码,会比较肿,套用这种结构,需要额外定义System.EventArgs的子类作为参数,委托在套用泛型的时候也要多加很多东西——不过多参数就可以直接塞到EventArgs的子类里面了,也不清楚是方便了还是糟心了。同上event的显式定义也是非必要的。

using System;

namespace ForPractise
{
    public class FooEventArgs : EventArgs
    {
        public int Counter { set; get; }

        public FooEventArgs(int count) { Counter = count; }
    }

    public delegate void MathematicEventHandler<TEArgs>(object source, TEArgs e) where TEArgs : EventArgs; // delegate follow the .Net framework three rules

    public interface IFoo { event MathematicEventHandler<FooEventArgs> InterfaceEvent; }

    public class Foo : IFoo
    {
        private int counter;
        private MathematicEventHandler<FooEventArgs> _field; // private field of delegate
        public event MathematicEventHandler<FooEventArgs> InterfaceEvent // explictly declare add & remove of interface IFoo
        {
            // ... there could have multiple fields
            add { _field += value; }
            remove { _field -= value; }
        }

        private void OnBraodcast(FooEventArgs e) // fire events
        {
            _field?.Invoke(this, e);
        }

        public int Counter
        {
            get { return counter; }
            set
            {
                if (counter == value)
                {
                    return;
                }
                counter = value;
                OnBraodcast(new FooEventArgs(counter));
            }
        }
    }

    class Program
    {
        static int Main()
        {
            Foo foo = new Foo();
            foo.Counter = 21;
            foo.InterfaceEvent += Multiple;
            foo.InterfaceEvent += Ratio;
            foo.Counter = 23;
            foo.InterfaceEvent -= Ratio;
            foo.Counter = 12;
            foo.InterfaceEvent -= Ratio;
            foo.InterfaceEvent += Ratio;
            foo.Counter = 1;

            Console.Read();

            return 0;
        }

        static void Multiple(object obj, FooEventArgs e) // will be quite clumsy for simple function methods.
        {
            Console.WriteLine("{0} multiply itself {1}", e.Counter, e.Counter * e.Counter);
        }

        static void Ratio(object obj, FooEventArgs e)
        {
            Console.WriteLine("{0} divide 0.1 {1}", e.Counter, e.Counter / 0.1d);
        }
    }
}

其实MathematicEventHandler这个委托名不以EventHandler结尾依旧可以正常运行,应该是没有放到标准的.Net环境下,不然就是这只是约定俗成的命名法——就跟fire event部分的函数以On做前缀一样。

上面的两段运行结果都是一样的,暂时没找出来差别。还是写简单一些的好呐。

运行结果:

23 multiply itself 529
23 divide 0.1 230
12 multiply itself 144
1 multiply itself 1
1 divide 0.1 10

猜你喜欢

转载自www.cnblogs.com/cityfn/p/12057160.html
今日推荐