[16] Дополнительную информацию по этой теме вы найдете в соответствующем разделе главы 8.

[17] Чтобы запретить появление окна сообщения, используйте P/Invoke для вызова функции Win32 SetErrorMode с передачей значения SEM NOGPFAULTERRORBOX.

[18] Это верно для случаев, когда поток не выходит за пределы одного класса AppDomain (подобно тому, как ASP.NET и управляемый SQL-сервер хранят сценарии процедур). Но для потоков, пересекающих границы домена приложений, может потребоваться завершение работы.

[19] Атрибут можно применить также к интерфейсу, конструктору, структуре, классу или сборке.

[20] Для автоматического тестирования можно использовать инструмент Рех, созданный группой Microsoft Research: http://research.microsoft.com/en-us/projects/pex/.

[21] KoiytaJIT-KOMinuMTop создает машинный код, модифицирующий ссылочное поле внутри объекта, туда входит вызов барьерного метода записи (write barrier method). Этот метод пр< >- веряет, принадлежит ли объект, поля которого изменяются, к поколению 1 или 2. В случае положительного результата код барьерного метода записи устанавливает бит во внутренней таблице (card table). Эта таблица содержит по одному биту для каждого 128-байтного диапазона данных в куче. В начале следующего цикла сборки мусора из таблицы определяется, поля каких объектов поколений 1 и 2 изменились с момента прошедшей сборки. Если какой-то из этих объектов ссылается на объект поколения 0, этот объект переживает уборку мусора. После завершения процедуры всем полям таблицы возвращаются нулевые значения. Наличие кода барьерного метода записи негативно сказывается на производительности при записи ссылочных полей у объекта (в отличие от локальных переменных или статических полей). Производительность падает еще больше, если объект принадлежит поколению 1 или 2.

[22] В будущем пороговый размер объекта, при котором он считается большим, может быть изменен. Не следует считать значение 85 000 константой.

[23] Возможно, в будущих версиях CLR для повышения производительности будут использоваться множественные потоки финализации.

[24] Это поведение можно переопределить вызовом конструктора StreamWriter, получающим логический параметр leaveOpen.

[25] В 64-разрядной версии Windows в действительности установлены два варианта файла MSCorEE.dll. Первый — это 32-разрядная версия х86, расположенная в папке C:\Windows\ SysWOW64, второй — 64-разрядная версия х64 или IA64 (в зависимости от архитектуры процессора), расположенная в папке C:\Windows\System32.

[26] Обратите внимание, что версии .NET Framework 3.0 и 3.5 поставляются с CLR 2.0. Я не указываю, в каких папках находятся версии .NET Framework 3.0 и 3.5, так как DLL-библиотека CLR загружается из папки v2.0.50727.

[27] Если бы среда CLR требовала закрытости всех полей (что рекомендуется для хорошей инкапсуляции), методы FieldGetter и FieldSetter не должны были бы существовать. В итоге к полям остался бы только непосредственный доступ из методов, что избавило бы нас от потерь производительности.

[28] Кстати, именно поэтому класс System. String является запечатанным. Если бы это было не так, вы могли бы определять собственные классы, производные от String, и добавлять к ним собственные поля. В результате среда CLR не смогла бы гарантировать неизменность строк.

[29] Конфигурацию класса AppDomainManager можно выполнить также при помощи переменных окружения и параметров реестра, но эти механизмы более громоздки и применять их имеет смысл разве что в некоторых тестовых сценариях.

[30] При любом блокировании вызываются методы BeginCriticalRegion и EndCriticalRegion класса Thread, показывающие момент входа в критическую область и выхода из нее. При необходимости вы тоже можете ими воспользоваться. Такая необходимость обычно возникает при взаимодействии с неуправляемым кодом.