C# 从函数返回事件

C# 从函数返回事件,c#,events,C#,Events,从函数返回事件的语法是什么?(不调用事件,而是返回事件以便将其绑定到函数) 我有一个容器类,其中包含一个字典,每个成员都有一个事件 目的是能够写出这样的东西: Container c = new Container(); c.CreateEventForKey("a"); // Create the member in the dictionary c.EventForKey("a") += some_function; // Bind some_function to

从函数返回事件的语法是什么?(不调用事件,而是返回事件以便将其绑定到函数)

我有一个容器类,其中包含一个字典,每个成员都有一个事件

目的是能够写出这样的东西:

Container c = new Container();
c.CreateEventForKey("a");             // Create the member in the dictionary
c.EventForKey("a") += some_function;  // Bind some_function to the event in the "a" member
c.OnEventForKey("a","b");             // Calls some_function with argument "b"
public class Container {

  public class Member {
     public event Action<string> AnEvent;
     public void OnEvent( string v ) { if(AnEvent!=null) { AnEvent(v); } }
  }

  protected Dictionary<string,Member> members;

  // This seems to work OK.
  public void OnEventForKey(string k, string v) {
    if ( members.ContainsKey(k) ) { members[k].OnEvent(v); }
    else { /* report error */ }
  }

  // Can't get this to compile.
  public event Action<string> EventForKey(string k ) {
    if ( members.ContainsKey(k) ) { return members[k].AnEvent; }
    else { /* report error */ }
  }
}
容器类如下所示:

Container c = new Container();
c.CreateEventForKey("a");             // Create the member in the dictionary
c.EventForKey("a") += some_function;  // Bind some_function to the event in the "a" member
c.OnEventForKey("a","b");             // Calls some_function with argument "b"
public class Container {

  public class Member {
     public event Action<string> AnEvent;
     public void OnEvent( string v ) { if(AnEvent!=null) { AnEvent(v); } }
  }

  protected Dictionary<string,Member> members;

  // This seems to work OK.
  public void OnEventForKey(string k, string v) {
    if ( members.ContainsKey(k) ) { members[k].OnEvent(v); }
    else { /* report error */ }
  }

  // Can't get this to compile.
  public event Action<string> EventForKey(string k ) {
    if ( members.ContainsKey(k) ) { return members[k].AnEvent; }
    else { /* report error */ }
  }
}
公共类容器{
公共班级成员{
公共事件行动事件;
public void OnEvent(字符串v){if(AnEvent!=null){AnEvent(v);}
}
受保护的词典成员;
//这似乎行得通。
public void oneventforky(字符串k、字符串v){
if(members.ContainsKey(k)){members[k].OnEvent(v);}
else{/*报告错误*/}
}
//无法将其编译。
公共事件操作EventForKey(字符串k){
if(members.ContainsKey(k)){返回成员[k].AnEvent;}
else{/*报告错误*/}
}
}
我如何定义
EventForKey
,使其符合我的期望

从函数返回事件的语法是什么

你不能,很容易。像属性一样的事件本身并不是第一类的“对象”;他们是一个班级的成员。这里实际上没有一个类成员——你只是想把委托保存在字典中

<>你可以创建你自己的“事件类”容器,但是最好考虑其他设计,例如

c.Subscribe("a", SomeFunction);
c.OnEventForKey("a");

您可能想从中获得灵感。

为什么不直接返回会员并订阅其活动

public IMember MemberForKey(string key) // return IMember
{
    if (!members.ContainsKey(key))
        throw new Exception();

    return members[key];
}
然后订阅:

Container c = new Container();
c.CreateEventForKey("a");            
c.MemberForKey("a").AnEvent += some_function;
c.OnEventForKey("a", "b"); 
但是在
Member
类中有public
OnEvent
方法。为了禁止客户端引发事件,您可以创建只显示事件的接口。只需通过
成员
类实现此接口:

public interface IMember
{
    event Action<string> AnEvent;
} 
事件的目的是只为客户端提供两个操作—添加和删除处理程序。委托本身对客户端是隐藏的。您可以将其公开:

public Action<string> _action;
public Action\u Action;
但在这种情况下,任何客户端都可以调用它

更新:如果您想使用Subscribe/Remove语法,只需使用字典和处理程序:

public class Container
{
    private Dictionary<string, Action<string>> handlers = 
            new Dictionary<string, Action<string>>();

    public void CreateEventForKey(string key)
    {
        // with empty handler added you can avoid null check
        handlers.Add(key, (value) => { });
    }

    public void OnEventForKey(string key, string value)
    {
        if (!handlers.ContainsKey(key))
            throw new Exception();

        handlers[key](value);
    }

    public void Subscribe(string key, Action<string> handler)
    {
        if (!handlers.ContainsKey(key))
            throw new Exception();

        handlers[key] += handler;
    }
}
公共类容器
{
专用字典处理程序=
新字典();
public void CreateEventForKey(字符串键)
{
//添加空处理程序后,可以避免空检查
Add(key,(value)=>{});
}
public void OneEventWorkey(字符串键、字符串值)
{
如果(!handlers.ContainsKey(键))
抛出新异常();
处理程序[键](值);
}
public void Subscribe(字符串键、操作处理程序)
{
如果(!handlers.ContainsKey(键))
抛出新异常();
处理程序[键]+=处理程序;
}
}

以下是完整的工作示例:

class Program
{
    static void Main(string[] args)
    {
        Container c = new Container();
        c.CreateEventForKey("a");             // Create the member in the dictionary
        c.EventForKey("a").Add(str => Console.WriteLine(str));
        c.EventForKey("a").Add(str => Console.WriteLine(str.ToUpper()));
        c.OnEventForKey("a", "baa baa black sheep");

        Console.ReadLine();
        }
    }

    public class Container
    {

        public class Member
        {
        public List<Action<string>> AnEvent = new List<Action<string>>();
        public void OnEvent(string v)
        {
            if (AnEvent != null)
            {
                this.AnEvent.ForEach(action => action(v));
            }
        }

        public void AddEvent(Action<string> action)
        {
            this.AnEvent.Add(action);
        }
    }

    protected Dictionary<string, Member> members = new Dictionary<string,Member>();

    public void CreateEventForKey(string key)
    {
        this.members[key] = new Member();
    }

    // This seems to work OK.
    public void OnEventForKey(string k, string v)
    {
        if (members.ContainsKey(k)) { members[k].OnEvent(v); }
        else { /* report error */ }
    }

    public List<Action<string>> EventForKey(string k)
    {
        if (members.ContainsKey(k)) { return members[k].AnEvent; }
        else { throw new KeyNotFoundException(); }
    }
}
类程序
{
静态void Main(字符串[]参数)
{
容器c=新容器();
c、 CreateEventForKey(“a”);//在字典中创建成员
c、 EventForKey(“a”).Add(str=>Console.WriteLine(str));
c、 EventForKey(“a”).Add(str=>Console.WriteLine(str.ToUpper());
c、 Oneventforky(“a”、“baa baa害群之马”);
Console.ReadLine();
}
}
公营货柜
{
公共班级成员
{
public List AnEvent=新列表();
公共void OnEvent(字符串v)
{
if(AnEvent!=null)
{
this.AnEvent.ForEach(action=>action(v));
}
}
公共无效事件(行动)
{
this.AnEvent.Add(action);
}
}
受保护的字典成员=新字典();
public void CreateEventForKey(字符串键)
{
this.members[key]=新成员();
}
//这似乎行得通。
public void oneventforky(字符串k、字符串v)
{
if(members.ContainsKey(k)){members[k].OnEvent(v);}
else{/*报告错误*/}
}
公共列表EventForKey(字符串k)
{
if(members.ContainsKey(k)){返回成员[k].AnEvent;}
else{抛出新的KeyNotFoundException();}
}
}

不同之处在于,使用委托列表的行为类似于事件。

我认为您不能返回事件,但可以返回可以绑定到事件的委托。这就是你的意思吗?我想你只需要从一个事件的声明中删除event关键字,以及从EventForKey的返回类型中删除它。@IanNewson-我遇到问题的关键部分是
c.EventForKey(“a”)+=some\u函数。我宁愿写这篇文章,也不愿写那些繁琐的
c.members[“a”].AnEvent+=some_函数(因为我可以在第一个版本中添加错误检查和日志记录,但不能在第二个版本中添加)。您可以通过在容器类中创建索引器来将日志添加到第二个中。@IanNewson-仅删除
事件
位会生成类似这样的错误
运算符“+”不能与“function(string):void”类型的左侧和“function(string)”类型的右侧一起使用:void.
当您尝试使用
c.EventForKey(“a”)+=some_函数时呼叫。