闭包分配和引用传递

本文关键字:引用 分配 闭包 | 更新日期: 2023-09-27 18:34:05

我有一个函数,看起来像:

private void OnItemChannelsListChanged(object sender, ListChangedEventArgs args)
{
...
int index = args.NewIndex;
this.UpdateLogsOnNewAssignedUnit(ref index, channels);
}

哪里

private void UpdateLogsNewAssignedUnit(ref int index, List<IChannel> channels)
{
}

我使用一个名为堆分配查看器插件的插件(ps。我不隶属于他们(,这在编辑器上直观地显示堆分配。好吧,在下面的 ref int 索引参数中,它显示

闭包分配:"索引"、"通道"参数和"this"引用

据我了解,传递 int ref 不应该创建新副本!有谁知道为什么会发生这种情况,我能做些什么来避免它?

提前非常感谢

闭包分配和引用传递

由此

private void OnItemChannelsListChanged(object sender, ListChangedEventArgs args)

我认为您正在触发一个事件,您没有像您在第一行中所说的那样"具有功能"。

如果您从事件处理程序外部调用 UpdateLogsNewAssignedUnit 函数,我敢打赌分配不会发生。事件通常作为多播委托实现(它们不必是,但通常是(。由于是从事件处理程序调用它,因此编译器正在创建一个要在调用中使用的状态对象。有关详细信息,请参阅此文章。具体说来:

在引入 lambdas/anonymous 方法之前,想要调用接受委托的方法的 C# 开发人员通常需要定义一个类来存储其状态,向该类添加一个方法以执行其处理,然后在该状态实例上创建一个指向该方法的委托,例如

    public static void WriteOnPool(Stream stream, byte [] data) 
    { 
        var state = new WriteOnPoolState(); 
        state.stream = stream; 
        state.data = data; 
        ThreadPool.QueueUserWorkItem(new WaitCallback(state.Invoke)); 
    } 
    private sealed class WriteOnPoolState 
    { 
        public Stream stream; 
        public byte [] data; 
        public void Invoke(object ignored) 
        { 
            stream.Write(data, 0, data.Length); 
        }    
    }

现在在 C# 中,当您使用匿名方法或 lambda 时,编译器实际上最终会代表您生成与此几乎相同的代码,因此您不再需要手动执行此操作。 下面是为我之前使用匿名方法的示例生成的内容的反编译版本:

    public static void WriteOnPool(Stream stream, byte[] data) 
    { 
        var locals2 = new DisplayClass1(); 
        locals2.stream = stream; 
        locals2.data = data; 
        ThreadPool.QueueUserWorkItem( 
            new WaitCallback(locals2.<WriteOnPool>b__0)); 
    } 
    [CompilerGenerated] 
    private sealed class DisplayClass1 
    { 
        public Stream stream; 
        public byte[] data; 
        public void <WriteOnPool>b__0(object param0) 
        { 
            this.stream.Write(this.data, 0, this.data.Length); 
        } 
    }