Разработка параметров

Примечание.

Это содержимое перепечатывается разрешением 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.

См. также