Reputation: 3755
I'm trying to avoid creating a default object in F#, at least in its full capacity to that I can represent it in WPF.
I read THIS post . So I tried implenting the type as a class, thinking that it would be optional in C# as well.
type OrderException(?id: Guid, ?orderId: Guid, ?orderNumber: string) =
member x.id = id
member x.OrderID = orderId
member x.OrderNumber = orderNumber
So - in F# I can create an empty object:
let orderException = new OrderException()
But if I use the library in C# and try to instantiate the object - then I get:
There is no argument given that corresponds to the required formal parameter 'id' of 'Artoo.OrderException.OrderException(FSharpOption, FSharpOption, FSharpOption)' Zimpla.Windows D:\Core\Zimpla\Zimpla.Windows\ViewModels\ResolveExceptionsViewModel.cs 26 N/A
So - back to square one. The only way I can see around this is to have an F# method that creates a "default" version of the object with nothing in it.
Upvotes: 1
Views: 261
Reputation: 243096
Depending on what exactly you want, it may also be worth using idiomatic F# style, like optional parameters in the ?id
format, but adding an overloaded default constructor. If you only need this for C# (or even WPF) then you could even annotate this with an attribute to produce a warning if the constructor is used from F#:
open System
type OrderException(?id: Guid, ?orderId: Guid, ?orderNumber: string) =
[<CompilerMessage("Default constructor should not be used from F#!",0)>]
new() = OrderException(?id=None)
member x.id = id
member x.OrderID = orderId
member x.OrderNumber = orderNumber
OrderException() // F# warning - should not be used!
OrderException(Guid.NewGuid()) // This is fine
Upvotes: 1
Reputation: 22123
From F# documentation:
For the purposes of C# and Visual Basic interop you can use the attributes [<Optional; DefaultParameterValue<(...)>] in F#, so that callers will see an argument as optional. This is equivalent to defining the argument as optional in C# as in MyMethod(int i = 3).
type OrderException(
[<Optional; DefaultParameterValue(Guid())>]id: Guid,
[<Optional; DefaultParameterValue(Guid())>]orderId: Guid,
[<Optional; DefaultParameterValue("")>]orderNumber: string) =
member x.id = id
member x.OrderID = orderId
member x.OrderNumber = orderNumber
That said, a record with an Empty
property is quite an idiomatic pattern and I'd favor this here.
type OrderException =
{ Id: Guid
OrderId: Guid
OrderNumber: String }
with
static member Empty =
{ Id = Guid.Empty
OrderId = Guid.Empty
OrderNumber = "" }
Upvotes: 2