【问题标题】:Prevent Action being set to null (except privately)防止 Action 设置为 null(私下除外)
【发布时间】:2019-05-25 03:59:05
【问题描述】:

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

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

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;
}

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

因此我的问题是:

是否有任何“好”/惯用的方式来允许公开X.a += ...X.a -= ...,但不允许公开X.a = null;

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

我怀疑可能有一种方法可以在 X.a 周围放置一个包装属性,其设置器在 value == null 时抛出/不做任何事情,但即使这样有效,我觉得它仍然非常冗长。

如果 Action 无法做到这一点,但事件/委托(我对此知之甚少)可能会实现大致相似的事情,我也会感兴趣!

希望你们都在享受节日吗????

【问题讨论】:

    标签: c# null action private


    【解决方案1】:

    可能适合您,具体取决于您的需要

    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 有很多共同点,使用事件关键字和上述模式限制了分配 null 的能力,还有一些细微的其他差异,但是我会尝试寻找一些有信誉的来源。


    其他资源

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

    • Delegates and Events

      • 事件关键字

        event 关键字向编译器表明委托可以是 仅由定义类调用,其他类可以 仅使用 分别使用适当的 += 和 -= 运算符。

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

      • 事件是一种特殊的多播委托,它只能是 从声明它的类中调用。客户端代码 通过提供对方法的引用来订阅事件 应该在事件触发时调用。这些方法被添加到 委托的调用列表通过事件访问器,类似于 属性访问器,除了事件访问器被命名为 add 和 删除。

    • add (C# Reference)

      • add contextual 关键字用于定义自定义事件访问器 当客户端代码订阅您的事件时调用。如果你 提供自定义添加访问器,您还必须提供删除访问器。

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

    【讨论】:

    • 哇!我根本不熟悉这个结构,但它看起来很棒。我能读懂这种技术的名称吗?谢谢@TheGeneral,当我问这个问题时,我真的没想到会有解决方案,但现在很高兴我做到了?
    • 我不知道根据定义,事件只允许定义类设置为空。考虑到这一点,一个简单的public event Action MyAction; 在没有自定义事件访问器的情况下工作,允许我完全删除私有字段。没有比这更“好”的了!
    • @BilalAkil 这是正确的,我对此发表了评论并将其删除,但是我留下了详细的访问器,以便您可以看到如何添加更多功能(取决于您的需要)并离开作为普通动作的动作
    • 变量_myAciton 似乎始终拼写错误。这会更清楚地拼写正确,还是换位有目的?
    猜你喜欢
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 2019-12-02
    • 2013-03-22
    相关资源
    最近更新 更多