12

I know that in F# if you have a C# class of the format:

public class Person {
    public DateTime BirthDate { get; set; }
    public string Name { get; set; }
}

You can initialize it like so, which is nice:

let p = new Person (Name = "John", BirthDate = DateTime.Now)

However how would you initialize it in F# if the C# class also had a constructor like this:

public class Person {
    public Person(int id)
    {
        Id = id
    }

    public int Id {get; private set;}
    public DateTime BirthDate { get; set; }
    public string Name { get; set; }
}

Are we forced to use this structure instead?

let p = new Person (123)
p.Name <- "John"
p.BirthDate <- DateTime.Now
Community
  • 1
  • 1
Luke Merrett
  • 5,724
  • 8
  • 38
  • 70
  • Possible duplicate of [Object initialization syntax](http://stackoverflow.com/questions/371878/object-initialization-syntax) – Anton Schwaighofer Dec 30 '16 at 11:00
  • @AntonSchwaighofer covers a similar topic, but asks how to do so with the addition of a constructor, which the referenced question does not. – Luke Merrett Dec 30 '16 at 11:23

2 Answers2

17

Using the equivilent F# syntax for auto properties might look like this. You are able to combine the constructor and property initialization as follows:

type Person(id : int) =
    member val Id = id with get,set
    member val BirthDate = DateTime.MinValue with get,set
    member val Name = "" with get,set

let p = Person(5, Name = "Stu")
p |> Dump
Stuart
  • 5,358
  • 19
  • 28
  • I see so it's the explicit declaration of property names that differentiates between the constructor and the initialization of the member properties? – Luke Merrett Dec 30 '16 at 11:21
  • 2
    Yes, so see [here](https://learn.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/members/constructors#assigning-values-to-properties-at-initialization) for details, including how you can mix optional constructor parameters and property setters, they must be named uniquely wrt properties, other than that the logic to resolve the constructor is as you would expect. – Stuart Dec 30 '16 at 11:54
6

The System.UriBuilder BCL class looks like the Person class in the OP, so I'll use that as an example:

> let ub = UriBuilder("http://blog.ploeh.dk", Path = "about");;    
val ub : UriBuilder = http://blog.ploeh.dk:80/about
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736