Разработка параметров
Примечание.
Это содержимое перепечатывается разрешением Pearson Education, Inc. из руководства по проектированию платформы: соглашения, идиомы и шаблоны для повторно используемых библиотек .NET, 2-го выпуска. Этот выпуск был опубликован в 2008 году, и книга с тех пор была полностью пересмотрена в третьем выпуске. Некоторые сведения на этой странице могут быть устаревшими.
В этом разделе приведены общие рекомендации по проектированию параметров, а также сведения о проверке аргументов. Кроме того, ознакомьтесь с рекомендациями, описанными в статье Именования параметров.
✔️ ИСПОЛЬЗУЙТЕ наименее производный тип параметра, который предоставляет функции, необходимые для элемента.
Например, предположим, что требуется разработать метод, который перечисляет коллекцию и выводит каждый элемент на консоль. Например, такой метод должен принимать IEnumerable в качестве параметра, а не ArrayList или IList.
❌ НЕ используйте зарезервированные параметры.
Если в какой-либо будущей версии для элемента требуется больше входных данных, можно добавить новую перегрузку.
❌ НЕ используйте общедоступные методы, которые принимают указатели, массивы указателей или многомерные массивы в качестве параметров.
Указатели и многомерные массивы достаточно сложно правильно использовать. В большинстве случаев можно переработать интерфейс API, чтобы не использовать эти типы в качестве параметров.
✔️ РАЗМЕЩАЙТЕ все параметры out
после всех параметров по значению и ref
(исключая массивы параметров), даже если это приведет к несогласованности упорядочения параметров между перегрузками (см. статью Перегрузка элементов).
Параметры out
могут рассматриваться как дополнительные возвращаемые значения. Объедините их вместе, чтобы лучше понять сигнатуру метода.
✔️ БУДЬТЕ последовательны в именовании параметров при переопределении элементов или реализации элементов интерфейса.
Это улучшает связь между методами.
Выбор между параметрами перечисления и логическими параметрами
✔ ИСПОЛЬЗУЙТЕ перечисления, чтобы не использовать в элементе два или более логических параметра.
❌ НЕ используйте логические параметры, если вы абсолютно не уверены, что вам никогда не понадобится больше двух значений.
Перечисления предоставляют возможность добавить значения в будущем. Но следует помнить о всех последствиях добавления значений к перечислениям, которые описаны в разделе Разработка перечислений.
✔️ Рассмотрите возможность использования логических значений для параметров конструктора, которые действительно являются значениями с двумя состояниями и просто используются для инициализации логических свойств.
Проверка аргументов
✔️ ПРОВЕРЯЙТЕ аргументы, переданные общедоступным, защищенным или явно реализованным элементам. Вызовите исключение System.ArgumentException или один из его подклассов, если проверка завершается неудачно.
Обратите внимание, что фактическая проверка не обязательно должна выполняться в самом общедоступном или защищенном элементе. Это может произойти на более низком уровне, например в частных или внутренних подпрограммах. Главным моментом является то, что вся контактная зона, предоставляемая конечным пользователям, проверяет аргументы.
✔️ ВЫЗОВИТЕ ArgumentNullException, если передается нулевой аргумент, а элемент его не поддерживает.
✔️ ПРОВЕРЯЙТЕ параметры перечисления.
Не рассчитывайте на то, что аргументы перечисления будут находиться в диапазоне, определенном перечислением. Среда CLR позволяет привести любое целочисленное значение в значение перечисления, даже если это значение не определено в перечислении.
❌ НЕ используйте Enum.IsDefined для проверки диапазона перечислений.
✔️ ИМЕЙТЕ В ВИДУ, что изменяемые аргументы могли измениться после проверки.
Если элемент, требует особых мер безопасности, рекомендуется создать копию, а затем проверить и обработать аргумент.
Передача параметров
С точки зрения конструктора инфраструктуры существуют три основные группы параметров: параметры по значению, параметры ref
и параметры out
.
Когда аргумент передается через параметр по значению, элемент получает копию фактического переданного аргумента. Если аргумент является типом значения, в стек помещается копия аргумента. Если аргумент является ссылочным типом, в стек помещается копия ссылки. Наиболее популярные языки среды CLR, такие как C#, VB.NET и C++, по умолчанию передают параметры по значению.
Когда аргумент передается через параметр ref
, элемент получает ссылку на фактически переданный аргумент. Если аргумент является типом значения, в стек помещается ссылка на аргумент. Если аргумент является ссылочным типом, в стек помещается ссылка на ссылку. Параметры Ref
можно использовать, чтобы разрешить элементу изменять аргументы, передаваемые вызывающим объектом.
Параметры Out
аналогичны параметрам ref
, с некоторыми небольшими отличиями. Изначально считается, что параметр не назначен и не может быть прочитан в теле элемента до того, как ему будет присвоено какое-либо значение. Кроме того, параметру необходимо назначить значение перед возвратом элемента.
❌ НЕ используйте параметры out
и ref
.
Чтобы использовать параметры out
и ref
, требуется опыт работы с указателями, понимание отличия между типами значения и ссылочными типами и умение работать с методами с несколькими возвращаемыми значениями. Кроме того, далеко не все понимают разницу между параметрами out
и ref
. Архитекторы платформы, разрабатывающие общую аудиторию, не должны ожидать, что пользователи становятся опытными в работе с out
или ref
параметрами.
❌ НЕ передавайте ссылочные типы по ссылке.
Есть некоторые исключения из этого правила. К ним относится метод, который можно использовать для обмена ссылками.
Элементы с переменным числом параметров
Элементы, которые могут принимать переменное число аргументов, выражаются путем предоставления параметра массива. Например, String предоставляет следующий метод:
public class String {
public static string Format(string format, object[] parameters);
}
Затем пользователь может вызвать метод String.Format следующим образом:
String.Format("File {0} not found in {1}",new object[]{filename,directory});
Если добавить ключевое слово C# params в параметр массива, параметр будет изменен на так называемый параметр массива params. Будет предоставлен быстрый способ создания временного массива.
public class String {
public static string Format(string format, params object[] parameters);
}
Это позволяет пользователю вызывать метод, передавая элементы массива непосредственно в список аргументов.
String.Format("File {0} not found in {1}",filename,directory);
Обратите внимание, что ключевое слово params можно добавить только к последнему параметру в списке.
✔️ РЕКОМЕНДУЕТСЯ добавить ключевое слово params к параметрам массива, если предполагается, что пользователи будут передавать массивы с небольшим числом элементов. Если предполагается, что множество элементов будут передаваться с помощью стандартного сценария, пользователи, вероятно, не будут передавать эти элементы в любом случае, поэтому ключевое слово params не требуется.
❌ НЕ используйте массивы params, если у вызывающего объекта почти всегда есть входные данные, которые уже находятся в массиве.
Например, элементы с параметрами массива байтов почти никогда не вызываются путем передачи отдельных байтов. По этой причине для параметров массива байтов на платформе .NET Framework не используется ключевое слово params.
❌ НЕ используйте массивы params, если элемент, принимающий параметр массива params, изменяет массив.
Из-за того что многие компиляторы превращают аргументы элемента во временный массив в месте вызова, массив может быть временным объектом и поэтому любые внесенные в него изменения будут потеряны.
✔️ РАССМОТРИТЕ возможность использования ключевого слова params в простой перегрузке, даже если более сложная перегрузка не может его использовать.
Решите, оценят ли пользователи наличие массива params в одной перегрузке, даже если он будет не во всех перегрузках.
✔️ ПОПЫТАЙТЕСЬ упорядочить параметры, чтобы можно было использовать ключевое слово params.
✔️ Рассмотрите возможность предоставления специальных перегрузок и путей кода для вызовов с небольшим количеством аргументов в чрезвычайно чувствительных к производительности API-интерфейсах.
Это позволяет избежать создания объектов массива, когда API вызывается с небольшим количеством аргументов. Сформируйте имена параметров, взяв единственную форму параметра массива и добавив числовой суффикс.
Это следует делать только в том случае, если вы собираетесь использовать весь путь к коду, а не просто создаете массив и вызываете более общий метод.
✔️ ПОМНИТЕ, что значение NULL можно передать как аргумент массива params.
Перед обработкой необходимо убедиться, что массив не равен NULL.
❌ НЕ используйте методы varargs
также известные как многоточия.
Некоторые языки среды CLR, такие как C++, поддерживают альтернативное соглашение для передачи списков параметров переменных, именуемых методами varargs
. Это соглашение не должно использоваться на платформах, так как оно несовместимо с CLS.
Параметры указателя
Как правило, указатели не должны отображаться в общедоступной области хорошо спроектированной инфраструктуры управляемого кода. В большинстве случаев указатели следует инкапсулировать. Однако в некоторых случаях указатели необходимы по причинам совместимости, и их использование в таких случаях целесообразно.
✔️ ПРЕДОСТАВЬТЕ альтернативу для любого элемента, который принимает аргумент указателя, потому что указатели не соответствуют CLS.
❌ ИЗБЕГАЙТЕ использования дорогостоящей проверки аргументов указателей.
✔️ СЛЕДУЙТЕ общепринятым соглашениям по указателям при разработке элементов с указателями.
Например, нет необходимости передавать начальный индекс, так как для достижения того же результата можно использовать простые арифметические операции с указателями.
Фрагменты: © Корпорация Майкрософт (Microsoft Corporation), 2005, 2009. Все права защищены.
Перепечатано с разрешения Pearson Education, Inc. из книги Инфраструктура программных проектов. Соглашения, идиомы и шаблоны для многократно используемых библиотек .NET (2-е издание), авторы: Кржиштоф Цвалина (Krzysztof Cwalina) и Брэд Абрамс (Brad Abrams). Книга опубликована 22 октября 2008 г. издательством Addison-Wesley Professional в рамках серии, посвященной разработке для Microsoft Windows.