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

时间:2011-08-26 22:08:45

标签: c# events sizeof

抱歉没有时间尝试sizeof参加活动,但本着加强google-fu的精神....

  1. 将为具有事件字段的类实例添加什么实际内存大小?

  2. 每次订阅活动会使用什么实际内存?

  3. 我假设每个事件或订阅的单个指针,但我只是想确定。

    考虑这个例子:

    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...
        }
    }
    

2 个答案:

答案 0 :(得分:2)

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

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

他们存储:

  1. 调用已关闭代理的目标
  2. 函数的MethodBase指向
  3. 要调用的函数指针
  4. 一个辅助指针,存储指向的实际函数的地址(与open delegates一起使用以重新排列参数)
  5. 多播代理(在实践中,所有普通代理)再增加两个:

    1. 多播代理人指向的代理数组(null代表单个代表)
    2. _invocationCountIntPtr),以不同方式用于不同类型的代表
    3. 我正在撰写一篇博文,其中将更详细地解释这些领域。

答案 1 :(得分:0)

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