【问题标题】:Why I can add method with default argument to event Action?为什么我可以将带有默认参数的方法添加到事件操作?
【发布时间】:2013-03-23 13:51:41
【问题描述】:

考虑类

class FirstClass 
{
    //Some fields, ctors and methods
    ...
    public event Action Test
    {
        add
        {
            var method = value.Method;
            var parameters = method.GetParameters (); //Count == 1
            // (1)
            //I don't know anything about value so I think I can pass null as argument list because it's Action, not Action<T>
            //And we get Reflection.TargetParameterCountException here.
            method.Invoke (value.Target, null); 
            //Instead of calling Invoke as done above, we should call it like that:
            // (2)
            method.Invoke (value.Target, new object[] { null });
            //But since it's Action, we should be able to call it with (1) not with (2)
        }
        remove
        {
            ...
        }
    }
}

还有一个班级

class SecondClass
{
    public void TestMethod (Action action = null)
    {
        ...
    }
    public void OtherMethod ()
    {
        var a = new FirstClass ();
        a.Test += TestMethod;
    }
}

恕我直言:在类型系统级别不应允许将具有默认参数的方法添加到不带参数的委托。 为什么是允许的?

P.S. 您不仅可以在 add { } 访问器中执行此操作,还可以在任何其他地方执行此操作,上面的代码只是示例。

【问题讨论】:

  • 我已经尝试了您的代码,编译器在 a.Test += TestMethod 行上抛出一个错误,指出它是不允许的,因为 TestMethod 与委托 System.Action 不匹配。你确定你的代码可以编译吗?
  • 你不能编译那个? pastie.org/7277752
  • 不,那不会编译。我正在使用 Visual Studio 2012,我收到编译错误“'TestMethod' 没有重载匹配委托'System.Action'”。将事件声明更改为公共事件 Action TestEvent 可修复编译错误。
  • 嗯,我正在使用 MonoDevelop,所以也许它只是单声道错误/功能。

标签: c# methods delegates mono


【解决方案1】:

这不应该编译。

Delegate Action 有一个零参数的标志,并且没有返回值:

public delegate void Action();

所以只能给它分配零参数而不是返回值的方法。你的第二堂课SecondClass.TestMethod 确实有一个Action 类型的参数(我猜是为了让这一切变得混乱;))。因此该方法将与另一个 Action 委托(其中 T = Action)兼容:

public delegate void Action<T>();

如果您甚至尝试调用 FirstClass.Test.Add,并且尝试进行两次 Invoke 调用,那么第一次应该会失败。

为什么?该方法是SecondClass.TestMethodMethodInfo。此方法至少需要一个参数。此参数必须在提供给调用方法的对象数组内。但是,在您的第一次通话中,您没有对象数组;您的对象数组设置为空。并且设置为 null 的对象数组不能容纳任何东西,甚至不能容纳 0 个元素,更不用说 1 个具有 null 的元素了。

第二个 Invoke 确实有一个带有一个元素的对象数组,具有 null。

【讨论】:

    猜你喜欢
    • 2014-05-03
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-12
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    相关资源
    最近更新 更多