【问题标题】:Using methods as a default parameter使用方法作为默认参数
【发布时间】:2020-02-22 17:21:25
【问题描述】:

我希望在我的自定义 XNA GUI 中创建一个 Button 类,它接受方法作为参数,类似于在 Python 的 tkinter 中您可以设置要使用 Button.config(command = a_method) 调用的函数。

我已经阅读了有关使用委托作为参数 hereherehere 的信息,但我似乎离让它工作更近了一步。我不完全理解代表是如何工作的,但是我尝试了几种不同的方法都没有成功,比如使用Func<int>? command = null 以便稍后测试command 是否为null 然后我会调用预设默认值,但是然后我得到一个Func cannot be nullable type 或类似的东西。

理想情况下,代码应该是这样的:

class Button
{
//Don't know what to put instead of Func
Func command;

// accepts an argument that will be stored for an OnClick event
public Button(Action command = DefaultMethod)
  {
    if (command != DefaultMethod)
    {
       this.command = command;
    }
  }
}

但似乎我尝试过的一切都没有成功。

【问题讨论】:

  • 什么UI框架?窗体? WPF?
  • Func<int> command = null 应该可以正常工作。 Func<T> 是引用类型,所以不能为空。
  • @CodingGorilla - 重要吗?
  • @CodingGorilla 这将是一个 XNA 自定义 GUI
  • 您是否想找出一种可以存储任何类型委托的数据类型?那是Delegate - 但我不确定我理解为什么/如何使用这个委托,Func<int>int 返回值将代表什么?似乎 Action 对于 parm 和 internal 类型都可以。如果这是构造函数的参数,为什么需要不同的东西来将它存储在属性中。

标签: c#


【解决方案1】:

默认参数必须是编译时间常数。在 C# 中,委托不能是常量。您可以通过在实现中提供自己的默认值来获得类似的结果。 (这里只使用 Winforms)

    private void button1_Click(object sender, EventArgs e)
    {
        Button(new Action(Print));
        Button();
    }

    public void Button(Action command = null)
    {
        if (command == null)
        {
            command = DefaultMethod;
        }
        command.Invoke();
    }

    private void DefaultMethod()
    {
        MessageBox.Show("default");
    }

    private void Print()
    {
        MessageBox.Show("printed");
    }

【讨论】:

  • 我不是 100% 肯定,但也许 93.2% 肯定,command() 会比command.Invoke() 快很多,因为后者使用反射。但无论哪种方式,强类型委托都不需要使用Invoke,您可以使用常规函数语法传递参数(或不传递参数)。
  • @jamietre 这只是语法糖。没有区别。
  • 愚蠢的 6.8%,总是让我看起来很糟糕。
【解决方案2】:

你得到的关于 Func<T> 不能为空的错误是正确的 - 它是一个引用类型,只有值类型可以为空。

要将Func<T> 参数默认为null,您可以简单地编写:

Func<int> command = null

【讨论】:

  • 有没有办法让&lt;int&gt; 类型更加动态?在玩了一会儿代码之后,我意识到它不会总是返回int,有时我想传递的某些函数中甚至不会有返回值。跨度>
  • @TankorSmash - 你可以保持它是通用的,具有泛型类型约束,但这不会让你将自己限制为数字类型,并且需要使类成为泛型。
【解决方案3】:

如果您对默认值感兴趣,这样的方法有用吗?

class Button
{
  //Don't know what to put instead of Func
  private readonly Func defaultMethod = ""?
  Func command;

  // accepts an argument that will be stored for an OnClick event
  public Button(Action command)
  {
    if (command != defaultMethod)
    {
       this.command = command;
    }
  }
}

【讨论】:

  • 嗯,这似乎也是一个不错的选择,但 Oded 的回答非常有效。 stackoverflow.com/questions/12097989/…谢谢
  • 您非常擅长链接到帖子和 cmets。常见问题解答中是否有关于如何执行此操作的部分? ...那反对票是怎么回事?
  • 刚刚对你投了赞成票,所以你又回到了 0,不知道你为什么是 -1。如果您单击答案/评论的时间码,您将获得指向它的链接。如果突出显示文本,然后单击链接按钮或在ask a question 屏幕中点击ctrl L,则可以将突出显示的文本设为链接
  • 不是我,但可能有人对你投了反对票,因为这段代码无法编译。没有类型Func,它需要一个泛型参数,并且您不能将Action 分配给Func&lt;T&gt;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-13
相关资源
最近更新 更多