3

I have a record type which occurs quite often in a nested complex data structure. Because the record type has an automatically generated ToString the ToString of my bigger structure becomes way to confusing and I do not care for the string representation of my record.
So I want to have an empty string as representation for my record. Overriding ToString seems to not do anything, using StructuredFormatDisplay does not work with empty strings since it requires an input of the form "Text {Field} Text". Right now I have

[<StructuredFormatDisplay("{}")>]
type MyRecord
    {  5 fields... }

    override __.ToString () = ""

But this results in The method MyRecord.ToString could not be found.

So what is the correct way to not have a string representation for a record type?

danielspaniol
  • 2,228
  • 21
  • 38
  • 1
    I can't understand your Q, what do you mean by `Overriding ToString seems to not do anything, `? – FoggyFinder Jun 27 '18 at 13:13
  • If I override `ToString` I still get the same result as if I do not override `ToString`. In both cases `sprintf "%A" myObj` will print the default string representation – danielspaniol Jun 27 '18 at 13:15
  • 1
    well, yeah - you have to call `myObj.ToString()` instead of `sprintf "%A" myObj` – FoggyFinder Jun 27 '18 at 13:18
  • 4
    See the accepted answer for https://stackoverflow.com/questions/791706/how-do-i-customize-output-of-a-custom-type-using-printf — you just need an `AsString` *property* that returns `""`, then you'd do `[]` – rmunn Jun 27 '18 at 13:21
  • @rmunn then it is a duplicate, right? Or maybe someone write an answer about difference between `ToString` and `sprintf`? – FoggyFinder Jun 27 '18 at 13:30
  • 3
    The `%A` format specification doesn't necessarily use `ToString()`. To print an object using its `ToString()` method, use `%O` instead of `%A`. See [Core.Printf Module (F#)](https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/core.printf-module-%5bfsharp%5d). – phoog Jun 27 '18 at 14:16

1 Answers1

5

The comments all provide correct information about how to achieve your goal. Pulling it all together, here's what I would do in a real-world scenario where I wanted a record type to always have the empty string as its string representation:

open System

[<StructuredFormatDisplay("{StringDisplay}")>]
type MyRecord =
    {  
        A: int
        B: string
        C: decimal
        D: DateTime
        E: Guid
    }
    member __.StringDisplay = String.Empty
    override this.ToString () = this.StringDisplay

This way, regardless of what technique is used to print the record, or if its ToString method is used by an external caller, the representation will always be the same:

let record = {A = 3; B = "Test"; C = 5.6M; D = DateTime.Now; E = Guid.NewGuid()}
printfn "Structured Format Display:  %A" record
printfn "Implicit ToString Call:  %O" record
printfn "Explicit ToString Call:  %s" <| record.ToString()

This prints:

Structured Format Display:  
Implicit ToString Call:  
Explicit ToString Call:  

One thing to keep in mind is that this will even override the way the record is displayed by F# interactive. Meaning, the record evaluation itself now shows up as:

val record : MyRecord = 
Aaron M. Eshbach
  • 6,380
  • 12
  • 22
  • This works, thank you. Out of curiosity why does it display `The method MyRecord.ToString could not be found` when I use `[]` – danielspaniol Jun 28 '18 at 06:12