Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在定义自删除事件操作时获得编译时类型安全性<&燃气轮机;没有显式键入处理程序的完整类型的处理程序?_C#_Events_.net 4.5_Type Safety - Fatal编程技术网

C# 如何在定义自删除事件操作时获得编译时类型安全性<&燃气轮机;没有显式键入处理程序的完整类型的处理程序?

C# 如何在定义自删除事件操作时获得编译时类型安全性<&燃气轮机;没有显式键入处理程序的完整类型的处理程序?,c#,events,.net-4.5,type-safety,C#,Events,.net 4.5,Type Safety,我在类中有一个简单的事件处理程序,如下所示: public class Eventable { public event Action<Eventable, TypeB> OnMagic; // ... } 是否有其他方法可以实现这一点,完全隐藏事件处理程序的类型,而不抛出类型安全性? 谢谢。有什么问题吗: Action<Eventable, TypeB> myHander = null; myHandler = (that, myB) => {

我在类中有一个简单的事件处理程序,如下所示:

public class Eventable
{
    public event Action<Eventable, TypeB> OnMagic;

    // ...
}
是否有其他方法可以实现这一点,完全隐藏事件处理程序的类型,而不抛出类型安全性? 谢谢。

有什么问题吗:

Action<Eventable, TypeB> myHander = null;
myHandler = (that, myB) => { eventable.OnMagic -= myHandler };
eventable.OnMagic += myHandler;
Action myHander=null;
myHandler=(即,myB)=>{eventable.OnMagic-=myHandler};
eventable.OnMagic+=myHandler;
?

毕竟,你已经知道了
myHander
的类型,所以你不需要经历
HandlerOf(t)
(这可能对处理匿名类型有用…我在你的代码中没有看到任何类型)

有什么问题:

Action<Eventable, TypeB> myHander = null;
myHandler = (that, myB) => { eventable.OnMagic -= myHandler };
eventable.OnMagic += myHandler;
Action myHander=null;
myHandler=(即,myB)=>{eventable.OnMagic-=myHandler};
eventable.OnMagic+=myHandler;
?


毕竟,您已经知道了
myHander
的类型,因此不需要对
HandlerOf(t)
进行扭曲(这可能有助于处理匿名类型…我在您的代码中没有看到任何)

如果您想注册一个操作,当调用unregister时,您可以执行以下操作:

public class Eventable
{
    public event Action<Eventable, int> OnMagic;

    public void Magic(int i)
    {
        OnMagic?.Invoke(this, i);
    }

    public void RegisterMagic(Action<Eventable, int> action)
    {
        Action<Eventable, int> _action = null;
        _action = (_e, i) =>
        {
            action(_e, i);
            OnMagic -= _action;
        };
        OnMagic += _action;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Eventable e = new Eventable();
        e.RegisterMagic((ev, i) => Console.WriteLine(i));
        e.RegisterMagic((ev, i) => Console.WriteLine(i * i));

        e.Magic(4);
        e.Magic(5);
    }
}

Output:
    4
    16
公共类可事件
{
公共事件行动;
公共虚空魔法(int i)
{
调用(这个,我);
}
公共无效登记处(行动)
{
Action _Action=null;
_行动=(_e,i)=>
{
行动(_e,i);
OnMagic-=\u作用;
};
OnMagic+=\u动作;
}
}
班级计划
{
静态void Main(字符串[]参数)
{
可事件e=新的可事件();
e、 RegisterMagic((ev,i)=>Console.WriteLine(i));
e、 RegisterMagic((ev,i)=>Console.WriteLine(i*i));
e、 魔术(4);
e、 魔术(5);
}
}
输出:
4.
16

注意:我将
RegisterMagic
放在
Eventable
类中,以防此行为仅适用于
Evantable
对象。但这可以根据您的需要进行修改。

如果您想注册一个操作,当调用“注销”时,您可以执行以下操作:

public class Eventable
{
    public event Action<Eventable, int> OnMagic;

    public void Magic(int i)
    {
        OnMagic?.Invoke(this, i);
    }

    public void RegisterMagic(Action<Eventable, int> action)
    {
        Action<Eventable, int> _action = null;
        _action = (_e, i) =>
        {
            action(_e, i);
            OnMagic -= _action;
        };
        OnMagic += _action;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Eventable e = new Eventable();
        e.RegisterMagic((ev, i) => Console.WriteLine(i));
        e.RegisterMagic((ev, i) => Console.WriteLine(i * i));

        e.Magic(4);
        e.Magic(5);
    }
}

Output:
    4
    16
公共类可事件
{
公共事件行动;
公共虚空魔法(int i)
{
调用(这个,我);
}
公共无效登记处(行动)
{
Action _Action=null;
_行动=(_e,i)=>
{
行动(_e,i);
OnMagic-=\u作用;
};
OnMagic+=\u动作;
}
}
班级计划
{
静态void Main(字符串[]参数)
{
可事件e=新的可事件();
e、 RegisterMagic((ev,i)=>Console.WriteLine(i));
e、 RegisterMagic((ev,i)=>Console.WriteLine(i*i));
e、 魔术(4);
e、 魔术(5);
}
}
输出:
4.
16


注意:我将
RegisterMagic
放在
Eventable
类中,以防此行为仅适用于
Evantable
对象。但这可以根据需要进行修改。

HandlerOf
接收两个参数,但只传递一个。您试图做的是在容器类的范围之外引发一个事件?因为如果是这样的话,你就不能这么做。对不起,忘记删除那个参数了。我不是想提出这件事,我只希望向该事件添加一个处理程序。为什么调用
HandlerOf
进行注册而不是直接注册到
eventable.OnMagic+=…
,因为它需要删除自身,因此需要删除引用。带有类似事件的字段的
类eventable
将事件的支持字段隐藏为私有类级别变量(字段)的类型。例如,可以在magicbackingfield{get{return OnMagic;}}上发布
公共操作
,但我认为这不是一个好主意。请参阅spender的答案。
HandlerOf
接收两个参数,但只传递一个。您试图做的是在容器类的范围之外引发一个事件?因为如果是这样的话,你就不能这么做。对不起,忘记删除那个参数了。我不是想提出这件事,我只希望向该事件添加一个处理程序。为什么调用
HandlerOf
进行注册而不是直接注册到
eventable.OnMagic+=…
,因为它需要删除自身,因此需要删除引用。带有类似事件的字段的
类eventable
将事件的支持字段隐藏为私有类级别变量(字段)的类型。例如,可以在magicbackingfield{get{return OnMagic;}}上发布
公共操作
,但我认为这不是一个好主意。请参阅spender提供的答案。当类型为Action时,它会变得很难读取,我不认为using alias指令会解决这个问题,我想完全隐藏这些类型名。我怀疑这不会编译,除非您将
myHandler
初始化为一些伪值,例如
null
@spencer您对匿名类型的看法是正确的,但你的建议正是我想要避免的。@gxtaillon也许,但至少这是一个已知的范例。通过
HandlerOf(T)
(如果你能让它工作起来的话)的通用魔法,为所有这些添加一层间接层可能会让你更容易,但对任何访问你的代码的人(甚至是你,在2年内…)来说,都会更加困惑@斯宾塞:我理解,但我还没有发现任何迹象表明这是可能的,所以现在我会放手。解决我的问题的方法类似于C++的类型别名。这将允许我使用OnMagicHandlerType=Action将实际类型放入
,声明
公共事件OnMagicHandlerType OnMagic并干净地将其用作
var myHandler=default(Eventable.OnMagicHandlerType)当类型为Ac时