C# 是否将值传递给 Lambda?

发布于 2024-07-19 23:10:30 字数 368 浏览 4 评论 0原文

我有一些代码,

int count = 0;

list.ForEach(i => i.SomeFunction(count++));

这似乎不会增加计数。 这里count是按值传递的吗? 如果我在 lambda 中使用 {} 有什么区别吗?

int count = 0;

list.ForEach(i => 
            {
                    i.SomeFunction(count++);
            });

更新 1

抱歉,我的错误,它确实更新了原始计数。

I have some code,

int count = 0;

list.ForEach(i => i.SomeFunction(count++));

This seems to not increment count. Is count passed by value here? Is there any difference if I use the {} in the lambda?

int count = 0;

list.ForEach(i => 
            {
                    i.SomeFunction(count++);
            });

Update 1

Sorry, my mistake, it does update the original count.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

美人如玉 2024-07-26 23:10:30

count 是一个 int,而 int 是值类型,这意味着它们确实是按值传递的。 您的第一个示例和第二个示例之间没有语义差异。

(也就是说,在我看来它应该递增 count,因为它应该捕获原始引用直至闭包。澄清一下 - 尽管 count 将按值传递到 SomeFunction ,当您在表达式中使用它们时,事物不会“传递”到您的 lambda 表达式中——它们与外部变量是相同的引用。)

count is an int, and ints are value types, which means they are indeed passed by value. There is no semantic difference between your first and second example.

(That said, it looks to me like it should be incrementing count, since it should be capturing the original reference as far as the closure. To clarify -- although count will be passed by value down into SomeFunction, things don't get "passed" into your lambda expression when you use them inside the expression -- they are the same reference as the external variable.)

水水月牙 2024-07-26 23:10:30

在这两种情况下,您都在创建所谓的闭包。 本质上,count 被包装在一个类中,并且该类由 lambda 表达式使用。

Bill Wagner 有一本很棒的书,名为更有效的 C#,他有一篇博客文章更详细地描述了闭包

In both cases you are creating what's called a closure. Essentially, count is being wrapped in a class and that class is being used by the lambda expression.

Bill Wagner has a great book called More Effective C# and he has a blog post that describes closures in more detail.

爱的故事 2024-07-26 23:10:30

在您的情况下,变量计数由 lambda 表达式捕获。 对 count 的任何更改都将对调用者可见。 因此,例如:

int count = 0;
list.ForEach(i => i.SomeFunction(count++));
Console.WriteLine(count);

将显示列表的大小,因为在每次迭代中您都会增加 count

但是,对 SomeFunction 的调用会按 value< 传递 count++ 的计算值(即递增之前 count 的值) /em> 到 SomeFunction。 换句话说,SomeFunction 无法更改 count 的值。

有关闭包和变量捕获的更多信息,请参阅我的闭包文章

The variable count is captured by the lambda expression in your situation. Any changes to count will be visible to the caller. So, for instance:

int count = 0;
list.ForEach(i => i.SomeFunction(count++));
Console.WriteLine(count);

will display the size of the list, because on each iteration you're incrementing count.

However, the call to SomeFunction passes the evaluated value of count++ (which is the value of count before the increment) by value to SomeFunction. In other words, SomeFunction can't change the value of count.

For more on closures and variable capture, see my closures article.

夏至、离别 2024-07-26 23:10:30

这应该增加,证明:

class Foo
{
    public void SomeFunction(int i) { }
}
static void Main()
{
    int count = 0;
    List<Foo> list = new List<Foo> {new Foo()};
    list.ForEach(i => i.SomeFunction(count++));
    Console.WriteLine(count); // 1
}

lambda 的作用(如前所述)“捕获”计数,本质上使代码如下:

class Foo
{
    public void SomeFunction(int i) { }
}
class CaptureScope
{
    public int count;
    public void AnonMethod(Foo foo)
    {
        foo.SomeFunction(count++);
    }
}
static void Main()
{
    CaptureScope scope = new CaptureScope();
    scope.count = 0;
    List<Foo> list = new List<Foo> {new Foo()};
    list.ForEach(scope.AnonMethod);
    Console.WriteLine(scope.count); // 1
}

上面是编译器如何解释委托 lambda 的粗略近似。 正如您所看到的,count 是类中的一个字段,并且会递增。

That should increment, proof:

class Foo
{
    public void SomeFunction(int i) { }
}
static void Main()
{
    int count = 0;
    List<Foo> list = new List<Foo> {new Foo()};
    list.ForEach(i => i.SomeFunction(count++));
    Console.WriteLine(count); // 1
}

The lambda acts (as already stated) to "capture" count, essentially making the code like:

class Foo
{
    public void SomeFunction(int i) { }
}
class CaptureScope
{
    public int count;
    public void AnonMethod(Foo foo)
    {
        foo.SomeFunction(count++);
    }
}
static void Main()
{
    CaptureScope scope = new CaptureScope();
    scope.count = 0;
    List<Foo> list = new List<Foo> {new Foo()};
    list.ForEach(scope.AnonMethod);
    Console.WriteLine(scope.count); // 1
}

The above is a rough approximation of how the compiler interprets a delegate lambda. As you can see, the count is a field on a class, and is incremented.

混浊又暗下来 2024-07-26 23:10:30

我想在这里添加一个小修正。 变量 count 既不是通过值传递,也不是通过对 lambda 表达式的引用传递,因为它不是参数。 相反,该值由闭包中的 lambda捕获

你应该看看雷蒙德关于这个主题的系列
- http://blogs.msdn.com/oldnewthing/archive /2006/08/02/686456.aspx

I wanted to add a small correction here. The variable count is neither passed by value or by reference to the lambda expression because it is not a parameter. The value is instead captured by the lambda in a closure.

You should check out Raymond's series on the subject
- http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx

离不开的别离 2024-07-26 23:10:30

这应该将计数捕获为闭包

That should capture (close over) count as a closure.

絕版丫頭 2024-07-26 23:10:30

不,没有区别。 参数通常按值传递,除非您在用于 lambda 的委托定义中明确将其设置为“ref”或“out”。

No, there is no difference. Arguments are usually by value, unless you explicitly make it "ref" or "out" in the delegate definition used for the lambda.

在巴黎塔顶看东京樱花 2024-07-26 23:10:30

Lambda 是匿名函数,因此遵循与将参数传递给函数相同的规则。

Lambdas are anonymous functions, and as such, follow the same rules as passing arguments into a function.

只想待在家 2024-07-26 23:10:30

在本例中,count 变量被捕获。 即使它是一个struct,捕获的变量的行为就像它的引用。 因此,您肯定会在 foreach 之后看到递增的 count

In this case, the count variable is captured. Even if it's a struct the captured variable acts like its a reference. So, you would certainly see an incremented count after the foreach.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文