C#: collections, references and copies
When to use .NET, what typed wrappers share and what Duplicate actually copies.
Choose a container
| Task | Type |
|---|---|
| Internal C# calculation, arbitrary C# objects | System.Collections.Generic.List<T> / Dictionary<TKey,TValue> |
| Export, Variant and APIs requiring engine arrays/dictionaries | Reckfell.Collections.Array<T> / Dictionary<TKey,TValue> |
| Dense numeric/byte data at an API boundary | Follow the declaration, for example int[] or byte[] |
.NET arrays use Length; engine collections use Count. Indices run from 0 to size − 1. Typed engine containers require Variant-compatible T; Array<DateTime> produces RF0301. Use a full name or alias when using directives make Array/Dictionary ambiguous.
Separate calculation from exchange
InventoryLedger is an ordinary C# class, not an Entity script. TryAdd checks the name, quantity sign and overflow before mutation. Snapshot creates an engine dictionary for API exchange. Changing a snapshot count leaves the original ledger unchanged: its keys and values are strings and numbers.
InventoryLedger.cs
using System;
using System.Collections.Generic;
public sealed class InventoryLedger
{
private readonly Dictionary<string, int> _counts = new(StringComparer.Ordinal);
public int CountOf(string item) => _counts.TryGetValue(item, out int count) ? count : 0;
public bool TryAdd(string item, int amount)
{
if (string.IsNullOrWhiteSpace(item) || amount <= 0) return false;
int current = CountOf(item);
if (current > int.MaxValue - amount) return false;
_counts[item] = current + amount;
return true;
}
public Reckfell.Collections.Dictionary<string, int> Snapshot() => new(_counts);
}Which operation copies data
| Operation | Result |
|---|---|
| b = a for a collection class | Shared reference |
| new Array<int>(untypedArray) | Wrapper over the same engine array |
| new Dictionary<string,int>(untypedDictionary) | Wrapper over the same engine dictionary |
| Duplicate(false) | New container; nested containers and Resources remain shared |
| Duplicate(true) | Nested arrays/dictionaries are copied; Resource elements remain shared |
A typed wrapper over an untyped container does not create an independent copy. Validate incoming types. Deep container copying also does not create private ShotSettings for every weapon; choose resource-copy policy explicitly.
Do not change collection membership during foreach: collect changes separately or choose a suitable traversal. Avoid converting back and forth on every calculation step; create snapshots at exchange boundaries. This example establishes no universal performance advantage. This SDK's Array<T> and Dictionary<TKey,TValue> do not implement IDisposable; do not put them in using like untyped wrappers.