通过事件处理程序发送参数?

8

我实际上并没有发送参数,而是将一个类变量设置为某个值,然后在另一个方法中再次使用它。这是做事情的“最佳实践”吗?如果不是,我很想学习正确的方式。谢谢!参数可以/应该以其他方式发送吗?

private string PrintThis;

public void PrintIt(string input){
    PrintThis = input; //SETTING PrintThis HERE
    static private PrintDocument pd = new PrintDocument();
    pd.PrintPage += new PrintPageEventHandler(PrintDocument_PrintSomething);
    pd.Print();
}
private void PrintDocument_PrintSomething(Object sender, PrintPageEventArgs e) {
    e.Graphics.DrawString(PrintThis, new Font("Courier New", 12), Brushes.Black, 0, 0);
    //USING PrintThis IN THE ABOVE LINE
}
3个回答

10

闭包被引入到语言中来解决这个问题。

通过捕获适当的变量,你可以为它提供存储空间,使其“超越”包含它的方法:

// Note that the 'input' variable is captured by the lambda.
pd.PrintPage += (sender, e) => Print(e.Graphics, input);
...

static void Print(Graphics g, string input) { ... }

请注意,这只是一个便利功能。编译器解决此问题的方式非常类似于您自己的现有解决方案。 (有一些区别,例如,捕获的变量最终成为某个其他(生成的)类的字段。您现有的解决方案不会这样做:您每个类实例仅有一个“临时”存储位置,而不是每次调用PrintIt都有一个,这不好-例如,它不是线程安全的)

在Print方法中,是发送参数e.Graphics比仅发送e更好呢?还是说这并不是很重要的事情? - sooprise
@sooprise:这取决于你 - 我觉得它不需要整个“PrintPageEventArgs”,所以让我们只给它它需要的东西。抱歉,也许我不应该这样做“重构”; 它会分散注意力,远离实际问题。 - Ani
我有一个关于闭包的问题。我突然意识到我的代码在 OP 中是错误的。变量“pd”实际上是一个私有类变量,被“PrintIt”和“PrintDocument_PrintSomething”两个方法使用。既然它在两个方法之外定义并且被两个方法使用,那么“pd”是否也应该像“input”一样作为参数传递? - sooprise
@sooprise:这取决于它被分配到哪里?PrintDocument实例是逻辑上绑定到特定的PrintIt调用还是包含类的实例? - Ani
我认为它与包含类的特定实例相关联。 - sooprise
@sooprise:那么就没有理由去捕获它了。当然,这意味着PrintSomething方法不能再是静态的,因为它需要一个对包含对象的引用。当然,你可以保持它的静态性并捕获this,但那样会很奇怪。 - Ani

1

通常情况下不是这样的,但对于这个API(WinForms打印),这是通常的方法。

请注意,PrintThis不仅仅是一个变量,它还是您的“模型”或“文档”。


0

或者,您可以使用继承:

class MyPrintDocument : PrintDocument
{
  public delegate void MyPrintPageEventHandler (object, PrintPageEventArgs, object); // added context!
  public event MyPrintPageEventHandler MyPrintPageEvent;

  public MyPrintDocument (object context) { m_context = context; }
  protected void OnPrintPage (PrintPageEventArgs args)
  {
    // raise my version of PrintPageEventHandler with added m_context
    MyPrintPageEvent (this, args, m_context);
  }
  object m_context;
}

public void PrintIt(string input)
{
  MyPrintDocument pd = new MyPrintDocument(input);
  pd.MyPrintPage += new MyPrintPageEventHandler (PrintDocument_PrintSomething);
  pd.Print();
}

private void PrintDocument_PrintSomething(Object sender, PrintPageEventArgs e, object context)
{
   e.Graphics.DrawString((string) context, new Font("Courier New", 12), Brushes.Black, 0, 0);
}

继承是“更好的实践”吗?(与闭包相比) - sooprise
@sooprise:这在所有版本的C#中都可以运行,闭包是最近引入的(3.5?)。至于“更好的实践”,很难说。 - Skizz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接