I have this C# DLL:
namespace TestCSProject
{
public class TestClass
{
public static TestClass Instance = null;
public int Add(int a, int b)
{
if (this == null)
Console.WriteLine("this is null");
return a + b;
}
}
}
And this F# app which references the DLL:
open TestCSProject
printfn "%d" (TestClass.Instance.Add(10,20))
No-one initiates the Instance static variable. Guess what the output of the F# app is?
this is null 30 Press any key to continue . . .
After a few tests I found out that unless I use this (e.g. to access instance field), I won’t get NullReferenceExpcetion.
Is that an intended behaviour or a gap in F# compilation / CLR?
I suspect you’ll find it’s using
callinstead ofcallvirtif you look at the IL. The C# compiler always usescallvirt, even for non-virtual methods, because it forces a nullity check.Is this a bug? Well, not necessarily. It depends on what the F# language specification states about methods calls on null references. It’s perfectly possible that it states that the method will be called (non-virtually) with a null “this” reference, which is exactly what has happened.
C# happens to specify that this sort of dereferencing will throw a
NullReferenceException, but that’s a language choice.I suspect the F# approach may be a little faster, due to the lack of nullity checking involved… and don’t forget that null references are less “expected” in F# than in C#… that may explain the different approach taken here. Or it could just be an oversight, of course.
EDIT: I’m not an expert at reading the F# specification, but section 6.9.6 at least suggests to me that it’s a bug:
Whether this counts as an elaborated application or not is a little beyond me, I’m afraid… but I hope this has been at least somewhat helpful.