Skip to content

C#-style optional arguments defined in F# cannot be consumed by F# as optional #1783

@kurtschelfthout

Description

@kurtschelfthout

It looks like fsc generates slightly different code for optional arguments defined in C# style (i.e. attributed with Optional; DefaultParameterValue(...)) than csc does. Interestingly, C# doesn't mind, i.e. it can consume these methods and recognizes the optionality, but F# itself cannot.

Repro steps

Define a method like:

type Methods = 
    static member NormalOverload(t : string, [<Optional;DefaultParameterValue(0)>] i : int) = ()

Calling it from F# without providing the i results in a compiler error.

Using ILSpy to look at the generated code:

.method public static 
	void NormalOverload (
		string t,
		[opt] int32 i
	) cil managed 
{
	.param [2]
	.custom instance void [System]System.Runtime.InteropServices.DefaultParameterValueAttribute::.ctor(object) = (
		01 00 08 00 00 00 00 00 00
	)
	// Method begins at RVA 0x2050
	// Code size 2 (0x2)
	.maxstack 8

	IL_0000: nop
	IL_0001: ret
} // end of method Methods::NormalOverload

Whereas for a similar method defined in C#:

public static class CsClass
    {
        public static void Overload(string s, int i = 0) {    }

it is:

.method public hidebysig static 
	void Overload (
		string s,
		[opt] int32 i
	) cil managed 
{
	.param [2] = int32(0)
	// Method begins at RVA 0x2050
	// Code size 2 (0x2)
	.maxstack 8

	IL_0000: nop
	IL_0001: ret
} // end of method CsClass::Overload

Expected behavior

To be able to call the method defined in F# without providing the optional parameter:

        Methods.NormalOverload("")

Actual behavior

Compile error:

This expression was expected to have type
    string * int    
but here has type
    string

Known workarounds

No known workarounds.

Related information

Windows, .NET 4.6.1, F# 4.0, Visual Studio 2015

Probably not a huge deal as the the main use cases (C# interop) seem to work, but it is surprising and perhaps we are dependent on some csc leniency there that might go away at some point.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions