2017-11-14 6 views
5

XAMLを使用してXAMLを使用しているビューをXAMLで書いています。入力がfalseの場合はIValueConverterと書いています。これらのセマンティクスが意味をなす型(文字列/リスト/シーケンス/配列/ IEnumerables)に対しては "空"です。私は空の文字列についてfalseを返す以下、で開始しているが、私はリスト、シーケンス、配列、IEnumerablesにこれを拡張する方法を見つけ出すことはできません。リスト、シーケンス、配列、またはIEnumerableの種類が空であるかどうかを確認する

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() 

は、物事は私が試したことドン」 T作業:

  • :? list<_>は、(少なくともintの)(箱入り)のリストと一致し、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>は警告を生成しない警告を生成するだけでなく、の箱入りリストと一致しないしませんints
  • Itそれは​​とIEnumerable<_>と同じだ(と上記のように私は似seq試合の下に配置した場合、それは私の知る限りseq対応しているので理にかなっている、ルールが一致することはないだろうと警告し:? seq<_>:? seq<obj>
  • と同じ)IEnumerableから
+2

'一致値は です。 :? System.Collections.IEnumerableとしてs - > s.GetEnumerator()。MoveNext()|> not | x - > invalidOp <| "サポートされていないタイプ" + x.GetType()。FullName' –

答えて

6

非ジェネリックIEnumerableを使用するフォギーFinderのアイデアを使用する:

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 

テストしたいタイプのすべてがのサブタイプですであり、IEnumerable<'a>stringを含み、これはseq<char>です)とまったく同じです。しかしこれはIEnumerableと呼ばれる非ジェネリック型のサブタイプでもあります(タイプパラメータがないことに注意してください)。これはIEnumerable<obj>に似ています。ここではすべてのアイテムがボックス化されています。このため、これらのすべてをIEnumerableにキャストしてからSeq.castを使用してIEnumerable<obj>に変換し、Seq.emptyを使用できるようにします。これは汎用タイプでのみ機能します。

+0

素晴らしい動作です。しかし、なぜIEnumerable 'の代わりに' IEnumerable'を使わなければならないのか分かりません。少し詳しく説明できますか? – cmeeren

+2

型テストを行うとき、 'string'は' seq 'で、' char'は 'obj'ですが、' string'は 'seq 'ではありません。祖先型のチェックは、たとえ理論的に可能であっても、型パラメーターまで拡張されません。なぜF#がそのように振る舞うのか、それが.NETのために実際にあるのか、ここに根本的な難しさがあるのか​​、機能の欠如に対するものなのか分かりません。 – TheQuickBrownFox

+0

ありがとう、それはそれをクリアし、多かれ少なかれ私が疑ったものです。 – cmeeren

関連する問題