相关疑难解决方法(0)

C#的隐藏功能?

在我从这个问题中学到以下内容后,我想到了这一点:

where T : struct
Run Code Online (Sandbox Code Playgroud)

我们C#开发人员都知道C#的基础知识.我的意思是声明,条件,循环,运算符等.

我们中的一些人甚至掌握了Generics,匿名类型,lambdas,LINQ等......

但是C#粉丝,瘾君子,专家几乎都不知道C#最隐藏的功能或技巧是什么?

以下是到目前为止显示的功能:


关键词

属性

c# hidden-features

1475
推荐指数
230
解决办法
68万
查看次数

C#事件和线程安全

UPDATE

从C#6开始,这个问题的答案是:

SomeEvent?.Invoke(this, e);
Run Code Online (Sandbox Code Playgroud)

我经常听到/阅读以下建议:

在检查事件之前,请务必复制事件null并将其触发.这将消除线程的潜在问题,其中事件变为null位于您检查null和触发事件的位置之间的位置:

// Copy the event delegate before checking/calling
EventHandler copy = TheEvent;

if (copy != null)
    copy(this, EventArgs.Empty); // Call any handlers on the copied list
Run Code Online (Sandbox Code Playgroud)

更新:我从阅读中了解到这可能还需要事件成员的优化,但Jon Skeet在他的回答中指出CLR不会优化副本.

但同时,为了解决这个问题,另一个线程必须做到这样的事情:

// Better delist from event - don't want our handler called from now on:
otherObject.TheEvent -= OnTheEvent;
// Good, now we can be certain that OnTheEvent will not run...
Run Code Online (Sandbox Code Playgroud)

实际的顺序可能是这种混合物:

// Copy the event delegate before checking/calling
EventHandler copy …
Run Code Online (Sandbox Code Playgroud)

c# events multithreading

230
推荐指数
6
解决办法
8万
查看次数

自动创建空的C#事件处理程序

无法在没有附加处理程序的C#中触发事件.因此,在每次调用之前,有必要检查事件是否为空.

if ( MyEvent != null ) {
  MyEvent( param1, param2 );
}
Run Code Online (Sandbox Code Playgroud)

我想保持我的代码尽可能干净,并摆脱那些空检查.我不认为这会影响性能,至少在我的情况下不会.

MyEvent( param1, param2 );
Run Code Online (Sandbox Code Playgroud)

现在我通过手动为每个事件添加一个空的内联处理程序来解决这个问题.这很容易出错,因为我需要记住这样做等等.

void Initialize() {
  MyEvent += new MyEvent( (p1,p2) => { } );
}
Run Code Online (Sandbox Code Playgroud)

有没有办法使用反射和一些CLR魔法自动为给定类的所有事件生成空处理程序?

c# clr events delegates

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

如何正确取消注册事件处理程序

在代码审查中,我偶然发现了这个(简化的)代码片段以取消注册事件处理程序:

 Fire -= new MyDelegate(OnFire);
Run Code Online (Sandbox Code Playgroud)

我认为这不会取消注册事件处理程序,因为它创建了一个之前从未注册过的新委托.但是搜索MSDN我发现了几个使用这个习惯用法的代码示例.

所以我开始了一个实验:

internal class Program
{
    public delegate void MyDelegate(string msg);
    public static event MyDelegate Fire;

    private static void Main(string[] args)
    {
        Fire += new MyDelegate(OnFire);
        Fire += new MyDelegate(OnFire);
        Fire("Hello 1");
        Fire -= new MyDelegate(OnFire);
        Fire("Hello 2");
        Fire -= new MyDelegate(OnFire);
        Fire("Hello 3");
    }

    private static void OnFire(string msg)
    {
        Console.WriteLine("OnFire: {0}", msg);
    }

}
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,发生了以下情况:

  1. Fire("Hello 1"); 按预期产生了两条消息.
  2. Fire("Hello 2");制作了一条消息!
    这使我确信取消注册的new代表工作!
  3. Fire("Hello 3");扔了一个NullReferenceException.
    调试代码显示Firenull …

.net c# events delegates

64
推荐指数
2
解决办法
5万
查看次数

是否在"null"引用(即没有订阅者的事件)上调用扩展方法?

邪恶还是不邪恶?

public static void Raise(this EventHandler handler, object sender, EventArgs args)
{
   if (handler != null)
   {
      handler(sender, args);
   }
}

// Usage:
MyButtonClicked.Raise(this, EventArgs.Empty);

// This works too! Evil?
EventHandler handler = null;
handler.Raise(this, EVentArgs.Empty);
Run Code Online (Sandbox Code Playgroud)

请注意,由于扩展方法的性质,如果MyButtonClicked为null,MyButtonClicked.Raise将不会抛出NullReferenceException.(例如,没有MyButtonClicked事件的监听器).

邪恶与否?

c# events extension-methods

59
推荐指数
5
解决办法
3106
查看次数

在事件调度之前检查null ...线程安全吗?

让我感到困惑的东西,但从来没有引起任何问题......推荐的事件发送方式如下:

public event EventHandler SomeEvent;
...
{
    ....
    if(SomeEvent!=null)SomeEvent();
}
Run Code Online (Sandbox Code Playgroud)

在多线程环境中,此代码如何保证另一个线程不会更改SomeEvent检查null和事件调用之间的调用列表?

c# events multithreading

35
推荐指数
3
解决办法
3万
查看次数

为事件定义空委托主体是一个好习惯吗?

可能重复:
在事件声明中添加匿名空委托是否有缺点?

为事件定义一个空委托主体是一个好习惯,这样您就不必担心引发没有事件处理程序的事件了吗?(无需检查事件是否为空).

像下面的代码:

public event EventHandler<LoadEventArgs> LoadedData = delegate { };
Run Code Online (Sandbox Code Playgroud)

c# events delegates

23
推荐指数
2
解决办法
1万
查看次数

C#代理是否是线程安全的?

如果你有一个带有委托成员变量的类实例,并且多个线程调用该委托(假设它指向一个长时间运行的方法),是否存在任何争用问题?

你需要锁定委托还是每个线程调用委托指向的方法是否安全,因为每个线程都有自己的调用堆栈?

c# multithreading delegates thread-safety

23
推荐指数
3
解决办法
2万
查看次数

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

我最近创建了这两个(不相关的)方法来替换我的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 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
查看次数