Так что здесь на самом деле две проблемы.Есть вопрос, который вы на самом деле задали: какие методы должны учитывать тот факт, что структуры должны быть неизменными, потому что они копируются по значению, но вы хотите изменить его.И затем возникает вопрос, который мотивирует этот вопрос: «Как я могу сделать производительность моей программы приемлемой?»
Мой другой ответ касается первого вопроса, но также интересен и второй вопрос.
Во-первых, если профилировщик действительно определил, что проблема производительности связана с сборкой мусора из ячеек,тогда возможно , что поможет преобразование ячейки в структуру.Также возможно, что это не поможет вообще, и возможно, что это ухудшит ситуацию.
Ваши ячейки не содержат никаких ссылочных типов;мы знаем это, потому что вы сказали, что они только три байта.Если кто-то еще читает это, думает, что он может сделать оптимизацию производительности, превратив класс в структуру, тогда это может вообще не помочь, потому что класс может содержать поле ссылочного типа , в этом случае мусорколлектор все еще должен собирать каждый экземпляр, даже если он превращен в тип значения.Типы ссылок в нем тоже нужно собирать!Я бы рекомендовал делать это только из соображений производительности, если Cell содержит только типы значений, что, по-видимому, и делает.
Это может ухудшить ситуацию, поскольку типы значений не являются панацеей;у них тоже есть расходы.Типы значений часто более дороги для копирования, чем ссылочные типы (которые почти всегда имеют размер регистра, почти всегда выровнены по соответствующей границе памяти, и поэтому микросхема высоко оптимизирована для их копирования).И типы значений копируются постоянно.
Теперь, в вашем случае, у вас есть структура, которая на меньше , чем ссылка;ссылки обычно составляют четыре или восемь байтов.И вы помещаете их в массив, что означает, что вы упаковываете массив;если у вас их будет тысяча, потребуется три тысячи байт.Это означает, что три из каждых четырех структур имеют неправильно выровненный , что означает больше времени (на многих архитектурах чипов) для извлечения значения из массива.Возможно, вы захотите измерить влияние padding вашей структуры на четыре байта, чтобы увидеть, будет ли это иметь значение, при условии, что вы все еще будете хранить их в массиве, что подводит меня к следующему пункту..
Абстракция ячеек может быть просто плохой абстракцией с целью хранения данных о множестве ячеек .Если проблема в том, что ячейки являются классами, вы храните массив из тысяч ячеек, и собирать их стоит дорого, тогда существуют другие решения, кроме превращения ячейки в структуру.Предположим, например, что ячейка содержит два байта заполнителя и один байт цвета.Это механизм Cell, но, конечно, это не тот интерфейс , который вы хотите предоставить пользователям. Нет причин, по которым ваш механизм должен использовать тот же тип, что и интерфейс .И поэтому вы можете создавать экземпляры класса Cell по запросу :
interface ICell
{
public int Population { get; set; }
public Color Color { get; set; }
}
private class CellMap
{
private ushort[,] populationData; // Profile the memory burden vs speed cost of ushort vs int
private byte[,] colorData; // Same here.
public ICell this[int x, int y]
{
get { return new Cell(this, x, y); }
}
private sealed class Cell : ICell
{
private CellMap map;
private int x;
private int y;
public Cell(CellMap map, int x, int y)
{
this.map = map; // etc
}
public int Population
{
get { return this.map.populationData[this.x, this.y]; }
set { this.map.populationData[this.x, this.y] = (ushort) value; }
}
и так далее. Изготовление ячеек по требованию .Они будут почти сразу же собраны, если они недолговечны. CellMap - это абстракция , поэтому используют абстракцию, чтобы скрыть грязные детали реализации.
С этой архитектурой у вас нет проблем со сборкой мусора, потому что вы почтинет живых экземпляров Cell, но вы все равно можете сказать
map[x,y].Population++;
Нет проблем, потому что первый индексатор создает неизменный объект, который знает, как обновить состояние карты . Cell не должен быть изменяемым; Обратите внимание, что класс Cell полностью неизменен. (Черт, Ячейка могла бы быть здесь структурой, хотя, конечно, приведение ее к ICell в любом случае просто поместило бы ее в коробку.) Это карта , которая является изменяемой, и ячейка изменяет карту для пользователь.