相关疑难解决方法(0)

事件 - 命名约定和样式

我正在学习C#中的事件/代表.我可以问一下你对我所选择的命名/编码风格的看法(取自Head First C#书)吗?

我明天正在和朋友一起教这个问题,并且正在尝试用最优雅的方式来解释这些概念.(认为​​理解一门学科的最好方法就是尝试教它!)

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();
        }
    }
Run Code Online (Sandbox Code Playgroud)
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) …
Run Code Online (Sandbox Code Playgroud)

c# events delegates

58
推荐指数
4
解决办法
5万
查看次数

锅炉板代码更换 - 这个代码有什么不好的吗?

我最近创建了这两个(不相关的)方法来替换我的winforms应用程序中的大量样板代码.据我所知,他们工作正常,但我需要一些保证/建议,以确定是否存在一些我可能会遗漏的问题.

(从记忆里)

static class SafeInvoker
{
    //Utility to avoid boiler-plate InvokeRequired code
    //Usage: SafeInvoker.Invoke(myCtrl, () => myCtrl.Enabled = false);
    public static void Invoke(Control ctrl, Action cmd)
    {
        if (ctrl.InvokeRequired)
            ctrl.BeginInvoke(new MethodInvoker(cmd));
        else
            cmd();
    }

    //Replaces OnMyEventRaised boiler-plate code
    //Usage: SafeInvoker.RaiseEvent(this, MyEventRaised)
    public static void RaiseEvent(object sender, EventHandler evnt)
    {
        var handler = evnt;
        if (handler != null)
            handler(sender, EventArgs.Empty);
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:请在此处查看相关问题

UPDATE

继死锁问题(在此问题中相关)之后,我已从Invoke切换到BeginInvoke(请参阅此处的解释).

另一个更新

关于第二个片段,我越来越倾向于使用'空委托'模式,通过使用空处理程序直接声明事件来解决"源"问题,如下所示:

event EventHandler MyEventRaised = delegate {};
Run Code Online (Sandbox Code Playgroud)

c# coding-style

18
推荐指数
1
解决办法
4743
查看次数

方法内联优化能否导致竞争条件?

正如这个问题所示: 使用扩展方法提升C#事件 - 这很糟糕吗?

我正在考虑使用此扩展方法来安全地引发事件:

public static void SafeRaise(this EventHandler handler, object sender, EventArgs e)
{
    if (handler != null)
        handler(sender, e);
}
Run Code Online (Sandbox Code Playgroud)

但是Mike Rosenblum在Jon Skeet的回答中提出了这个问题:

你们需要将[MethodImpl(MethodImplOptions.NoInlining)]属性添加到这些扩展方法中,否则你可以通过JITter优化将代理复制到临时变量的尝试,从而允许空引用异常.

我在发布模式下做了一些测试,看看当扩展方法没有用NoInlining标记时是否可以获得竞争条件:

int n;
EventHandler myListener = (sender, e) => { n = 1; };
EventHandler myEvent = null;

Thread t1 = new Thread(() =>
{
    while (true)
    {
        //This could cause a NullReferenceException
        //In fact it will only cause an exception in:
        //    debug x86, debug x64 and release x86
        //why doesn't it …
Run Code Online (Sandbox Code Playgroud)

.net inline-method race-condition

15
推荐指数
2
解决办法
674
查看次数

这是一种更好的方法来启动/调用事件而无需在C#中进行空检查吗?

我见过的大多数代码都使用以下方式来声明和调用事件触发:

public class MyExample
{
    public event Action MyEvent; // could be an event EventHandler<EventArgs>, too

    private void OnMyEvent()
    {
        var handler = this.MyEvent; // copy before access (to aviod race cond.)
        if (handler != null)
        {
            handler();
        }
    }

    public void DoSomeThingsAndFireEvent() 
    {
        // ... doing some things here
        OnMyEvent();
    }
 }
Run Code Online (Sandbox Code Playgroud)

甚至ReSharper也会按照上面提到的方式生成一个调用方法.

为什么不这样做:

public class MyExample
{
    public event Action MyEvent = delegate {}; // init here, so it's never null

    public void DoSomeThingsAndFireEvent() 
    {
        // ... doing …
Run Code Online (Sandbox Code Playgroud)

.net c# resharper events event-handling

12
推荐指数
3
解决办法
1108
查看次数

事件处理程序和空条件运算符

例如,实现INotifyPropertyChanged接口:

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    var handler = PropertyChanged;
    if (handler != null)
        handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Run Code Online (Sandbox Code Playgroud)

两件事情:

  1. 将事件复制到本地变量以防止多线程错误(这里有一些示例).如果不复制到局部变量,Resharper会发出通知:

可能的NullReferenceException

  1. 检查它是否为null,以防止 NullReferenceException

但是现在,我们可以使用?.运算符进行空值检查.如果我使用它,Resharper是空闲的: 没有错误

所以,问题是:ProperyChanged如果我使用空条件运算符,我应该将事件复制到局部变量吗?

.net c# resharper event-handling

7
推荐指数
1
解决办法
1852
查看次数