Closed Houtamelo closed 11 months ago
Hi! The reason for allocation is the delegate creation to store the actual event subscribers list (events may have arbitrary number of subscriptions). Under public event Action<CharacterStateMachine> CharacterSetup;
event declaration there is a hidden field of Action<CharacterStateMachine>
type. Every time you subscribe to this event there is Delegate.Combine
invocation happening to combine the current Action<CharacterStateMachine>
instance stored in the field with the Action<CharacterStateMachine>
instance you've provided when subscribing to the event. Delegates in .NET are immutable so the only way to get the delegate instance consisting all of the invocables combined is to allocate the new delegate instance, this is exactly what Delegate.Combine
performs. The inspection message contains "may" word because Delegate.Combine
do not allocates new instances if one of it's the arguments is null
- in this case it is safe to just return another arguments instead (thx to immutability). So if your event
contains zero subscribers (null
is stored in Action<CharacterStateMachine>
hidden field) or you're somehow subscribing with null
as a Action<CharacterStateMachine>
reference (this is safe in C# and will not trigger NRE) - there will be no actual allocation on both event subscription or unsubscription.
I'll try to clarify HeapView's message in this case.
Hi! The reason for allocation is the delegate creation to store the actual event subscribers list (events may have arbitrary number of subscriptions). Under
public event Action<CharacterStateMachine> CharacterSetup;
event declaration there is a hidden field ofAction<CharacterStateMachine>
type. Every time you subscribe to this event there isDelegate.Combine
invocation happening to combine the currentAction<CharacterStateMachine>
instance stored in the field with theAction<CharacterStateMachine>
instance you've provided when subscribing to the event. Delegates in .NET are immutable so the only way to get the delegate instance consisting all of the invocables combined is to allocate the new delegate instance, this is exactly whatDelegate.Combine
performs. The inspection message contains "may" word becauseDelegate.Combine
do not allocates new instances if one of it's the arguments isnull
- in this case it is safe to just return another arguments instead (thx to immutability). So if yourevent
contains zero subscribers (null
is stored inAction<CharacterStateMachine>
hidden field) or you're somehow subscribing withnull
as aAction<CharacterStateMachine>
reference (this is safe in C# and will not trigger NRE) - there will be no actual allocation on both event subscription or unsubscription.I'll try to clarify HeapView's message in this case.
Thanks for the explanation!
Heap Allocations Viewer shows the following inspection:
The event
CharacterSetup
is declared as follows:public event Action<CharacterStateMachine> CharacterSetup;
The delegate
_onCharacterSetup
is declared as follows:private readonly Action<CharacterStateMachine> _onCharacterSetup;
I understand the inspection only says that it "may" allocate a new delegate instance, my question is: When would that happen? When and why an event handler would create a new instance for a delegate that is already allocated?
Asking here because I couldn't find any information on this specific subject.