Каковы размеры данных для событий и подписки на события? - PullRequest
0 голосов
/ 27 августа 2011

Извиняюсь за то, что не успел попробовать 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...
    }
}

Ответы [ 2 ]

2 голосов
/ 27 августа 2011

Поле события - это просто ссылка на объект.
Пока вы не поместите в него обработчик (делегат), он будет использовать только один размер указателя (4 или 8 байт) на экземпляр класса.

Экземпляр делегата имеет четыре поля размера указателя плюс стандартный заголовок объекта CLR.

Они хранят:

  1. Цель вызова закрытого делегата
  2. MethodBase функции, указывающей на
  3. Указатель на функцию для вызова
  4. Вспомогательный указатель, хранящий адрес фактической указанной функции (используется с открытыми делегатами для перестановки параметров)

Многоадресные делегаты (на практике все обычные делегаты) добавляют еще два:

  1. Массив делегатов, на которые указывает многоадресный делегат (null для отдельных делегатов)
  2. _invocationCount (IntPtr), используется по-разному для разных типов делегатов

Я сейчас пишу в блоге, который более подробно объясняет эти поля.

0 голосов
/ 27 августа 2011

Событие - это пара методов для добавления и удаления подписок (на самом деле это три метода, но третий метод вообще ни для чего не используется). Сами события ничего не добавляют к размеру экземпляра объекта, но логика добавления / удаления обычно должна добавлять хотя бы одно поле. Наиболее распространенной реализацией события по умолчанию является создание поля типа MultiCastDelegate и использование Delegate.Combine для добавления подписок и Delegate.Remove для их удаления.

...