在C#中,我可以拥有:
public class A {
...
private List<int> _items;
public List<int> Items{
get {
if (_items == null){
_items = DAL.FetchFromDB();
}
return _items;
}
}
}
这样,我可以实例化A类,当我要求物品
时F#的等效构造是什么? 我不确定如何制作这样做的类型......
我不一定要求一个可变列表;我想知道F#这样做的标准形式是什么,因为我只是学习语言。
答案 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>>
,它总是告诉你该值是懒惰计算的,除了在这种情况下代码实际上更短。