F# [StructuredFormatDisplay] attribute
A short post about a little-known attribute in the F# standard library: StructuredFormatDisplayAttribute. It controls how values are formatted with the %A format specifier (in printf, sprintf, and other functions in the Printf module), as well as how values of the type appear in F# Interactive. If you define a custom type like this:
type Person(name: string, age: int, money: decimal) =
member __.Name = name
member __.Age = age
member __.Money = money
let alex = Person("Alex", 22, 200000m)
Instances of the type will appear in F# Interactive as follows:
val alex : Person = FSI.Person
Overriding System.Object.ToString() lets you see the object’s internal state in the interactive console: both F# Interactive and %A use a ToString() override when one is available:
type Person(name: string, age: int, money: decimal) =
member __.Name = name
member __.Age = age
member __.Money = money
override __.ToString() =
sprintf "Person(%s, %d, %O)" name age money
let alex = Person("Alex", 22, 200000m)
Output:
val alex : Person = Person(Alex, 22, 200000M)
Sometimes, though, the text returned by ToString() is not what you want to see in F# Interactive or when formatting a value with %A. The [<StructuredFormatDisplay>] attribute lets you specify a separate display format. Its format string has the form "Prefix {PropertyName} Suffix", where Prefix and Suffix are optional literal text, and PropertyName is the name of a property defined in the type or one of its base classes:
[<StructuredFormatDisplay("Person (with Name='{Name}')")>]
type Person(name: string, age: int, money: decimal) =
member __.Name = name
member __.Age = age
member __.Money = money
override __.ToString() =
sprintf "Person(%s, %d, %O)" name age money
let alex = Person("Alex", 22, 200000m)
The output now looks like this:
val alex : Person = Person (with Name='Alex')
The format string can refer to only one property. Literal { and } characters are not supported, even when escaped as {{ and }}. Properties declared private are supported.