Поделиться через


Проектирование параметров

Замечание

Это содержимое перепечатывается разрешением Pearson Education, Inc. из руководства по проектированию платформы: соглашения, идиомы и шаблоны для повторно используемых библиотек .NET, 2-го выпуска. Этот выпуск был опубликован в 2008 году, и книга с тех пор была полностью пересмотрена в третьем выпуске. Некоторые сведения на этой странице могут быть устаревшими.

В этом разделе приведены общие рекомендации по проектированию параметров, включая разделы с рекомендациями по проверке аргументов. Кроме того, следует ссылаться на рекомендации, описанные в разделе "Параметры именования".

✔️ Используйте наименее производный тип параметра, предоставляющий функциональные возможности, необходимые элементу.

Например, предположим, что вы хотите разработать метод, перечисляющий коллекцию и печатающий каждый элемент в консоли. Такой метод должен принимать IEnumerable в качестве параметра, а не ArrayList или IList, например.

❌ НЕ используйте зарезервированные параметры.

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

❌ Не предоставляйте общедоступные методы, которые принимают указатели, массивы указателей или многомерные массивы в качестве параметров.

Указатели и многомерные массивы относительно трудно использовать должным образом. В почти всех случаях API-интерфейсы можно изменить, чтобы избежать использования этих типов в качестве параметров.

✔️ Размещайте все параметры out после параметров, передаваемых по значению, и ref параметров (за исключением массивов параметров), даже если это приводит к несоответствию порядка параметров между перегрузками (см. раздел Перегрузка элементов).

Параметры out можно рассматривать как дополнительные возвращаемые значения и группировать их вместе, что упрощает понимание сигнатуры метода.

✔️ При переопределении элементов или реализации элементов интерфейса следует выполнять согласованность в параметрах именования.

Это лучше объясняет взаимосвязь между методами.

Выбор между перечислением и логическими параметрами

✔️ Используйте перечисления, если элемент в противном случае имеет два или более логических параметров.

❌ НЕ используйте булевые значения, если вы не уверены, что в будущем не потребуется больше двух значений.

Перечисления дают вам возможность для будущего добавления значений, но следует учитывать все последствия добавления значений в перечисления, которые описаны в разделе "Проектирование перечислений".

✔️ Используйте булевые значения для параметров конструктора, которые являются по-настоящему двухсостоячными и просто используются для инициализации логических свойств.

Проверка аргументов

✔️ Проверьте аргументы, передаваемые общедоступным, защищенным или явно реализованным членам. Вызовите System.ArgumentException, или один из его подклассов, если проверка не пройдена.

Обратите внимание, что фактическая проверка не обязательно должна выполняться в общедоступном или защищенном элементе. Это может случиться на более низком уровне в некоторых частных или внутренних рутинах. Главной точкой является то, что вся область поверхности, которая предоставляется конечным пользователям, проверяет аргументы.

✔️ Выполните вызов, ArgumentNullException если передается пустой аргумент, и член не поддерживает аргументы NULL.

✔️ ПРОВЕРЯЙТЕ параметры перечисления.

Не предполагайте, что аргументы перечисления будут находиться в диапазоне, определенном перечислением. Среда 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});

Добавление ключевого слова params в C# к параметру массива превращает его в так называемый 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.

❌ Избегайте дорогостоящих проверок аргументов указателя.

✔️ Следуйте общим соглашениям, связанным с указателями, при проектировании элементов с указателями.

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

© Часть 2005, 2009 Корпорация Майкрософт. Все права защищены.

Перепечатан с разрешения Pearson Education, Inc. из Руководство по проектированию: Соглашения, идиомы и шаблоны для повторного использования библиотек .NET, 2-е издание Кшиштоф Чвалина и Брэд Абрамс, опубликованное 22 октября 2008 года Addison-Wesley Профессиональный в рамках серии разработки Microsoft Windows.

См. также