C#: коллекции, ссылки и копии
Где использовать .NET, что разделяет типизированная обёртка и что копирует Duplicate.
Выбрать контейнер
| Задача | Тип |
|---|---|
| Внутренний расчёт на C#, произвольные C#-объекты | List<T>, Dictionary<TKey,TValue> из System.Collections.Generic |
| Export, Variant и API с движковым массивом/словарём | Reckfell.Collections.Array<T> / Dictionary<TKey,TValue> |
| Плотный массив чисел/байтов на границе API | Тип из сигнатуры, например int[] или byte[] |
У массивов .NET размер — Length, у движковых коллекций — Count. Индексы идут от 0 до размера − 1. Типизированный движковый контейнер ограничивает T совместимыми с Variant значениями; Array<DateTime> даёт RF0301. Используйте полное имя или alias, если Array/Dictionary неоднозначны из-за using.
Отделить расчёт от обмена
InventoryLedger — обычный C#-класс: прикреплять его к Entity не нужно. TryAdd проверяет имя, знак количества и переполнение до изменения данных. Snapshot создаёт движковый словарь для передачи через API. Изменение количества в снимке не меняет исходный учёт: здесь ключи и значения — строки и числа.
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);
}Какая операция создаёт копию
| Операция | Результат |
|---|---|
| b = a для коллекции-класса | Общая ссылка |
| new Array<int>(untypedArray) | Обёртка над тем же движковым массивом |
| new Dictionary<string,int>(untypedDictionary) | Обёртка над тем же движковым словарём |
| Duplicate(false) | Новый контейнер; вложенные контейнеры и Resource общие |
| Duplicate(true) | Копируются вложенные массивы/словари; Resource-элементы остаются общими |
Типизированная обёртка над нетипизированным контейнером не является способом получить независимую копию. Проверяйте входные типы. Глубокая копия контейнера также не создаёт личный ShotSettings для каждого оружия; отдельную политику копирования ресурсов выбирайте явно.
Не меняйте состав коллекции во время foreach: соберите изменения отдельно либо выберите подходящий обход. Не превращайте каждый шаг расчёта в конвертацию туда и обратно: снимок создавайте на границе обмена. Универсальное преимущество по скорости этим примером не измерялось. Array<T> и Dictionary<TKey,TValue> этого SDK не реализуют IDisposable; не помещайте их в using как нетипизированные обёртки.