Структура - изменение значений максимально быстро - PullRequest
0 голосов
/ 21 февраля 2012

Представьте, что у меня есть структура Point с координатами X и Y. Теперь у меня есть конструктор: Point (int x, int y).

Вопрос: Должен ли я также добавить метод с именем Point.SetXY (int x, int y)?

пример:

// I have some point
point = new Point (5,5);

// and I wanna change some values
point = new Point (7,7);

// or maybe should I do like this?
point.SetXY (7,7); // is it faster?

Для классов я знаю, что это быстрее, потому что вам не нужно создавать новый экземпляр в куче и т. Д.

Но, может быть, для структур это не имеет значения?

Ответы [ 3 ]

4 голосов
/ 21 февраля 2012

Если нет очень веских причин для этого, я бы посоветовал сделать ваши структуры неизменяемыми - просто создайте новую структуру с новыми значениями X и Y, когда это необходимо.

Например, почему изменяемыйструктуры могут быть нелогичными (или зло (в зависимости от метрик, относящихся к лицензии на творчество)) Эрик Липперт имеет очень хороший пост в блоге на эту тему.

2 голосов
/ 21 февраля 2012

Я думаю, что вы можете достичь этого

point.X = 7;
point.Y = 7;

Это самый быстрый

1 голос
/ 22 февраля 2012

Структуры с открытыми полями не являются злом. В то время как некоторые действительно старые компиляторы будут принимать код вроде:

List<Point> myList;
myList[4].X = 5;

, который копировал бы myList [4] во временную структуру, изменял поле X этой временной структуры, а затем выбрасывал измененную структуру, а создание неизменяемых структур было способом, гарантирующим, что компилятор закричит на вышеуказанную конструкцию лучший способ гарантировать, что компилятор будет кричать при таком коде, - это изменить компилятор, чтобы запретить запись в поля временных структур. Учитывая, что такой код долгое время запрещался компиляторами, структуры с открытыми полями часто являются лучшим способом хранения вещей, которые имеют фиксированное количество независимых элементов данных (например, Point, Rectangle и т. Д.)

Проблемными являются структуры, в которых функции, отличные от конструкторов или установщиков свойств, модифицируют this. Хотя компиляторы распознают, что запись в someStructProperty.someField пытается изменить someStructProperty, и запретят это в тех случаях, когда такое изменение фактически не работает, к сожалению, у компилятора нет средств, чтобы узнать, что someStructProperty.MutatingFunction() попытается изменить временный экземпляр структуры. Таким образом, компилятор разрешит такой код, даже если он не сможет работать так, как задумано. Что бы я предложил в качестве средства исправления в случаях, когда функция должна изменять структуру «на месте», было бы определение статического метода, который принимает экземпляр структуры в качестве параметра ref. Например, SetPointXY(ref Point pt, int x, int y). Компилятор будет рассматривать передачу структуры как параметр ref как попытку изменить эту структуру и разрешит ее только в ситуациях, когда она действительно будет работать.

Обратите внимание, что с точки зрения производительности, единственный раз, когда написание структурных полей по отдельности не было бы самым быстрым способом обновления структуры, был бы, когда большая часть структуры соответствовала либо значению по умолчанию, либо некоторым другим существующим ранее структура. Могут быть такие случаи, когда было бы быстрее переписать структуру с уже существующим экземпляром, а затем записать поля, которые должны содержать что-то другое, но в целом я бы предложил использовать методы или функции для обновления структур только тогда, когда код, который делает это, будет более читабельным, чем код, который устанавливает поля индивидуально. Если AreaCode является открытым полем типа PhoneNumber, эффекты somePhoneNumber.AreaCode = "847"; гораздо более очевидны, чем эффекты somePhoneNumber = new PhoneNumber("847", somePhoneNumber.Exchange, somePhoneNumber.Number, somePhoneNumber.Extension);. Среди прочего, нужно было бы изучить всю структуру, чтобы узнать, изменит ли последняя какие-либо поля, кроме AreaCode. С другой стороны, если цель на самом деле состояла в том, чтобы иметь структуру, которая была бы пустой, за исключением некоторых совершенно новых данных, использование конструктора или метода фабрики могло бы помочь прояснить тот факт, что это делается; если просто переписать все поля структуры по отдельности, нужно будет изучить всю структуру, чтобы знать, что не было полей, которые можно было бы оставить без изменений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...