事件和事件订阅的数据大小是多少?

发布于 2024-12-02 01:22:58 字数 1356 浏览 1 评论 0原文

抱歉,没有时间在事件上尝试 sizeof,但本着增强 google-fu 的精神......

  1. 将向具有事件字段的类实例添加多少实际内存大小?

  2. 每次订阅事件将使用多少实际内存?

我假设每个事件或订阅都有单个指针,但我只是想确定一下。

考虑这个例子:

public class VertexMovedArgs : EventArgs {
    public Vertex theVert;
}

public class Vertex {
    // what size does this add to each Vertex?
    public event EventHandler<VertexMovedArgs> VertexMovedEvent;
    private Vector3 m_pos;
    public Vector3 pos {
        get { return m_pos; }
        set { 
            if ( value != m_pos ) {
                m_pos = value;
                EventHandler<VertexMovedArgs> tellEveryoneWeMoved = VertexMovedEvent;
                if ( handler != null ) {
                     VertexMovedArgs args = new VertexMovedArgs( this );
                     tellEveryoneWeMoved( this, args );
                }
            }
        }
    }
}

public class Mesh {
    private List<Vertex> m_verts = new List<Vertex>();
    public Vertex AddVert() {
        Vertex vert = new Vertex();
        // what size per-subscription does this add to this Mesh instance (or elsewhere)?
        vert.VertexMovedEvent += onVertexMoved;
        m_verts.Add( vert );
    }
    void onVertexMoved( object sender, VertexMovedArgs args ) {
         // play the vertex like a violin, etc...
    }
}

Apologies for not quite having the time to try sizeof on an event but in the spirit of enhancing google-fu....

  1. What actual memory size will be added to a class instance which has an event field?

  2. What actual memory will be used for each subscription to an event?

I assume single pointers for each event or subscription, but I just want to be sure.

Consider this example:

public class VertexMovedArgs : EventArgs {
    public Vertex theVert;
}

public class Vertex {
    // what size does this add to each Vertex?
    public event EventHandler<VertexMovedArgs> VertexMovedEvent;
    private Vector3 m_pos;
    public Vector3 pos {
        get { return m_pos; }
        set { 
            if ( value != m_pos ) {
                m_pos = value;
                EventHandler<VertexMovedArgs> tellEveryoneWeMoved = VertexMovedEvent;
                if ( handler != null ) {
                     VertexMovedArgs args = new VertexMovedArgs( this );
                     tellEveryoneWeMoved( this, args );
                }
            }
        }
    }
}

public class Mesh {
    private List<Vertex> m_verts = new List<Vertex>();
    public Vertex AddVert() {
        Vertex vert = new Vertex();
        // what size per-subscription does this add to this Mesh instance (or elsewhere)?
        vert.VertexMovedEvent += onVertexMoved;
        m_verts.Add( vert );
    }
    void onVertexMoved( object sender, VertexMovedArgs args ) {
         // play the vertex like a violin, etc...
    }
}

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

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

发布评论

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

评论(2

予囚 2024-12-09 01:22:58

事件字段只是一个对象引用。
在您将处理程序(委托)放入其中之前,每个类实例只会消耗一个指针大小(4 或 8 字节)。

委托实例有四个指针大小的字段,加上标准的 CLR 对象头。

它们存储:

  1. 调用封闭委托的目标
  2. 函数指向的 MethodBase 调用的
  3. 函数指针 存储
  4. 指向的实际函数地址的辅助指针(与开放委托一起使用以重新排列参数)

多播委托(实际上,所有普通委托)再添加两个:

  1. 由多播委托指向的委托数组(单个委托为 null
  2. _invocationCount(一个 IntPtr),针对不同的情况以不同的方式使用 。

我正在撰写一篇博客文章,该文章将更详细地解释这些字段

An event field is just an object reference.
Until you put a handler (delegate) in it, it will just consume one pointer-size (4 or 8 bytes) per class instance.

Delegate instance have four pointer-size fields, plus the standard CLR object header.

They store:

  1. The target to invoke a closed delegate
  2. The MethodBase of the function pointed to
  3. A function pointer to invoke
  4. An auxiliary pointer storing the address of the actual function pointed to (used with open delegates to rearrange parameters)

Multicast delegates (in practice, all normal delegates) add two more:

  1. An array of delegates pointed to by the multicast delegate (null for single delegates)
  2. _invocationCount (an IntPtr), used in different ways for different kinds of delegates

I'm in the middle of writing a blog post that will explain these fields in greater detail.

淡莣 2024-12-09 01:22:58

事件是一对方法,用于添加和删除订阅(实际上,它是三个方法,但第三个方法通常不用于任何用途)。事件本身不会向对象实例的大小添加任何内容,但添加/删除逻辑通常必须添加至少一个字段。事件最常见的默认实现是创建一个 MultiCastDelegate 类型的字段,并使用 Delegate.Combine 添加订阅,使用 Delegate.Remove 删除订阅。

An event is a pair of methods, for adding and removing subscriptions (actually, it's a trio of methods, but the third method is generally not used for anything). Events themselves do not add anything to the size of an object instance, but the add/remove logic will usually have to add at least one field. The most common default implementation of an event is to create a field of type MultiCastDelegate, and use Delegate.Combine to add subscriptions and Delegate.Remove to remove them.

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