Я думаю, что разработка API в значительной степени субъективна и / или должна сильно зависеть от «сценариев использования» API. С другой стороны, варианты использования вашего API полностью зависят от клиентского кода.
Сказав все это лично, я бы воспользовался перегрузкой метода и пошел бы к следующей структуре:
Метод со всеми параметрами:
void someFunction(int[] input1, int[] input2, int offset, int length, int[] output)
Это основная функция. Все остальные функции просто вызывают это с соответствующими параметрами.
int[] someFunction(int[] input1, int[] input2, int offset, int length)
Вызывает первую функцию, но выделяет и возвращает выходной массив от имени вызывающей стороны.
void someFunction(int[] input1, int[] input2, int[] output)
int[] someFunction(int[] input1, int[] input2)
Обратите внимание, что общая стратегия состоит в том, чтобы сократить список параметров, исключив «необязательные» параметры.
В целом, я стараюсь избегать изменения поведения метода в зависимости от того, является ли параметр (например, выходной массив) null
. Это может затруднить выявление тонких ошибок таким образом. Поэтому я предпочитаю два разных стиля вызова: один, в котором указывается (и требуется) выходной параметр, и другой, где метод возвращает свой вывод.