简洁地创建一个 IDictionary<_ ,obj>;

发布于 2024-12-04 13:17:37 字数 438 浏览 1 评论 0原文

是否有更短的方法来创建 IDictionary<_,obj>,可能不需要装箱每个值?这就是我所拥有的。

let values =
  [ "a", box 1
    "b", box "foo"
    "c", box true ]
  |> dict

Dictionary<_,obj>.Add 可以在不装箱的情况下调用,但我无法找到比我所拥有的更短的使用方法。

我希望除了定义拳击操作员之外还有其他东西。

编辑

根据布莱恩的建议,这是一种方法,但它有其自身的问题。

let values =
  Seq.zip ["a"; "b"; "c"] ([1; "foo"; true] : obj list) |> dict

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

let values =
  [ "a", box 1
    "b", box "foo"
    "c", box true ]
  |> dict

Dictionary<_,obj>.Add can be called without boxing, but I couldn't figure out a way to use it that's shorter than what I have.

I'm hoping for something other than defining a boxing operator.

EDIT

Based on Brian's suggestion, here's one way to do it, but it has its own problems.

let values =
  Seq.zip ["a"; "b"; "c"] ([1; "foo"; true] : obj list) |> dict

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

短暂陪伴 2024-12-11 13:17:37

这是一个解决方案,遵循 kvb 的建议(可能是迄今为止最简洁、最清晰的):

let inline (=>) a b = a, box b

let values =
  [ "a" => 1
    "b" => "foo"
    "c" => true ]
  |> dict

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
暖阳 2024-12-11 13:17:37

这是我能做的最巧妙的事情。它比你的拳击版本有更多的角色,但可能感觉不那么肮脏。请注意,^ 是右关联的(它是从 ocaml 继承的字符串连接运算符),这让它像 :: 一样工作,并且它比 具有更强的优先级,,这就是元组周围需要括号的原因。

let inline (^+) (x1:'a,x2:'b) (xl:('a*obj) list) = 
    (x1,box x2)::xl

let values =
  ("a", 1) ^+  ("b", "foo") ^+ ("c", true) ^+ []
  |> dict

Here's the slickest thing I was able to whip up. It has more characters than your boxing version, but possibly feels a little less dirty. Note that the ^ is right-associative (it's the string concat operator inherited from ocaml), which lets it work like ::, and it has stronger precedence than ,, which is why the parenthesis are needed around the tuples.

let inline (^+) (x1:'a,x2:'b) (xl:('a*obj) list) = 
    (x1,box x2)::xl

let values =
  ("a", 1) ^+  ("b", "foo") ^+ ("c", true) ^+ []
  |> dict
耳钉梦 2024-12-11 13:17:37

我在 FsSql 中遇到了类似的问题,我只是将拳击隐藏在函数中:

let inline T (a,b) = a, box b
let values = dict [T("a",1); T("b","foo"); T("c",true)]

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)]
洒一地阳光 2024-12-11 13:17:37

这是另一个“解决方案”,其灵感来自 Brian 的建议,但它使用反射,因此存在时间和安全成本。

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

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
溺ぐ爱和你が 2024-12-11 13:17:37

斯蒂芬的想法的一个变体:

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
)

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
)
魂归处 2024-12-11 13:17:37

还有另一种解决方案,只需在 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

当然,这里的values不是是不可变的就像你的问题一样,但我相信你可以在该目标中采用相同的策略。

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.

为你拒绝所有暧昧 2024-12-11 13:17:37
let v : (string*obj) list = [...]
let values = dict v

一种方法是,列表文字左侧的类型签名将自动向上转换每个元素。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文