Я много читал о изменчивости структур в C#. Большинство слов говорят, что изменчивые структуры являются злыми. Я понимаю, почему. Но у меня есть случай, когда изменчивая структура кажется законной. Конечно, я сталкиваюсь с проблемами, которые распространяются вокруг структурной изменчивости.юридический (?) Изменяемый случай структуры в C#
Скажет, у меня есть, простая структура, как это, в приложении редактора ГИСА:
enum CoordinateSystem : byte { .... } // coordinate system types
struct Vertex
{
float m_x; // m_ is the original value of coordinate, it needs to be kept
float m_y;
float c_x; // c_ is a cache of the result of expensive coordinate transformation
float c_y;
CoordinateSystem cachedSystem; // the current coordinate system type in c_x and c_y
public float x { get {...} set {...}} // properties are for accessing values outside of struct
public float y { get {...} set {...}} // and transforming m_x,m_y into c_x,c_y if necessary
}
Свойство для доступа к координате снаружи. Из внешнего одноэлементного класса известно, какая структура системы необходима при доступе к свойствам x и y. Свойство get преобразует m_x и m_y по требованию, если необходимо, и помимо возвращаемого значения он сохраняет результат в c_x и c_y для дальнейшего доступа. Конечно, кеширование необходимо, потому что преобразование координат очень дорого. При кэшировании только первый доступ будет медленным, и все дальнейший доступ в одной и той же системе координат будет «немедленным».
Вершины живут в списке, поэтому в списке вершин длиной 10000 выделяется вершина [10000] в списке.
Очевидно, проблема заключается в том, что доступ к вершине из списка возвращает копию структуры, хранящейся в списке <>, поэтому кэширование после преобразования не влияет, поскольку оно сохраняет результат в короткоживущей копии , а не в списке <> сам.
Я не хочу менять Вершину в класс, потому что она будет выделять (в 64-битной версии) 10000 * 8 байтов в качестве ссылки в одном блоке и 10000 * 17 байт в блоке 10000, это примерно равно 1/3 памяти и 10000 раз количество выделенных блоков. (Я знаю, что это грубый расчет из-за выравнивания, ...) И это примерно один список вершин, у меня их десять тысяч, поэтому класс будет тратить много памяти.
Я бы хотел, чтобы преобразование было прозрачным для внешних аксессуаров, потому что Vertex - это основной тип приложения, на который ссылается много раз. Другая причина заключается в том, что только координаты вершин знают о координатных системах, все остальные части смотрят на Vertex.x и Vertex.y как «числа», не более того. Таким образом, свойства x и y должны выполнять преобразование.
Вопрос: какой правильный подход для решения этой проблемы?
(Пожалуйста, не закрывайте этот вопрос как на основе мнений. Это не один из этого. Я заинтересован в ответах, основанных на фактах, принимая во внимание цели применения.)
Не можете ли вы обновить список с измененной копией? –
Я думаю, что лучше отделить неизменяемые и изменяемые части, иметь отдельный тип для фактических значений и кешированных значений. Я не думаю, что 'CoordinateSystem' может отличаться для каждой вершины. поэтому лучше иметь кэшированные значения в другом списке, и когда когда-либо изменения 'CoordinateSystem' воссоздают список с новыми значениями. –
Такая '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' используется только при сохранении/экспонировании из массивов, которые в настоящее время являются единственной структурой коллекции, C# 7 'ref возвращает', вероятно, позволит подвергать большее количество индексов, таких как массив, но до тех пор ... Кроме того, для обратной совместимости они, вероятно, будут хранить« Список », как сейчас. –