在Dart中,将动态转换为给定类型或返回null的语法上不错的方法吗?

时间:2018-10-03 16:57:05

标签: dart

我有一个dynamic x,如果x,我想将T s分配给x is T,否则将null分配给s。具体来说,我想避免不得不两次键入x,并避免创建一个临时文件。 (例如,我不想一遍又一遍地写String s = map['key'] is String ? map['key'] : null;,因为我会有很多这样的表达式。)我不希望有任何运行时错误的可能性。

以下作品:

class Cast<T> {
  T f(x) {
    if (x is T) {
      return x;
    } else {
      return null;
    }
  }
}

// ...

dynamic x = something();
String s = Cast<String>().f(x);

在语法上有更好的方法吗?

7 个答案:

答案 0 :(得分:10)

只需使用 as 关键字

final tweet = tweets[index] as Tweet;

答案 1 :(得分:4)

Dart 2具有允许使用的通用功能

T cast<T>(x) => x is T ? x : null;
dynamic x = something();
String s = cast<String>(x);

您也可以使用

var /* or final */ s = cast<String>(x);

并从String推断出s

答案 2 :(得分:4)

我使用以下实用程序功能,该功能允许使用可选的后备值和错误记录。

T tryCast<T>(dynamic x, {T fallback}){
    try{
        return (x as T);
    }
    on CastError catch(e){
        print('CastError when trying to cast $x to $T!');
        return fallback;
    }
}
var x = something();
String s = tryCast(x, fallback: 'nothing');

答案 3 :(得分:2)

我正在使用具有 Dart 空安全性的那些(Dart SDK >= 2.12):

T? castOrNull<T>(dynamic x) => x is T ? x : null;

T castOrFallback<T>(dynamic x, T fallback) => x is T ? x : fallback;

答案 4 :(得分:1)

前两个帖子的组合,不进行记录。

不提供时,Fallback默认为null。

T cast<T>(dynamic x, {T fallback}) => x is T ? x : fallback;

答案 5 :(得分:0)

<块引用>

CastError 已弃用,而是使用 TypeError。

使用 null 安全性,您可以尝试以下代码段。回退是可选的/可为空的。

T? tryCast<T>(dynamic value, {T? fallback}) {
  try {
    return (value as T);
  } on TypeError catch (_) {
    return fallback;
  }
}

或者没有后备 -

T? tryCast<T>(dynamic value) {
  try {
    return (value as T);
  } on TypeError catch (_) {
    return null;
  }
}

用法 -

final val = tryCast<String>(1) ?? "";

答案 6 :(得分:-1)

编辑

弄清楚我的答案有很大问题,类型检查不正确。例如,即使T is num被传递Tnum也会返回false。我暂时通过显式检查T与所需类型(如T == int && T == double)是否相等来解决此问题,但这对于检查诸如T == num的子类类型可能不起作用。总的来说,我编辑了答案,因此现在可以正常工作。尽管答案是正在进行的工作,当我找到解决此类型检查问题的方法时,它将得到更好的改善。


这是我的修改后的版本,支持在num中解析int(即doubleDateTime)和tryCast

用法

var decimalNumber = tryCast<double>("42.42", fallback: 0);
var integerNumber = tryCast<int>("42", fallback: 0);
var currentTimestamp = tryCast<DateTime>(DateTime.now().toIso8601String(), fallback: DateTime.now());
var someType = tryCast<SomeType>(jsonString['someType'], fallback: null);

解决方案

/// Casts `x` of [dynamic] type to [T] type. With fallback value `fallback` if casting failed
/// Supports tryParse from [String] to {[num],[DateTime], [Uri]}
/// Edited from [this ](https://stackoverflow.com/a/59714798/10830091) StackOverflow answer
T tryCast<T>(dynamic x, {T fallback}) {

  // tryParse from [String] `x`
  if (x is String) {
    if (T == int || T == double) {
      // tryParse to [num] (i.e. [int], [double])
      return num.tryParse(x) as T ?? fallback;
    } else if (T == DateTime) {
      // tryParse to [DateTime]
      return DateTime.tryParse(x) as T ?? fallback;
    } else if (T == Uri) {
      // tryParse to [Uri]
      return Uri.tryParse(x) as T ?? fallback;
    }
  }

  try {
    return (x as T) ?? fallback;
  } on CastError catch (e) {
    print('CastError when trying to cast $x to $T! Exception catched: $e');
    return fallback;
  }
}

灵感来自Magnus的answer