Перегрузки, которые принимают SafeFileHandle
, существуют по той же причине, что и устаревшие сейчас перегрузки, которые приняли IntPtr
: так что вы можете создать новый экземпляр FileStream
из дескриптора файла, который вы получили через p /вызвать взаимодействие, т. е. из неуправляемого кода.
Тип SafeHandle
и идиома его использования не существовали в ранних версиях .NET. Необработанные значения IntPtr
использовались в любое время, когда управлял кодом, необходимым для работы с собственными дескрипторами. Когда был представлен гораздо лучший тип SafeHandle
, просто имело смысл предоставить конкретные подклассы для обычно используемых типов собственных дескрипторов, таких как файловые дескрипторы, а затем поддерживать эти конкретные подклассы в любом управляемом API, включая конструкторы, подобные тем, которые используются для * 1009. *, где ранее использовался собственный тип дескриптора.
Приведенный вами пример никогда не будет (или, по крайней мере, никогда) не появится в реальном коде. Если вы открываете файл из управляемого кода и используете его только в управляемом коде, то вы просто делаете это. У вас никогда нет причин возиться с нативным дескриптором файла. Вы бы использовали свойство SafeFileHandle
объекта FileStream
только в том случае, если вам нужно было передать собственный дескриптор файла неуправляемому коду, и вы бы передали значение SafeFileHandle
конструктору FileStream
, только если у вас не было возможностиполучить этот конкретный дескриптор файла, кроме как из неуправляемого кода.
Честно говоря, я не совсем понимаю вашу аналогию с веревкой и детьми. Это не кажется правильным или полезным для меня, хотя. Вы уже получили ответ на свой предыдущий, очень широкий вопрос Что такое SafeFileHandle в c # и когда мне следует его использовать? , поэтому вы уже должны знать, почему существует SafeFileHandle
, но подведем итог:
SafeHandle
и его подклассы - гораздо лучшая альтернатива заключению классовой сделки с финализаторами. Класс SafeHandle
сам реализует логику финализации, поэтому вашему классу это не нужно. По крайней мере, до тех пор, пока единственные неуправляемые объекты, с которыми обычно работает ваш класс, могут быть заключены в подкласс SafeHandle
- и, поскольку вы можете реализовать свои собственные оболочки, для тех объектов, у которых еще нет оболочки, предоставляемой .NETэто должно быть всех ваших неуправляемых объектов - тогда вам не нужен финализатор. (Вам все еще нужно реализовать IDisposable
, чтобы ваши неуправляемые объекты могли быть детерминированно очищены ... финализатор находится там исключительно как резервная копия).
Я надеюсь, что вышеприведенного достаточно, чтобы объяснить всеэто. Переполнение стека не совсем подходящее место для подробных объяснений концепций на уровне учебного пособия. Но, если предположить, что вышеупомянутое краткое обсуждение обеспечивает уровень детализации, который вам необходим, чтобы понять, почему существуют эти конструкторы, мне это кажется правильным.