所以当我在我的F#代码中创建一些属性时,因为F#不支持自动属性,据我所知。我必须创建支持字段并将它们初始化为null,这在函数式编程术语中似乎不正确。对于例如
let mutable albums : DbSet = null
let mutable genres : DbSet = null
member x.Albums
with get() = albums
and set(value) = albums <- value
member x.Genres
with get() = genres
and set (value) = genres <- value
有没有更好的方法呢?非常感谢你的建议。
答案 0 :(得分:10)
当您需要可变属性时,F#不支持自动属性,但当您只需要 readonly 属性时,它支持轻量级语法。如果您正在编写一些功能代码,那么使用 readonly 属性可能实际上更合适:
type Music(genres : DbSet, albums : DbSet) =
member x.Albums = albums
member x.Genres = genres
这与pad建议的记录基本相同,但如果您希望更好地控制类型的外观(以及它们在C#中的显示方式或数据绑定方式),则可能更合适。
如果DbSet
是一个可变类型,那么您可能只需使用上述类型并将其初始化一次(您仍然可以修改DbSet
值)。如果要更改DbSet
值,可以添加返回克隆对象的方法:
member x.WithAlbums(newAlbums) =
Music(genres, newAlbums)
在F#中使用null
或Unchecked.defaultOf<_>
被认为是一种非常糟糕的做法,您应该始终尝试创建完全初始化的对象。如果该值可能丢失,您可以使用option
类型来表示该值,但是您必须始终为缺失值编写处理程序,以使您的程序安全。
答案 1 :(得分:5)
除非你做一些复杂的事情,否则我建议使用记录而不是类。基本上,它们是具有额外功能的类:不变性,结构相等,模式匹配等:
type Playlists = {
Albums: DbSet;
Genres: DbSet
}
您可以轻松获取记录字段:
let p = {Albums = ...; Genres = ...}
let albums = p.Albums
let genres = p.Genres
在默认记录中,字段是不可变的;你可以在记录中声明可变字段,但这被认为是一种不好的做法。虽然您无法设置属性,但可以使用旧记录创建新记录。默认的不变性通常不是问题,而且它使代码更具功能性,更容易推理:
let p = {Albums = a; Genres = g}
// Create new records by updating one field
let p1 = {p with Albums = a1}
let p2 = {p with Genres = g2}
如果您坚持创建类,建议使用带有显式参数的构造函数:
type Playlists(a: DbSet, g: DbSet) =
let mutable albums = a
let mutable genres = g
// ...
当需要默认构造函数时,可以将Unchecked.default<'T>
用于非可空字段,或者更好地使用它们的默认构造函数:
// Set fields using dump values
let mutable albums = new DbSet()
let mutable genres = new DbSet()
但请确保在实际使用之前设置这些字段。
答案 2 :(得分:5)
仅供参考 - 为F#3.0计划自动属性。请参阅preview documentation [MSDN]。看起来你的例子会变成:
type Music() =
member val Albums : DbSet = null with get, set
member val Genres : DbSet = null with get, set