事件 - 命名约定和样式 [英] Events - naming convention and style

查看:20
本文介绍了事件 - 命名约定和样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 C# 中的事件/委托.我能否就我选择的命名/编码风格(取自 Head First C# 书籍)征求您的意见?

I'm learning about Events / Delegates in C#. Could I ask your opinion on the naming/coding style I've chosen (taken from the Head First C# book)?

我明天正在教一个朋友这个,并试图想出解释这些概念的最优雅的方式.(认为​​理解一门学科的最好方法是尝试并教授它!)

Am teaching a friend about this tomorrow, and am trying to come up with the most elegant way of explaining the concepts. (thought the best way to understand a subject is to try and teach it!)

class Program
    {
        static void Main()
        {
            // setup the metronome and make sure the EventHandler delegate is ready
            Metronome metronome = new Metronome();

            // wires up the metronome_Tick method to the EventHandler delegate
            Listener listener = new Listener(metronome);
            metronome.OnTick();
        }
    }

<小时>

public class Metronome
    {
        // a delegate
        // so every time Tick is called, the runtime calls another method
        // in this case Listener.metronome_Tick
        public event EventHandler Tick;

        public void OnTick()
        {
            while (true)
            {
                Thread.Sleep(2000);
                // because using EventHandler delegate, need to include the sending object and eventargs 
                // although we are not using them
                Tick(this, EventArgs.Empty);
            }
        }
    }

<小时>

public class Listener
    {
        public Listener(Metronome metronome)
        {
            metronome.Tick += new EventHandler(metronome_Tick);
        }

        private void metronome_Tick(object sender, EventArgs e)
        {
            Console.WriteLine("Heard it");
        }
    }

n.b.代码重构自 http://www.codeproject.com/KB/cs/simplesteventexample.aspx

推荐答案

有几点我想提一下:

Metronome.OnTick 似乎没有正确命名.从语义上讲,OnTick"告诉我它会在Tick"s 时被调用,但这并不是真正发生的事情.我会称它为Go".

Metronome.OnTick doesn't seem to be named correctly. Semantically, "OnTick" tells me it will be called when it "Tick"s, but that isn't really what's happening. I would call it "Go" instead.

通常接受的模型是执行以下操作.OnTick 是一个引发事件的虚方法.这样,您可以轻松覆盖继承类中的默认行为,并调用基类来引发事件.

The typically accepted model, however would be to do the following. OnTick is a virtual method that raises the event. This way, you can override the default behavior in inherited classes easily, and call the base to raise the event.

class Metronome
{
    public event EventHandler Tick;

    protected virtual void OnTick(EventArgs e)
    {
        //Raise the Tick event (see below for an explanation of this)
        var tickEvent = Tick;
        if(tickEvent != null)
            tickEvent(this, e);
    }

    public void Go()
    {
        while(true)
        {
            Thread.Sleep(2000);
            OnTick(EventArgs.Empty); //Raises the Tick event
        }
    }
}

<小时>

另外,我知道这是一个简单的例子,但如果没有附加侦听器,您的代码将抛出 Tick(this, EventArgs.Empty).您至少应该包含一个空保护来检查侦听器:


Also, I know this is a simple example, but if there are no listeners attached, your code will throw on Tick(this, EventArgs.Empty). You should at least include a null guard to check for listeners:

if(Tick != null)
    Tick(this, EventArgs.Empty);

然而,如果监听器在保护和调用之间未注册,这在多线程环境中仍然容易受到攻击.最好的办法是先捕获当前的听众并调用它们:

However, this is still vulnerable in a multithreaded environment if the listener is unregistered between the guard and the invocation. The best would be to capture the current listeners first and call them:

var tickEvent = Tick;
if(tickEvent != null)
    tickEvent(this, EventArgs.Empty);

我知道这是一个旧答案,但由于它仍在收集投票,​​这里是 C# 6 的做事方式.整个守卫"概念可以用条件方法调用代替,并且编译器确实在捕获侦听器方面做了正确的事情(TM):

I know this is an old answer, but since it's still gathering upvotes, here's the C# 6 way of doing things. The whole "guard" concept can be replaced with a conditional method call and the compiler does indeed do the Right Thing(TM) in regards to capturing the listeners:

Tick?.Invoke(this, EventArgs.Empty);

这篇关于事件 - 命名约定和样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆