我正在构建一个示例应用程序,其中我的类型层次结构不适用于Visual Studio中的类型排序。无论我以何种方式安排文件(向上,向下),我都无法定义所有类。
所以按照他们在f#项目中的顺序
type Artist() =
let mutable artistId = 0
let mutable name = String.Empty
member x.ArtistId
with get() = artistId
and set (value) = artistId <- value
member x.Name
with get() = name
and set ( value ) = name <- value
type Genre() =
let mutable name = String.Empty
let mutable genreId = 0
let mutable description = String.Empty
let mutable albums = [new Album()]
member x.Name
with get() = name
and set (value) = name <- value
member x.GenreId
with get() = genreId
and set ( value ) = genreId <- value
member x.Description
with get() = description
and set ( value ) = description <- value
member x.Albums
with get() = albums
and set ( value ) = albums <- value
and Album() =
let mutable title = String.Empty
let mutable genre = new Genre()
let mutable albumId = 0
let mutable genreId = 0
let mutable artistId = 0
let mutable price : decimal = Decimal.Zero
let mutable albumArtUrl = String.Empty
let mutable artist = new Artist()
member x.Title
with get() = title
and set (value) = title <- value
member x.Genre
with get() = genre
and set (value) = genre <- value
member x.AlbumId
with get() = albumId
and set ( value ) = albumId <- value
member x.GenreId
with get() = genreId
and set ( value ) = genreId <- value
member x.ArtistId
with get() = artistId
and set ( value ) = artistId <- value
member x.Price
with get() = price
and set ( value ) = price <- value
member x.AlbumArtUrl
with get() = albumArtUrl
and set ( value ) = albumArtUrl <- value
member x.Artist
with get() = artist
and set ( value ) = artist <- value
所以在上面的情况下,我得到错误“Album”没有定义。
有办法解决这个问题吗?或者我只需要重新考虑我的类型的整个层次结构?
答案 0 :(得分:5)
如果您需要定义两个相互递归的类型(意味着它们可以相互引用),那么您需要将它们放在一个文件中并使用type ... and ...
语法。
在您的示例中,这意味着Genre
和Album
需要像这样定义:
// Start a definition block using 'type' as normal
type Genre() =
let mutable name = String.Empty
let mutable albums = [new Album()]
member x.Name
with get() = name
and set (value) = name <- value
member x.Albums
with get() = albums
and set ( value ) = albums <- value
// Continue single type definition block using 'and'
and Album() =
let mutable genre = new Genre()
let mutable albumId = 0
let mutable artist = new Artist()
member x.Genre
with get() = genre
and set (value) = genre <- value
member x.AlbumId
with get() = albumId
and set ( value ) = albumId <- value
member x.Artist
with get() = artist
and set ( value ) = artist <- value
但是,你的例子是在非常C#风格中使用F#,因此代码看起来并不是非常优雅,它可能无法为您提供函数式编程的许多好处。
如果我想表示您正在使用的结构,那么我可能不会将该类型的引用添加到Album
类型中。当您在Genre
内放置专辑列表时,您将始终能够在处理数据结构时恢复该类型(即将其转换为其他结构,可能是F#记录,可以传递给数据绑定)。 F#的优点在于它允许您在几行上编写域,但这仅适用于功能类型。
使用单一案例的歧视联盟,你可以写:
// Type aliases to make code more readable
type Name = string
type AlbumID = int
// Simple type definitions to represent the domain
type Artist = Artist of Name
type Album = Album of AlbumID * Artist
type Genre = Genre of Name * Album list