我的功能如下:
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)
{
}
我使用了一个名为Heap Allocations Viewer插件的插件(ps。我不隶属于他们),它在编辑器上直观地显示堆分配。好吧,在它下面的ref int index参数中显示
关闭分配:'index','channels'参数和'this'参考
根据我的理解,传递int ref不应该创建新副本! 有谁知道它为什么会发生,我该怎么做才能避免呢?
非常感谢提前
答案 0 :(得分:2)
从此
private void OnItemChannelsListChanged(object sender, ListChangedEventArgs args)
我认为你正在开一个活动,你没有像你在第一行所说的那样“有一个功能”。
如果从事件处理程序外部调用UpdateLogsNewAssignedUnit函数,我会打赌不会发生分配。事件通常实现为多播代理(它们不一定是,但通常是)。由于您是从事件处理程序调用它,因此编译器正在创建要在调用中使用的状态对象。有关详细信息,请参阅this文章。具体做法是:
在引入lambdas /匿名方法之前,想要调用接受委托的方法的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);
}
}