Determine if a List, Sequence, Array, or IEnumerable Is Empty

I am writing an Xamarin.Forms application using XAML for my views, and I am trying to write an IValueConverter whose job should return false if the input is "empty" for types where these semantics make sense (strings / lists / sequence / arrays / IEnumerables). I started with the following, which returns false for empty strings, but I can't figure out how to extend this for lists, sequences, arrays, and 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() 

Things I tried that don't work:

  • :? list<_> :? list<_> does not match the list (in the box) (at least not from int) and issues a warning This construct causes code to be less generic than indicated by its type annotations. The type variable implied by the use of a '#', '_' or other type annotation at or near [...] has been constrained to be type 'obj' This construct causes code to be less generic than indicated by its type annotations. The type variable implied by the use of a '#', '_' or other type annotation at or near [...] has been constrained to be type 'obj'
  • :? list<obj> :? list<obj> does not display a warning, but also does not match the index list enclosed in the box
  • Same thing with :? seq<_> :? seq<_> and :? seq<obj> :? seq<obj>
  • Same thing with :? System.Collections.Generic.IEnumerable<obj> :? System.Collections.Generic.IEnumerable<obj> and IEnumerable<_> (and if I put it below a similar seq match as above, it warns that the rule will never be consistent, which makes sense, since AFAIK seq matches before IEnumerable )
+5
source share
1 answer

Using the Foggy Finder idea to use non-generic 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 

All the types you want to test are subtypes of Seq<'a> that exactly match IEnumerable<'a> (including string , which is seq<char> ). But this is also a subtype of a non-generic type called IEnumerable (note the lack of a type parameter). This is similar to IEnumerable<obj> , where each element is placed in a box. That's why we can apply all of this to IEnumerable , and then use Seq.cast to convert to IEnumerable<obj> so that we can use Seq.empty , which only works with the generic type.

+6
source

Source: https://habr.com/ru/post/1273345/


All Articles