С#:Преимущество явного указания «небезопасного» параметра/опции компилятора

StackOverflow https://stackoverflow.com/questions/607159

Вопрос

Я понимаю указатели и редкую необходимость их использования в коде C#.Мой вопрос:какова причина необходимости явно указывать «небезопасно» в блоке кода.Кроме того, почему необходимо изменить параметр компилятора, чтобы разрешить «небезопасный» код?

Нижняя граница: Что в CLR (или спецификациях языка) делает так, что мы не можем просто использовать указатели, когда захотим (так же, как C и C++), без необходимости вводить «unsafe» и изменять параметр компилятора?

В целях разъяснения:Я знаю, что такое «небезопасный» и «безопасный» код.Это просто вопрос, почему мы должны выполнять всю дополнительную работу (ладно, не НАСТОЛЬКО дополнительную) только для того, чтобы иметь возможность использовать эти функции.

Это было полезно?

Решение

Есть интервью с создателем C# Андерсом Хейлсбергом, которое затрагивает эту тему. здесь.По сути, именно то, что сказал @Marc Gravell:безопасность типов прежде всего, небезопасность при явном объявлении.

Итак, чтобы ответить на ваш вопрос:ничто в CLR не препятствует этому;это языковая идиома, позволяющая вам работать с типами в защитных перчатках.Если вы хотите снять перчатки, это ваш выбор, но вы должны сделать активный выбор и снять перчатки.

Редактировать:

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

Как упоминалось в интервью, на которое я дал ссылку, это было явное дизайнерское решение.C#, по сути, является развитием Java, а в Java вообще нет указателей.Но дизайнеры хотели разрешить указатели;однако, поскольку C# обычно привлекает разработчиков Java, они считали, что было бы лучше, если бы по умолчанию поведение должно быть похоже на Java, т.е.нет указателей, но при этом разрешено использование указателей путем явного объявления.

Таким образом, «дополнительная работа» предназначена для того, чтобы заставить вас подумать о том, что вы делаете, прежде чем делать это.Будучи явным, это заставляет вас, по крайней мере, учитывать:«Почему я это делаю?Я Действительно нужен указатель, когда ссылочного типа будет достаточно?»

Другие советы

Во многом речь идет о возможности проверки.Заявив unsafe, перчатки сняты — система больше не может гарантировать, что ваш код не выйдет из-под контроля.В большинстве случаев крайне желательно оставаться в безопасной зоне.

Это становится более заметным при частичном доверии (надстройки и т. д.), но по-прежнему полезно в обычном коде.

На самом деле CLR вообще не предъявляет никаких требований к переключателю или ключевому слову /unsafe.Фактически, C++/CLI (язык C++, работающий под управлением CLR) не имеет такого переключателя /unsafe, и указатели можно свободно использовать в CLR.

Таким образом, я бы перефразировал ваш вопрос как «Почему C# требует использования /небезопасности, прежде чем можно будет использовать указатели?» И ответ на этот вопрос, как указано в других ответах, приведенных здесь:чтобы помочь пользователю принять сознательное решение потерять возможность работать в CLR в режиме, отличном от полного доверия.C++ практически всегда требует полного доверия к CLR, а C# может всякий раз, когда вы вызываете код, требующий полного доверия, или всякий раз, когда вы используете указатели.

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

Подумайте об этом с противоположной точки зрения:поскольку он не помечен как небезопасный, вы можете сделать вывод, что большая часть кода по умолчанию «безопасна».Так что же значит быть «безопасным»?Для кода .Net это включает (но не ограничивается):

  • Сборщик мусора может работать как обычно.
  • Ссылки на конкретный тип воля ссылаются на объекты этого типа (или null).
  • Код гарантированно соответствует требованиям доверия/безопасности .Net.
  • Математически доказано, что код не касается напрямую памяти за пределами своего собственного домена приложения.Это может показаться тривиальным, но представьте, что у вас есть несколько доменов приложений в одном приложении.Программист может с уверенностью рассматривать их как логически отдельные.

Каждый раз, когда вы используете указатели, у вас есть шанс нарушить любую из этих гарантий.Поэтому пометка кода как небезопасного лишает эту защиту.

Короче говоря, .NET хочет, чтобы вы заявили о своих намерениях.

Конечно, компилятор может сделать вывод о необходимости использования флага «небезопасно».Но дизайнеры хотят, чтобы это было обдуманное решение.

На мой взгляд, это похоже на ряд синтаксических требований в C#:

  • без корпуса переключателя без перерыва
  • нет «разделов» уровня доступа (таких как маркер «public:» в C++)
  • нет полей класса с использованием «var»

Закономерность такова: не следует перемещать или менять одну вещь и непреднамеренно влиять на другую.В разумных пределах они хотят уберечь вас от «выстрела себе в ногу».

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

Чтобы сразу было видно, какой код не будет запускаться в веб-сервисах без повышенных разрешений и т. д.

Воспитание хороших привычек и безопасности.Всякий раз, когда вы используете небезопасный блок в сборке, из стека будет запрашиваться разрешение NativeCode.Конечно, это можно сделать неявно, но не можем ли мы просто полностью удалить ключевое слово Private?Я думаю, что было бы хорошо заставить разработчиков требовать наличие небезопасного кода, прежде чем они смогут его использовать.

Наиболее существенное различие между безопасным и небезопасным кодом заключается в том, что небезопасный код недоступен сборщику мусора .net.Автоматический сборщик мусора — это огромная часть языка .net, и когда вы выходите за его границы, вы меняете многое из того, что можно предположить о вашем коде.

Указатели, в частности, позволяют создавать объекты в куче без ссылок на GC.Это приводит к еще одной отличной причине, чтобы потребовать, чтобы код был помечен как «небезопасный». Это позволяет легко сузить, откуда исходит утечка памяти, когда вы понимаете, что у вас есть ее.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top