Concisely creating an IDictionary<_,obj>

后端 未结 7 1508
萌比男神i
萌比男神i 2020-12-03 23:09

Is there a shorter way of creating an IDictionary<_,obj>, possibly without boxing every value? This is what I have.

let values =
  [ \"a\"         


        
相关标签:
7条回答
  • 2020-12-03 23:47

    Here's another "solution" which is inspired from Brian's suggestion but it uses reflection so there is a time and safety cost.

    let unboxPair (pair:obj) =
        let ty = pair.GetType()
        let x = ty.GetProperty("Item1").GetValue(pair,null) :?> string
        let y = ty.GetProperty("Item2").GetValue(pair,null)
        x,y
    
    let unboxPairs (pairs:obj list) =
      pairs |> List.map unboxPair  
    
    let values =
      unboxPairs
        ["a", 1
         "b", "foo"
         "c", true]
      |> dict
    
    0 讨论(0)
  • 2020-12-03 23:49

    Yet another solution, simply define a bunch of overloaded extension members on Dictionary<'a,'b>:

    open System.Collections.Generic
    type Dictionary<'a,'b> with
        member this.Add(x1,y1,x2,y2) =
            this.Add(x1,y1)
            this.Add(x2,y2)
        member this.Add(x1,y1,x2,y2,x3,y3) =
            this.Add(x1,y1,x2,y2)
            this.Add(x3,y3)
        member this.Add(x1,y1,x2,y2,x3,y3,x4,y4) =
            this.Add(x1,y1,x2,y2,x3,y3)
            this.Add(x4,y4)
        member this.Add(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5) =
            this.Add(x1,y1,x2,y2,x3,y3,x4,y4)
            this.Add(x5,y5)
        member this.Add(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6) =
            this.Add(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5)
            this.Add(x6,y6)
        //etc.
    
    let values = 
        let d = Dictionary<_,obj>()
        d.Add("a", 1, 
              "b", "foo", 
              "c", true)
        d
    

    Of course values here is not immutable like in your question, but I'm sure you could employ the same strategy in that goal.

    0 讨论(0)
  • 2020-12-03 23:51

    A variation of Stephen's idea:

    open System
    open System.Collections.Generic
    
    type Dictionary<'a,'b> with
      member this.Add([<ParamArray>] args:obj[]) =
        match args.Length with
        | n when n % 2 = 0 ->
          for i in 1..2..(n-1) do
            this.Add(unbox args.[i-1], unbox args.[i])
        | _ -> invalidArg "args" "even number of elements required"
    
    let d = Dictionary<string,obj>()
    d.Add(
      "a", 1,
      "b", "foo",
      "c", true
    )
    
    0 讨论(0)
  • 2020-12-04 00:03

    I had a similar problem in FsSql and I just tucked away boxing in a function:

    let inline T (a,b) = a, box b
    let values = dict [T("a",1); T("b","foo"); T("c",true)]
    
    0 讨论(0)
  • 2020-12-04 00:09
    let v : (string*obj) list = [...]
    let values = dict v
    

    Is one way, the type signature on the left of the list literal will auto-upcast each element.

    0 讨论(0)
  • 2020-12-04 00:10

    Here's a solution, following kvb's suggestion (probably the most concise, and clearest, so far):

    let inline (=>) a b = a, box b
    
    let values =
      [ "a" => 1
        "b" => "foo"
        "c" => true ]
      |> dict
    
    0 讨论(0)
提交回复
热议问题