Table of Contents

Struct ConditionSet

Namespace
MassiveDotNet.WebSocket.Events
Assembly
MassiveDotNet.WebSocket.dll

Up to eight condition codes held inline, spilling to the heap beyond that.

public readonly struct ConditionSet : IEquatable<ConditionSet>
Implements
Inherited Members

Remarks

An int[] would allocate on every event carrying conditions, which is most trades. Renting from ArrayPool is not available either: the array escapes to the caller with the event, so nothing could ever return it. Eight covers every condition set observed, and the field holds no reference in that case, so the common path allocates nothing.

A ninth code spills to a heap array rather than being dropped. Truncating would be silent data loss, which this SDK refuses everywhere else.

Equality is hand-written rather than left to the compiler-synthesized member-wise comparison a struct normally gets: the InlineArrayAttribute field makes the runtime's default ValueType.Equals/GetHashCode refuse to run at all (NotSupportedException), and StockTrade and StockQuote are record struct types (D4) whose own synthesized equality delegates straight to this type's. Without IEquatable<T> here, both events would inherit that failure.

Fields

InlineCapacity

How many codes fit before spilling to the heap.

public const int InlineCapacity = 8

Field Value

int

Properties

Count

How many codes this set holds.

public int Count { get; }

Property Value

int

this[int]

The code at index.

public int this[int index] { get; }

Parameters

index int

A zero-based index below Count.

Property Value

int

Methods

AsSpan()

The codes, as a span over inline or spilled storage.

public ReadOnlySpan<int> AsSpan()

Returns

ReadOnlySpan<int>

A span of exactly Count codes.

Remarks

The inline branch reads through AsRef<T>(scoped ref readonly T) over a readonly field, which is what makes this method possible on a readonly struct at all: an InlineArrayAttribute buffer normally cannot be indexed, let alone spanned, through a readonly binding, because the compiler cannot prove indexing does not mutate it. AsRef<T>(scoped ref readonly T) deliberately launders that ref-safety, which means the compiler can no longer catch a span that outlives the ConditionSet it was taken from.

The two branches do not fail the same way, and the difference matters more than it looks. Inline (Count at most InlineCapacity): the returned span points at bytes living inside this ConditionSet value itself. Once that exact value is copied over, reassigned, or falls out of scope, the span is left pointing at whatever now occupies that memory — it does not throw, it reads garbage. trade.Conditions.AsSpan().ToArray() is safe, because the copy happens before the value could go stale; holding the span itself across statements, such as ReadOnlySpan<int> s = trade.Conditions.AsSpan(); followed by later use, is not. Spilled (Count above InlineCapacity): the returned span is backed by the independently heap-allocated int[], which the ReadOnlySpan<T> itself keeps referenced — so, measured, it keeps reading correctly even after the source ConditionSet is cleared or discarded. This is the more dangerous case, not the safer one: it is an accident of how many codes a given message happened to carry, not a documented guarantee, so code that holds the span because "it worked when I tried it with nine conditions" breaks the moment a message arrives with three. Nothing at the call site distinguishes which branch a given ConditionSet took, so treat both the same way: a caller that needs the codes to outlive the ConditionSet they came from must call ToArray() on the returned span, or use this[int], rather than retain the span itself. This compiles clean either way, because the hazard is exactly the one this method exists to route around.

Equals(ConditionSet)

Whether this set holds the same codes, in the same order, as other.

public bool Equals(ConditionSet other)

Parameters

other ConditionSet

The set to compare against.

Returns

bool

true when both sets hold the same codes in the same order.

Equals(object?)

Whether obj is a ConditionSet equal to this one.

public override bool Equals(object? obj)

Parameters

obj object

The object to compare against.

Returns

bool

true when obj is an equal ConditionSet.

GetHashCode()

A hash code consistent with Equals(ConditionSet): equal sets hash equal.

public override int GetHashCode()

Returns

int

The hash code.

Operators

operator ==(ConditionSet, ConditionSet)

Whether left and right hold the same codes in the same order.

public static bool operator ==(ConditionSet left, ConditionSet right)

Parameters

left ConditionSet

The first set.

right ConditionSet

The second set.

Returns

bool

true when the two sets are equal.

operator !=(ConditionSet, ConditionSet)

Whether left and right differ.

public static bool operator !=(ConditionSet left, ConditionSet right)

Parameters

left ConditionSet

The first set.

right ConditionSet

The second set.

Returns

bool

true when the two sets are not equal.