I have the following C# classes
public class BadClass
{
public BadClass(int? bad = 1)
{
}
}
public class GoodClass
{
public GoodClass(int? good = null)
{
}
}
As you can see they both have optional nullable parameters as part of their constructors, the only difference is that BadClass has the parameter default set to something other than null.
If I attempt to create an instance of these classes in F# this is what I get:
This works fine:
let g = GoodClass()
This throws a NullReferenceException:
let b = BadClass()
And this throws an AccessViolationException
let asyncB = async { return BadClass() } |> Async.RunSynchronously
Any idea why this is?
EDIT
Using ILSpy to decompile it this is the output of the F#
The C# classes are in an assembly called InteopTest [sic]
ILSpy to C#
GoodClass g = new GoodClass(null);
BadClass b = new BadClass(1);
FSharpAsyncBuilder defaultAsyncBuilder = ExtraTopLevelOperators.DefaultAsyncBuilder;
FSharpAsync<BadClass> fSharpAsync = defaultAsyncBuilder.Delay<BadClass>(new Program.asyncB@10(defaultAsyncBuilder));
FSharpAsync<BadClass> computation = fSharpAsync;
BadClass asyncB = FSharpAsync.RunSynchronously<BadClass>(computation, null, null);
FSharpFunc<string[], Unit> fSharpFunc = ExtraTopLevelOperators.PrintFormatLine<FSharpFunc<string[], Unit>>(new PrintfFormat<FSharpFunc<string[], Unit>, TextWriter, Unit, Unit, string[]>("%A"));
fSharpFunc.Invoke(argv);
return 0;
and this is the IL
.method public static
int32 main (
string[] argv
) cil managed
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.EntryPointAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2050
// Code size 92 (0x5c)
.maxstack 5
.entrypoint
.locals init (
[0] class [InteopTest]InteopTest.GoodClass g,
[1] valuetype [mscorlib]System.Nullable`1<int32>,
[2] class [InteopTest]InteopTest.BadClass b,
[3] class [InteopTest]InteopTest.BadClass asyncB,
[4] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [InteopTest]InteopTest.BadClass>,
[5] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder builder@,
[6] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [InteopTest]InteopTest.BadClass>,
[7] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string[], class [FSharp.Core]Microsoft.FSharp.Core.Unit>,
[8] string[]
)
IL_0000: nop
IL_0001: ldloca.s 1
IL_0003: initobj valuetype [mscorlib]System.Nullable`1<int32>
IL_0009: ldloc.1
IL_000a: newobj instance void [InteopTest]InteopTest.GoodClass::.ctor(valuetype [mscorlib]System.Nullable`1<int32>)
IL_000f: stloc.0
IL_0010: ldc.i4.1
IL_0011: newobj instance void [InteopTest]InteopTest.BadClass::.ctor(valuetype [mscorlib]System.Nullable`1<int32>)
IL_0016: stloc.2
IL_0017: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_DefaultAsyncBuilder()
IL_001c: stloc.s builder@
IL_001e: ldloc.s builder@
IL_0020: ldloc.s builder@
IL_0022: newobj instance void Program/asyncB@10::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder)
IL_0027: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<!!0> [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay<class [InteopTest]InteopTest.BadClass>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<!!0>>)
IL_002c: stloc.s 4
IL_002e: ldloc.s 4
IL_0030: stloc.s 6
IL_0032: ldloc.s 6
IL_0034: ldnull
IL_0035: ldnull
IL_0036: call !!0 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync::RunSynchronously<class [InteopTest]InteopTest.BadClass>(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<!!0>, class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1<int32>, class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1<valuetype [mscorlib]System.Threading.CancellationToken>)
IL_003b: stloc.3
IL_003c: ldstr "%A"
IL_0041: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string[], class [FSharp.Core]Microsoft.FSharp.Core.Unit>, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit, string[]>::.ctor(string)
IL_0046: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string[], class [FSharp.Core]Microsoft.FSharp.Core.Unit>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
IL_004b: stloc.s 7
IL_004d: ldarg.0
IL_004e: stloc.s 8
IL_0050: ldloc.s 7
IL_0052: ldloc.s 8
IL_0054: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string[], class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
IL_0059: pop
IL_005a: ldc.i4.0
IL_005b: ret
} // end of method Program::main