【问题标题】:Why is "MyEvent" always make compiler error "CS0070"?为什么“MyEvent”总是使编译器错误“CS0070”?
【发布时间】:2021-10-15 21:15:09
【问题描述】:

如何修复 CS0070 错误?

错误:

错误 CS0070 事件“Demo.MyEvent”只能出现在 += 或 -= 的左侧(在“Demo”类型中使用时除外)

代码:

class Demo
{
    public event EventHandler<int> MyEvent;

    public void Handler(object sender, int arg)
    {
        Console.WriteLine($"I just go {arg}");
    }
}


class Program
{
    static void Main(string[] args)
    {
        var demo = new Demo();

        var eventInfo = typeof(Demo).GetEvent("MyEvent");
        var handlerMethod = demo.GetType().GetMethod("Handler");

        var handler = Delegate.CreateDelegate(
            eventInfo.EventHandlerType,
            null,
            handlerMethod
        );

        eventInfo.AddEventHandler(demo, handler);
        demo.MyEvent?.Invoke(null, 312);
    }
}

错误行:

demo.MyEvent?.Invoke(null, 312);

【问题讨论】:

  • 因为,正如错误消息所述,只有Demo 被允许Invoke 事件。

标签: c# events delegates


【解决方案1】:

类似字段的事件(这是)对于声明类型来说就像一个字段,但对于外部类型来说就像一个事件添加/删除对。这意味着只有声明事件的类型才能执行诸如访问当前值之类的操作,这是调用支持委托所必需的。基本上,有一个隐藏的私有字段,编译后声明您看不到 - 当您从类型内访问事件时,您直接与该字段交谈。但是当从外部访问事件时,您必须通过访问器 - 而 C# 提供的唯一访问器是添加和删除访问器。

如果您在Demo 中编写方法,该方法将能够调用事件。

【讨论】:

    【解决方案2】:

    事件必须直接从它的类中调用,如果您的场景需要从事件外部调用它,那么只需使用方法封装您的事件:

    public void InvokeMyEvent(int value)
    {
        MyEvent?.Invoke(this,value);
    }
    

    然后使用短代码轻松订阅:

    demo.MyEvent += MyEvent_EventHandeler;
    private void My_EventHandeler(object sender, int e)
    {
        //enter code here
    }
    

    使用 lambda 甚至更短:

    demo.MyEvent += (s, e) =>
    {
      //enter code here
    }
    

    从任何地方调用它:

    demo.InvokeMyEvent(321);
    

    【讨论】:

      【解决方案3】:

      谢谢Marc Gravell先生。

      对不起,我的代码错了。

      正确的代码是:

      namespace ConsoleApp1
      {
          class Demo
          {
              public event EventHandler<int> MyEvent;
      
              public void Handler(object sender, int arg)
              {
                  Console.WriteLine($"I just go {arg}");
              }
      
              public static void Main(string[] args)
              {
                  var demo = new Demo();
      
                  var eventInfo = typeof(Demo).GetEvent("MyEvent");
                  var handlerMethod = demo.GetType().GetMethod("Handler");
      
                  var handler = Delegate.CreateDelegate(
                      eventInfo.EventHandlerType,
                      null,
                      handlerMethod
                  );
      
                  eventInfo.AddEventHandler(demo, handler);
                  demo.MyEvent?.Invoke(null, 312);
              }
          }
      }
      

      【讨论】:

      • 你为什么要在这里使用反射?这是不好的做法,因为由于性能问题,必须在某些情况下避免反射。创建事件不是为了这样使用。
      • @sabsab 此代码仅用于测试和提问,不用于实际项目。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-13
      • 2021-10-15
      • 1970-01-01
      • 1970-01-01
      • 2014-06-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多