在C#中,我可以这样:
public class A {
...
private List<int> _items;
public List<int> Items{
get {
if (_items == null){
_items = DAL.FetchFromDB();
}
return _items;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这样,我可以实例化A类,当我要求物品时
什么是F#的等效结构?我不确定如何制作一个这样做的类型......
我不一定要求一个可变的清单; 我想知道在F#中做这样的事情的标准形式是什么,因为我只是学习语言.
正如ildjarn在上述评论中指出的那样,您可以lazy以相同的方式使用关键字:
type A () =
let items = lazy (DAL.FetchFromDB ())
member this.Items with get () = items.Value
Run Code Online (Sandbox Code Playgroud)
然而,问题在于它是"惯用的"F#还是"良好实践"?
该Items属性不是引用透明的(因为它不是确定性的),而且功能编程往往非常强调引用透明性.
当然:F#不是一种纯粹的功能语言; 它是功能第一语言.尽管如此,这意味着要充分利用它,您应该采用类似的功能优先方法来设计.
你自己的代码功能越多,你从F#获得的价值就越大.
你制作F#代码的命令,隐式或面向对象越多,你获得的代码就越少.
因此,尝试将C#逐字翻译成F#代码并不总是有意义的.你可以,但你会从中获得什么吗?
最重要的是,你可以将你的C#翻译成类似于F#的东西,但你应该考虑它是否是一个好主意.使用lazy关键字没有任何内在错误,但隐含性是我要重新考虑的事情.
这是对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
Run Code Online (Sandbox Code Playgroud)
有更好(和更短)的方法在F#中使用对象编写等效代码(参见另一个答案),但你根本不需要创建一个对象,你可以简单地定义一个函数,而其他人已经指出你可以使用lazy关键字:
let items =
let v = lazy DAL.FetchFromDB()
fun () -> v.Value
let x = items() // db access here
let y = items()
Run Code Online (Sandbox Code Playgroud)
或者直接使用标准的延迟值,我更喜欢这个,因为你在类型中明确items表示你的值是惰性求值而不是隐藏在魔术对象属性或函数后面:
let items = lazy DAL.FetchFromDB()
let x = items.Value // db access here
let y = items.Value
Run Code Online (Sandbox Code Playgroud)
所以,现在的类型items就是Lazy<'List<'T>>它总是告诉你,值将是懒惰的计算,除了在这种情况下的代码实际上是更短.