防止操作被设置为空(私下除外)

Prevent Action being set to null (except privately)

我正在尝试以一种限制错误表面积的方式编写代码,即仅公开我希望 public 用户能够使用的内容。

在这种情况下,我有一个 Action,我希望 public 用户能够订阅或取消订阅。但是,我不希望这些用户能够对其他用户产生不利影响,即取消订阅所有人。

public class X
{
    public static Action a;
}

public class Mistake
{
    public void Oops()
    {
        X.a = null;
        // I just cleared ALL subscribers to X.a - not just my own subscription.
    }
}

解决此问题的一种方法是隐藏 Action 本身,而是将 sub/unsub 的方法提供给它:

public class X
{
    static Action _a;

    public static void SubA(Action cb) =>
        _a += cb;
    public static void UnsubA(Action cb) =>
        _a -= cb;
}

这行得通 - 犯类似错误已经难多了。但是,它比我想要的要冗长一点。

因此我的问题是:

是否有任何"nice"/惯用方式允许publicX.a += ...X.a -= ...,但不允许publicX.a = null;?

我尝试使用自动 属性 public static Action A { get; private set; },但正如预期的那样,这阻止了 +=-= publicly 的使用。

我怀疑可能有一种方法可以将 属性 包裹在 X.a 周围,而 value == null 的 setter throws/does 什么都没有,但即使行得通,我觉得它仍然很冗长。

如果 Action 做不到这一点,但 event/delegate 可以做一些大致相似的事情(我对此知之甚少),我也很感兴趣!

希望大家过得愉快

这个可能适合你,具体取决于你的需要

private Action _myActon;

public event Action MyAction
{
   add => _myActon += value;
   remove => _myActon -= value;
} 

...

MyAction += () => Console.WriteLine("test1");
MyAction += () => Console.WriteLine("test2");
MyAction += null;
//MyAction = null // compiler error;

...

_myActon.Invoke();
_myActon= null;

输出

test1
test2

对于编译器,Events 和 Delegate 有很多共同点,使用 event 关键字和上述模式限制了分配 null 的能力,还有一些细微的其他差异,但我会尝试找到一些有信誉的来源。


其他资源

活动和代表的详细描述,全家人在这里玩得很开心

  • Delegates and Events

    • The event Keyword

      The event keyword indicates to the compiler that the delegate can be invoked only by the defining class, and that other classes can subscribe to and unsubscribe from the delegate using only the appropriate += and -= operators, respectively.

  • How to: Implement Custom Event Accessors (C# Programming Guide)

    • An event is a special kind of multicast delegate that can only be invoked from within the class that it is declared in. Client code subscribes to the event by providing a reference to a method that should be invoked when the event is fired. These methods are added to the delegate's invocation list through event accessors, which resemble property accessors, except that event accessors are named add and remove.

  • add (C# Reference)

    • The add contextual keyword is used to define a custom event accessor that is invoked when client code subscribes to your event. If you supply a custom add accessor, you must also supply a remove accessor.

  • Delegates and Events (C# in Depth) Jon Skeet