F# - “自填”类型属性

时间:2015-01-11 06:08:59

标签: c# f#

在C#中,我可以拥有:

public class A {
    ...
    private List<int> _items;
    public List<int> Items{
        get {
            if (_items == null){
                _items = DAL.FetchFromDB();
            }
            return _items;
        }
    }
}

这样,我可以实例化A类,当我要求物品

  1. 我保证在没有明确填写清单的情况下得到它。
  2. 我避免重复调用数据库
  3. F#的等效构造是什么? 我不确定如何制作这样做的类型......

    我不一定要求一个可变列表;我想知道F#这样做的标准形式是什么,因为我只是学习语言。

2 个答案:

答案 0 :(得分:7)

正如ildjarn在上述评论中指出的那样,您可以以同等方式使用lazy关键字:

type A () =
    let items = lazy (DAL.FetchFromDB ())
    member this.Items with get () = items.Value

然而,问题在于它是否是惯用的&#39; F#,或者#39;良好做法&#39;总的来说?

Items属性不是referentially transparent(因为它不具有确定性),而且功能编程往往非常强调引用透明度。

当然:F#不是功能语言;它是一种功能优先语言。尽管如此,这意味着要充分利用它,您应该采用类似的功能优先方法来设计。

您自己的代码功能越多,您从F#中获得的价值就越大。

你制作F#代码的命令性,隐式或面向对象越多,你从中获得的就越少。

因此,尝试将C#逐字翻译成F#代码并不总是有意义的。你可以,但你会从中获得什么吗?

最重要的是,您可以将C#转换为与F#类似的内容,但您应该考虑它是否是一个好主意。使用lazy关键字没有任何内在错误,但隐含是我重新思考的内容。

答案 1 :(得分:6)

这是对F#的一对一转换:

type A() =
    let mutable _items = null
    member this.items 
        with get() = 
            if _items = null then _items <- DAL.FetchFromDB()
            _items

let a = A()

let x = a.items  // db access here
let y = a.items

有更好(和更短)的方法在F#中使用对象编写等效代码(请参阅另一个答案),但您根本不需要创建对象,您可以简单地定义一个函数,而其他人已经指出了你可以使用lazy关键字:

let items = 
    let v = lazy DAL.FetchFromDB()
    fun () -> v.Value

let x = items()  // db access here
let y = items()

或直接使用标准的延迟值,我更喜欢这个,因为你在items的类型中明确表示你的值是懒惰的,而不是隐藏在 magic 对象后面财产或职能:

let items = lazy DAL.FetchFromDB()

let x = items.Value  // db access here
let y = items.Value

所以现在items的类型是Lazy<'List<'T>>,它总是告诉你该值是懒惰计算的,除了在这种情况下代码实际上更短。