委托分配是否在C#中创建新副本? [英] Does a delegate assignment create a new copy in C#?

查看:69
本文介绍了委托分配是否在C#中创建新副本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了有关C#和性能注意事项的文章(此处)

I read an article about C# and performance considerations (here)

在文章中,据说委托分配会触发内存分配,例如:

In the article, it is said that a delegate assignment triggers memory allocations, e.g:

每个单个局部变量赋值,例如"Func fn = Fn" 在堆上创建委托类Func的新实例

every single local variable assignment like "Func fn = Fn" creates a new instance of the delegate class Func on the heap

我想知道那是否是真的,那是如何实现的?我不熟悉引用分配可以触发C#中的额外内存分配的任何方式.

I wanted to know if that is true, and if it is - how is that implemented? i am not familiar with any way that a reference assignment can trigger extra memory allocation in C#.

推荐答案

本文正确.很容易测试:

The article is right. Quite easy to test:

static void Main(string[] args)
{
    Action<string[]> main = Main;
    Action<string[]> main2 = Main;
    Console.WriteLine(object.ReferenceEquals(main, main2)); // False
}

http://ideone.com/dgNxPn

如果您查看生成的IL代码 http://goo.gl/S47Wfy ,这很清楚会发生什么:

If you look at the IL code generated http://goo.gl/S47Wfy, it is quite clear what happens:

    IL_0002: ldftn void Test::Main(string[])
    IL_0008: newobj instance void class [mscorlib]System.Action`1<string[]>::.ctor(object, native int)
    IL_000d: stloc.0
    IL_000e: ldnull

    IL_000f: ldftn void Test::Main(string[])
    IL_0015: newobj instance void class [mscorlib]System.Action`1<string[]>::.ctor(object, native int)
    IL_001a: stloc.1

所以有两个 newobj instance void class [mscorlib]System.Action 1 ::.ctor(对象,本机int)`

So there are two newobj instance void class [mscorlib]System.Action1::.ctor(object, native int)`

请注意,这是违反直觉的:

Note that you are right that this is counterintuitive:

public class TestEvent
{
    public event Action Event;

    public TestEvent()
    {
        Action d1 = Print;
        Action d2 = Print;

        // The delegates are distinct
        Console.WriteLine("d1 and d2 are the same: {0}", object.ReferenceEquals(d1, d2));

        Event += d1;
        Event -= d2;

        // But the second one is able to remove the first one :-)
        // (an event when is empty is null)
        Console.WriteLine("d2 was enough to remove d1: {0}", Event == null);
    }

    public void Print()
    {
        Console.WriteLine("TestEvent");
    }
}

例如,对于event,您可以使用等效但不相同"的委托删除另一个委托,如示例所示.参见 https://ideone.com/xeJ6LO

With events for example, you can use an "equivalent but not the same" delegate to remove another delegate, as shown in the example. See https://ideone.com/xeJ6LO

这篇关于委托分配是否在C#中创建新副本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆