Идентификация функции с возвращаемым типом void во время выполнения

#dart

Вопрос:

У меня есть функция, которая принимает другую функцию и ее аргументы в качестве аргументов. Тип возвращаемой функции и типы ее параметров неизвестны. Мне нужно знать во время выполнения, возвращает ли функция аргумента значение или это функция void.

 functionHandler(Function fn, List<dynamic> args) {
  var result = fn(args[0], args[1]);
  if ( -- fn returns a value --)
    doSomething();
  else if ( -- fn is a void function --)
    doSomethingElse();
}
 

Я не могу использовать fn.RuntimeType, потому что типы параметров неизвестны.

Функция void вернет значение null, но тогда я не смогу отличить функцию void от функции, которая просто вернула значение null.

Есть ли способ проверить во время выполнения, является ли fn функцией с типом возврата void?

Комментарии:

1. Действительно ли вам нужно различать void функции и не void функции? Если вы намерены вернуться result , вы можете сделать это независимо от типа возврата.

2. Кроме того, void функции также могут (к сожалению) возвращать не — null значения. Как правило, они не должны , но если вы пишете void foo() => something(); как сокращение void foo() { something(); } , вы фактически возвращаете результат something(); .

Ответ №1:

Хакерским способом было бы использовать fn.runtimeType.toString().endsWith('=> void') .

Поскольку вы, похоже, знаете, что для этого fn требуется ровно два позиционных аргумента, лучшим способом было бы создать functionHandler универсальную функцию, полностью квалифицировать свой Function тип с помощью параметризованных типов, а затем проверить параметр типа для возвращаемого типа:

 dynamic functionHandler<ReturnType, ArgumentType1, ArgumentType2>(
  ReturnType Function(ArgumentType1, ArgumentType2) fn,
  List<dynamic> args,
) {
  // `ReturnType == void` is a syntax error, so we must do a little
  // dance to get its corresponding `Type` object.
  Type getType<T>() => T;

  if (ReturnType == getType<void>()) {
    print('void');
  } else {
    print('non-void');
  }
}

void main() {
  // Test a `void` function.
  void voidFunction(Object arg1, dynamic arg2) {}
  functionHandler(voidFunction, []); // Prints: void

  // Test a function that returns `null`.
  Null nullFunction(int arg1, String? arg2) => null;
  functionHandler(nullFunction, []); // Prints: non-void

  // Test a function with optional arguments.
  int intFunction(int arg1, [int? arg2, int? arg3]) => 0;
  functionHandler(intFunction, []); // Prints: non-void
}
 

Комментарии:

1. Использование Type.toString предполагает синтаксис, используемый для toString Type объектов типов функций, который не указан и исторически не был согласован между платформами. Это также дает ложный положительный результат для void Function() Function(int, int) . В зависимости от параметра типа работает только в том случае, если выводятся аргументы типа. Если вы явно вызовете functionHandler<Object?, Never, Never>(anyFunction); , вы не увидите возвращаемый тип anyFunction . Тем не менее, у меня нет строго лучшего подхода 🙂