调用没有参数的代理但使用本地参数c#

时间:2010-02-25 02:17:52

标签: c# parameters delegates lazy-evaluation

我发现自己做了很多事情,我不知道是否有任何副作用,但在WinForms C#应用程序中考虑以下内容。 (请原谅任何错误,因为我输入了代码,而不是复制粘贴任何内容)

int a = 1;
int b = 2;
int c = 3;
this.Invoke((MethodInvoker)delegate()
{
    int lol = a + b + c;
});

那有什么不对吗?或者我应该做很长的路> _<

int a = 1;
int b = 2;
int c = 3;
TrippleIntDelegate ffs = new TrippleIntDelegate(delegate(int a_, int b_, int c_)
{
   int lol = a_ + b_ + c_;
});

this.Invoke(ffs);

不同之处在于参数传递而不是使用局部变量,一些非常甜蜜的.net魔法。我想我曾经看过它上面的反射器,它创建了一个全新的类来保存这些变量。

重要吗?我可以偷懒吗?

编辑:注意,显然不关心返回值。否则我必须使用我自己的类型委托,虽然我仍然可以使用局部变量而不传入它!

4 个答案:

答案 0 :(得分:3)

你使用它的方式,并没有真正有所作为。但是,在第一种情况下,您的匿名方法是捕获变量,如果您不知道自己在做什么,这会产生很大的副作用。例如:

// No capture :
int a = 1;
Action<int> action = delegate(int a)
{
    a = 42; // method parameter a
});
action(a);
Console.WriteLine(a); // 1

// Capture of local variable a :
int a = 1;
Action action = delegate()
{
    a = 42; // captured local variable a
};
action();
Console.WriteLine(a); // 42

答案 1 :(得分:1)

只要您了解到您正在进行延迟执行,传入局部变量就没有错。如果你这样写:

int a = 1;
int b = 2;
int c = 3;
Action action = () => Console.WriteLine(a + b + c);
c = 10;
action();  // Or Invoke(action), etc.

这个输出将是13,而不是6.我想这将是托马斯所说的对应物;如果您在委托中读取本地人,它将使用操作实际执行时变量所持有的任何值,而不是声明时。如果变量保存引用类型并且您异步调用委托,则可以生成一些有趣的结果。

除此之外,将局部变量传递给委托有很多充分的理由;除此之外,它还可用于简化线程代码。只要你不熟悉它就可以了。

答案 2 :(得分:1)

好吧,所有其他答案似乎都忽略了多线程上下文以及在这种情况下出现的问题。如果您确实在WinForms中使用它,那么您的第一个示例可能会抛出异常。根据您尝试从代理中引用的实际数据,实际调用代码的线程可能有也可能无权访问您关闭的数据。

另一方面,您的第二个示例实际上是通过参数传递数据。这允许Invoke方法正确地跨越线程边界封送数据并避免那些讨厌的线程问题。如果你从后台工作者那里调用Invoke,那么你应该使用类似你的第二个例子(尽管我会选择使用Action&lt; T,...&gt;和Func&lt; T,...&gt;代表尽可能而不是创建新代表。)

答案 3 :(得分:0)

从风格的角度来看,我会选择参数传递方式。它表达的意图更容易通过args instad采取任何类型的环境(也使其更容易测试)。我的意思是,你可以这样做:

public void Int32 Add()
{
    return this.Number1 + this.Number2
}

但它既不可测试也不清楚。使用params的sig对于其他方法正在做的更清楚......它添加了两个数字:不是一组数字或其他任何数字。

我经常使用parms之类的parms来做这件事,无论如何都要通过ref使用,不需要明确地'返回':

public List<string> AddNames(List<String> names)
{
    names.Add("kevin");
    return names;
}

即使名称集合由ref传递,因此不需要显式返回,我更清楚的是该方法获取列表并添加到它,然后将其返回。在这种情况下,以这种方式写信号有没有技术理由,但对我而言,就清晰度和可维护性而言,有充分的理由。