Обычно я выбираю между struct и классом не из-за проблем с памятью, а из-за семантики этого типа. Некоторые из моих типов значений имеют довольно большой объем памяти, иногда слишком большой, чтобы копировать эти данные все время. Поэтому мне интересно, стоит ли передавать неизменяемым значения объектов всегда по ссылке? Поскольку объекты неизменяемы, они не могут быть изменены с помощью методов, которые принимают их по ссылке. Существуют ли другие вопросы при передаче по ссылке?Передача неизменяемых типов значений по ссылке
ответ
Некоторые из моих типов значений имеют довольно большой след
памяти Это предполагает, что они не должны быть типы значений, с точки зрения реализации. Из «Руководства по проектированию для развивающихся библиотек классов», раздел "Choosing Between Classes And Structures":
Не определить структуру, если тип не имеет все следующие характеристики:
- Это логически представляет собой одно значение, подобно примитивным типы (целое, двойное и т. д.).
- У него размер экземпляра меньше 16 байт.
- Неизменяется.
- Его не нужно часто вставлять в коробки.
Похоже, вы должны создавать незыблемый ссылку типа вместо. Во многих отношениях они в конечном итоге «чувствуют», как объекты ценности (думаю, строки), но вам не нужно беспокоиться об эффективности их прохождения.
«Неизменность» для типов значений этого понятия немного жидкости - и это, конечно, не означает, что с помощью ref
безопасно:
// int is immutable, right?
int x = 5;
Foo(ref x);
Console.WriteLine(x); // Eek, prints 6...
...
void Foo(ref int y)
{
y = 6;
}
Мы не меняем одна части стоимости - мы заменяем все значение x
совершенно другим значением.
Неизменности несколько легче думать о том, когда речь идет о ссылочных типах - хотя и тогда вы можете иметь объект, который сам по себе не изменится, но может относиться к изменяемым объектам ...
«У него размер экземпляра меньше 16 байт». Вы действительно пишете 'class Vector3d', потому что он имеет 24 байта? – hansmaad
@ hansmaad Это просто руководство. Каждый случай не может быть охвачен им, но они должны учитывать вещи/правила при принятии решения. – vcsjones
@hansmaad: Если тип, вероятно, будет * передан значением * много, то * да *, вы должны. Если тип значения вряд ли передается по значению - если вы просто создаете его и используете его локально, не переходя по другому методу, - тогда идите вперед и сделайте его большим, если хотите. –
Так что, интересно, стоит ли передавать неизменяемые объекты значения всегда по ссылке? Поскольку объекты неизменяемы, они не могут быть изменены с помощью методов, которые принимают их по ссылке. Существуют ли другие вопросы при передаче по ссылке?
Непонятно, что вы имеете в виду. Предполагая, что вы имеете в виду передать его как параметр ref
или out
, тогда метод может просто назначить новый экземпляр хранилищу. Это изменит то, что видит вызывающий, поскольку место хранения в вызываемом абоненте является псевдонимом для места хранения, переданного вызывающим абонентом.
Если вы имеете дело с проблемами памяти из-за копирования экземпляров struct
, вам следует подумать о создании неизменяемого ссылочного типа, такого как string
.
I думаю, что на самом деле плохая идея заключается в том, чтобы использовать структуры, когда все, что вы делаете точки, чтобы использовать классы
Связанные ответ: https://stackoverflow.com/questions/2440029/is-it-a-bad-practice-to-pass-structs-by-reference
ответ Джона, конечно, правильный; Я бы добавил к этому: значения типов уже переданы по ссылке при вызове метода по типу значения. Например:
struct S
{
int x;
public S(int x) { this.x = x; }
public void M() { Console.WriteLine(this.x); }
}
Метод M() логически то же самое:
public static void M(ref S _this) { Console.WriteLine(_this.x); }
Всякий раз, когда вы вызываете метод экземпляра на структуры, мы передаем реф к переменной что был приемником вызова.
Так что, если приемник не является переменной? Затем значение копируется во временную переменную, которая используется в качестве приемника. И если ценность большая, это потенциально дорогостоящая копия!
Типы значений копируются по значению; поэтому они называются типами значений. Если вы не планируете быть крайне осторожным о том, чтобы найти все возможные дорогие копии и устранить их, я бы посоветовал совет по дизайну каркаса: сохраните структуры до 16 байт и передайте их по значению.
Я также хотел бы подчеркнуть, что Джон прав: передача структуры посредством ref означает передачу ссылки на переменную, а переменные могут изменять. Вот почему их называют «переменными». В C# нет «const ref», как есть на C++; даже если сам тип значения кажется «неизменным», что не означает, что переменная является неизменной. Вы можете увидеть яркий пример того, что в этой надуманной, но образовательный пример:
struct S
{
readonly int x;
public S(int x) { this.x = x; }
public void M(ref S s)
{
Console.WriteLine(this.x);
s = new S(this.x + 1);
Console.WriteLine(this.x);
}
}
Возможно ли M выписать две разные номера? Вы бы наивно считали, что структура неизменна, и поэтому x не может измениться. Но оба s и это являются переменные и переменные могут изменить:
S q = new S(1);
q.M(ref q);
Это печатает 1, 2, потому что this
и s
являются ссылки на q
, и ничто не мешает q
от изменения ; не только.
Вкратце: если бы у меня было много данных, которые я хотел пройти, и у вас есть сильные гарантии того, что он был неизменным, я бы использовал класс, а не структуру.Используйте только структуру в этом сценарии, если у вас есть продемонстрированная проблема производительности , которая фактически решена путем создания ее структуры, имея в виду, что большие структуры потенциально очень дороги для копирования.
Так называемые неизменяемые структуры могут быть изменены, даже если ничто внутри их кода не взаимодействует в такой мутации. Например, хотя местоположение хранилища «KeyValuePair
- 1. Передача значений по ссылке
- 2. Передача пользовательских типов срезов по ссылке
- 3. Сравнение неизменяемых типов данных
- 4. Передача значений по ссылке в многопоточном программировании
- 5. Id of неизменяемых типов
- 6. Унаследовано от неизменяемых типов?
- 7. Наследование из неизменяемых типов
- 8. Передача переменной по ссылке
- 9. Передача указателя по ссылке?
- 10. Передача вектора по ссылке
- 11. Передача объекта по ссылке
- 12. Передача shared_ptr по ссылке
- 13. Передача UIButton по ссылке
- 14. Передача справки по ссылке
- 15. Java передача по ссылке
- 16. Передача LPCWSTR по ссылке
- 17. Передача аргументов по ссылке
- 18. Передача данных по ссылке
- 19. Функция. Передача по ссылке
- 20. PHP Передача по ссылке
- 21. Передача справки по ссылке?
- 22. Передача анонимную переменную по ссылке
- 23. Передача примитивных типов данных по ссылке в Objective C
- 24. Передача примитивных типов данных по ссылке в JNI
- 25. Передача скалярных типов по значению или ссылке: это имеет значение?
- 26. Настройка неизменяемых типов в Python
- 27. C# - Хороший и гибкий способ передачи типов значений по ссылке?
- 28. Сериализация неизменяемых типов значений с помощью драйвера Mongo C#
- 29. Программирование C++ Data Structures: передача значений по ссылке?
- 30. Рекурсия и передача по ссылке
Возможно, вам нужно переосмыслить свое обоснование для решения между структурами и классами. –