Структура C# с объектом как элемент данных

Как мы знаем, в структурах C# передаются значением, не ссылкой. Таким образом, если у меня есть структура со следующими элементами данных:

private struct MessageBox
{
    // data members
    private DateTime dm_DateTimeStamp; // a struct type
    private TimeSpan dm_TimeSpanInterval; // also a struct
    private ulong dm_MessageID; // System.Int64 type, struct
    private String dm_strMessage; // an object (hence a reference is stored here)
    // more methods, properties, etc ...
}

Таким образом, когда MessageBox передается в качестве параметра, КОПИЯ сделана на стеке, правильно? Что это означает с точки зрения того, как элементы данных копируются? Первые два являются типами структуры, таким образом, копии должны быть сделаны из DateTime и TimeSpan. Третий тип является примитивом, таким образом, он также копируется. Но что относительно dm_strMessage, который является ссылкой на объект? Когда это копируется, другая ссылка на ту же Строку создается, правильно? Сам объект находится в "куче" и НЕ копируется (существует только один экземпляр его на "куче".) Поэтому теперь мы имеем к ссылкам на тот же объект Строки типа. Если к этим двум ссылкам получают доступ от различных потоков, возможно, что Строковый объект мог быть поврежден, будучи измененным от двух различных направлений одновременно. В документации MSDN говорится та Система. Строка ориентирована на многопотоковое исполнение. Это означает, что Строковый класс имеет встроенный механизм для предотвращения объекта, повреждаемого в точно типе ситуации, описанной здесь? Я пытаюсь выяснить, имеет ли моя структура MessageBox какие-либо потенциальные дефекты / ловушки, являющиеся структурой по сравнению с классом. Спасибо за любой вход.

Источник. Энергия.

5
задан Richard Everett 2 May 2010 в 06:50
поделиться

3 ответа

Во-первых, ваше первое предложение подразумевает, что вы думаете, что классы передаются по ссылке. Это не так - ссылка передается по значению (по умолчанию). См. мою статью о передаче параметров для получения более подробной информации. Когда вы это поймете, это может прояснить другие аспекты.

На самом деле ваш вопрос касается двух разных вещей:

  • Как копируются значения структуры
  • Насколько безопасно разделять строки между потоками

Я думаю, вам поможет, если вы разделите их.

При копировании значения структуры члены обрабатываются одинаково, независимо от того, являются ли они типами значений или ссылочными типами. Значение просто копируется, бит за битом. Важно понимать, что значение dm_strMessage является ссылкой, а не строковым объектом. Эта ссылка скопирована.

Это не более опасно, чем этот код:

string message = GetMessageFromSomewhere();
string otherMessage = message;

Происходит то же самое: значение message копируется в otherMessage : две переменные имеют одинаковое значение, который является ссылкой на один строковый объект.

Пока это не имеет ничего общего с потоками. Теперь, если вы разделяете ссылку на строку между несколькими потоками, это безопасно, потому что строки неизменяемы . Вы не можете изменить содержимое строкового объекта, поэтому две строки могут без проблем читать данные из одного и того же объекта без риска повреждения. То же самое не верно для многих других типов в .NET. Например, небезопасно совместно использовать List между несколькими потоками, которые потенциально могут изменить список.

3
ответ дан 14 December 2019 в 08:45
поделиться

Строки не могут быть "испорчены" многопоточным доступом, поскольку они неизменяемы.

Тем не менее, вы должны избегать делать ваши структуры изменяемыми. Прочитайте этот вопрос и ответы для получения дополнительной информации.

Я пытаюсь понять, есть ли у моей структуры MessageBox какие-либо потенциальные недостатки / подводные камни, будучи структурой по сравнению с классом.

Вероятно, он не должен быть структурой. См. рекомендации на MSDN по выбору между классом и структурой.

Не определяйте структуру, если тип не обладает всеми следующими характеристиками:

  • Он логически представляет одно значение, подобно примитивным типам (integer, double и так далее).
  • Размер экземпляра меньше 16 байт.
  • Он неизменяем.
  • Его не придется часто упаковывать в коробки.

Я думаю, что ваш MessageBox определенно нарушает первое и второе руководство, и, возможно, также третье, в зависимости от того, какие методы доступны.

4
ответ дан 14 December 2019 в 08:45
поделиться

С точки зрения GC, передача одной структуры мало чем отличается от передачи полей в качестве отдельных параметров. Конечно, нет ничего страшного в передаче строки в структуре по сравнению с передачей строки как простого параметра.

Строки неизменяемы, поэтому их невозможно испортить, независимо от того, сколько потоков их разделяет.

0
ответ дан 14 December 2019 в 08:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: