dart 当使用num.parse解析时,如何将int转换为double,反之亦然?

w6lpcovy  于 2023-01-22  发布在  其他
关注(0)|答案(1)|浏览(180)

最小可复制代码:

void main() {
  print(foo<int>('1'));
  print(foo<double>('1.0'));
  print(foo<double>('1'));
  print(foo<int>('1.0'));
}

T foo<T extends num>(String s) {
  final res = num.parse(s);
  return (T == double ? res.toDouble() : res.toInt()) as T;
}

正如你所看到的,我正在手动处理类型。有没有更好的方法来做这件事?

zzlelutf

zzlelutf1#

我看不出有什么更好的解决方案。你有一个完全基于类型参数来改变行为的函数。因为你对类型参数所能做的就是子类型检查,或者把它与常量类型文本进行比较,所以你需要做类似的事情。
我更喜欢子类型检查,因为它也允许升级,但是对于像T只有四种可能类型的情况,检查Type对象是否相等也可以工作,在返回之前至少需要有一个as T
这两种方法都 * 仅 * 适用于有限的类型层次结构,并且您考虑了所有可能的类型。即使在这里,当前代码也没有覆盖<num><Never>,这两个参数对于绑定的num也是有效的类型参数。因此,请保持警惕。
也许,使用子类型检查升级:

T parse<T extends num>(String source) {
  var value = num.parse(source);
  if (value is T) return value;
  // T is not `num`.
  num d = value.toDouble();
  if (d is T) return d; // T was double.
  try {
    num n = value.toInt(); // Can fail for Infinity/NaN
    if (n is T) return n; // T was int
  } catch (_) {
    // T was `int` after all, so throwing was correct.
    if (1 is T) rethrow; // T was int, but the input was not valid.
  }
  // T was neither num, double, nor int, so must be `Never`.
  throw ArgumentError.value(T, "T", "Must not be Never");
}

或者.使用Type对象等式:

T parse<T extends num>(String source) {
  var value = num.parse(source);
  switch (T) {
    case num: return value as T;
    case int: return value.toInt() as T;
    case double: return value.toDouble() as T;
    default: 
     throw ArgumentError.value(T, "T", "Must not be Never");
  }
}

相关问题