F#属性设计

net*_*x01 6 f#

因此,当我在我的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
Run Code Online (Sandbox Code Playgroud)

这样做有更好的方法吗?非常感谢你的建议.

Tom*_*cek 10

当您需要可变属性时,F#不支持自动属性,但是当您只需要readonly属性时,它支持轻量级语法.如果您正在编写一些功能代码,那么使用readonly属性可能实际上更合适:

type Music(genres : DbSet, albums : DbSet) = 
  member x.Albums = albums
  member x.Genres = genres
Run Code Online (Sandbox Code Playgroud)

这与pad建议的记录基本相同,但如果您希望更好地控制类型的外观(以及它们在C#中的显示方式或数据绑定方式),则可能更合适.

如果DbSet是一个可变类型,那么你可能只需使用上面的类型并初始化它一次(你仍然可以修改DbSet值).如果要更改该DbSet值,可以添加一个返回克隆对象的方法:

  member x.WithAlbums(newAlbums) = 
    Music(genres, newAlbums)
Run Code Online (Sandbox Code Playgroud)

使用nullUnchecked.defaultOf<_>在F#中被认为是一种非常糟糕的做法,你应该总是尝试创建完全初始化的对象.如果该值可能丢失,您可以使用optiontype来表示该值,但是您必须始终为缺失值编写处理程序,以使程序安全.


pad*_*pad 5

除非你做一些复杂的事情,否则我建议使用记录而不是类.基本上,它们是具有额外功能的类:不变性,结构相等,模式匹配等:

type Playlists = {
    Albums: DbSet;
    Genres: DbSet
    }
Run Code Online (Sandbox Code Playgroud)

您可以轻松获取记录的字段:

let p = {Albums = ...; Genres = ...}
let albums = p.Albums
let genres = p.Genres
Run Code Online (Sandbox Code Playgroud)

在默认记录中,字段是不可变的; 你可以在记录中声明可变字段,但这被认为是一种不好的做法.虽然您无法设置属性,但可以使用旧记录创建新记录.默认的不变性通常不是问题,而且它使代码更具功能性,更容易推理:

   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} 
Run Code Online (Sandbox Code Playgroud)

如果您坚持创建类,建议使用带有显式参数的构造函数:

type Playlists(a: DbSet, g: DbSet) =
     let mutable albums = a
     let mutable genres = g
     // ...
Run Code Online (Sandbox Code Playgroud)

当需要默认构造函数时,可以使用Unchecked.default<'T>非可空字段,或者更好地使用它们的默认构造函数:

 // Set fields using dump values
 let mutable albums = new DbSet()
 let mutable genres = new DbSet()
Run Code Online (Sandbox Code Playgroud)

但请确保在实际使用它们之前设置这些字段.


Dan*_*iel 5

仅供参考 - 计划用于F#3.0的自动属性.请参阅预览文档[MSDN].看起来你的例子会变成:

type Music() =
  member val Albums : DbSet = null with get, set
  member val Genres : DbSet = null with get, set
Run Code Online (Sandbox Code Playgroud)