【问题标题】:How to define a type extension for T[] in F#?如何在 F# 中为 T[] 定义类型扩展?
【发布时间】:2012-08-06 21:25:02
【问题描述】:

在 C# 中,我可以为 T 类型的泛型数组定义扩展方法,如下所示:

public static T GetOrDefault<T>(this T[] arr, int n)
{
    if (arr.Length > n)
    {
        return arr[n];
    }

    return default(T);
}

但对于我来说,我无法弄清楚如何在 F# 中做同样的事情!我试过type 'a array withtype array&lt;'a&gt; withtype 'a[] with,编译器对它们都不满意。

谁能告诉我在 F# 中这样做的权利是什么?

当然,我可以通过遮盖 Array 模块并轻松添加一个函数来做到这一点,但我真的很想知道如何将它作为扩展方法!

【问题讨论】:

  • “为了我的一生”是什么意思:)?
  • 扩展System.Array 是我的第一个想法,但除非您对obj 满意,否则需要类型参数和强制转换。
  • @Chuck Norris - 意思是'我不能......即使我非常努力'

标签: c# arrays f# extension-methods


【解决方案1】:

您必须使用“反引号”来编写数组类型 - 像这样:

type 'a ``[]`` with
  member x.GetOrDefault(n) = 
    if x.Length > n then x.[n]
    else Unchecked.defaultof<'a>

let arr = [|1; 2; 3|]
arr.GetOrDefault(1) //2
arr.GetOrDefault(4) //0

编辑:语法type ``[]``&lt;'a&gt; with ... 似乎也是允许的。在 F# 源代码(prim-types-prelude.fs)中可以找到以下定义:

type ``[]``<'T> = (# "!0[]" #)

【讨论】:

  • @Daniel:实验。我试图在规范/文档中找到任何内容,但没有成功。
【解决方案2】:

好问题。我不知道如何扩展'T[],但您可以利用数组实现IList&lt;_&gt; 的事实来做:

type System.Collections.Generic.IList<'T> with
  member x.GetOrDefault(n) = 
    if x.Count > n then x.[n]
    else Unchecked.defaultof<'T>

let arr = [|1; 2; 3|]
arr.GetOrDefault(1) //2
arr.GetOrDefault(4) //0

【讨论】:

  • 我很确定 F# 中没有合法的语法可以向数组类型添加扩展成员,所以这可能是最好的选择(除了事实之外,我想不出任何缺点此方法也出现在任何其他 IList 类型上)。
  • @Daniel - 天哪,你是对的! 'T [] 确实实现了 IList!我不知道!不确定这对我是否有意义,数组占用连续的内存块,对吗?所以每次添加操作肯定都必须为整个新数组重新分配,在我看来,你应该鼓励和鼓励使用 List (它有一个内部缓冲区)来代替。跨度>
  • IList&lt;_&gt;的变异成员,Add/Remove等,抛出NotSupportedException。试试:([|1|] :&gt; System.Collections.Generic.IList&lt;_&gt;).Add(2)
  • @kvb - 我的记忆是这样的东西的筛子:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-13
  • 1970-01-01
相关资源
最近更新 更多