确定任何类型的列表、序列、数组或 IEnumerable 是否为空

Determine if any kind of list, sequence, array, or IEnumerable is empty

我正在编写一个 Xamarin.Forms 应用程序,使用 XAML 作为我的观点,我正在尝试编写一个 IValueConverter 如果输入,它的工作应该返回 false "empty" 对于那些语义有意义的类型 (strings/lists/sequences/arrays/IEnumerables)。我从以下内容开始,对于空字符串 returns false,但我不知道如何将其扩展到列表、序列、数组和 IEnumerables:

type FalseIfEmptyConverter() =
  interface IValueConverter with 
    member __.Convert(value:obj, _, _, _) = 
      match value with
      | :? string as s -> (s <> "" && not (isNull s)) |> box
      // TODO: extend to enumerables
      | x -> invalidOp <| "unsupported type " + x.GetType().FullName

    member __.ConvertBack(_, _, _, _) =
      raise <| System.NotImplementedException()

我尝试过但不起作用的方法:

利用Foggy Finder的思路来使用非泛型IEnumerable:

let isEmpty (x:obj) =
    match x with
    | null -> true
    | :? System.Collections.IEnumerable as xs -> xs |> Seq.cast |> Seq.isEmpty
    | _ -> invalidOp <| "unsupported type " + x.GetType().FullName

isEmpty "" // true
isEmpty [] // true
isEmpty (set []) // true
isEmpty [||] // true
isEmpty null // true

isEmpty "a" // false
isEmpty [|1|] // false

isEmpty 1 // exception

您要测试的所有类型都是 Seq<'a> 的子类型,这与 IEnumerable<'a> 完全相同(包括 string,它是 seq<char>).但这也是称为 IEnumerable 的非泛型类型的子类型(注意缺少类型参数)。这类似于 IEnumerable<obj>,其中每个项目都已装箱。这就是为什么我们可以将所有这些转换为 IEnumerable,然后使用 Seq.cast 将其转换为 IEnumerable<obj>,这样我们就可以使用 Seq.empty,它只适用于泛型.