Sample code for blog post Null-checking considerations in F# - it's harder than you think
Last active
August 29, 2015 14:21
-
-
Save latkin/20750903fc625b49e27e to your computer and use it in GitHub Desktop.
Blog: Null-checking considerations in F#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let nullCheck01 x = (x = null) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static bool nullCheck01<a>(a x) where a : class | |
{ | |
return LanguagePrimitives.HashCompare.GenericEqualityIntrinsic<a>(x, default(a)); | |
} | |
// --- F# core library --- | |
public static bool GenericEqualityIntrinsic<T>(T x, T y) | |
{ | |
return LanguagePrimitives.HashCompare.GenericEqualityObj(false, LanguagePrimitives.HashCompare.fsEqualityComparerNoHashingPER, ); | |
} | |
internal static bool GenericEqualityObj(bool er, IEqualityComparer iec, object xobj, object yobj) | |
{ | |
if(xobj == null) return yobj == null; | |
if(yobj != null) { ... core logic, fairly big, prevents JIT inlining ... } | |
return false; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Cat = { Name : string; Lives : int } | |
let nullCheck02 (x : Cat) = (x = Unchecked.defaultof<_>) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static bool nullCheck02(Cat x) | |
{ | |
Cat obj = null; | |
// nullref | |
return x.Equals(obj, LanguagePrimitives.GenericEqualityComparer); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Cat = { Name : string; Lives : int } | |
let ohNoes x = | |
try | |
if x.Lives > 1 then Some({ x with Lives = x.Lives - 1}) | |
else None | |
with | |
| :? NullReferenceException -> None | |
ohNoes (Unchecked.defaultof<_>) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static FSharpOption<Cat> ohNoes(Cat x) | |
{ | |
if (x.Lives@ > 1) | |
{ | |
return FSharpOption<Cat>.Some(new Cat(x.Name@, x.Lives@ - 1)); | |
} | |
return FSharpOption<Cat>.None; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Cat = { Name : string; Lives : int } | |
let nullCheck03 x = match x with null -> true | _ -> false | |
let nullCheck04 (x : Cat) = match box x with null -> true | _ -> false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; if x is null, go to 00D50503 | |
00D504FB test ecx,ecx | |
00D504FD je 00D50503 | |
; set return value to 0 (false) | |
00D504FF xor eax,eax | |
; return | |
; set return value to 1 (true) | |
00D50503 mov eax,1 | |
; return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// nullCheck04 is identical except generic "a" becomes concrete "Cat" | |
.method public static bool nullCheck03<class a> (!!a x) cil managed | |
{ | |
.maxstack 8 | |
IL_0000: ldarg.0 | |
IL_0001: box !!a | |
IL_0006: brfalse.s IL_000a | |
IL_0008: ldc.i4.0 | |
IL_0009: ret | |
IL_000a: ldc.i4.1 | |
IL_000b: ret | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let nullCheck05 (x : 't when 't : null) = System.Object.ReferenceEquals(x, null) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; if x is null, set the lowest byte of return value to 1 | |
; otherwise set it to 0 | |
012404A3 test ecx,ecx | |
012404A5 sete al | |
; fill out the rest of return value with 0s | |
012404A8 movzx eax,al | |
; return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.method public static bool nullCheck05<class t> (!!t x) cil managed | |
{ | |
.maxstack 8 | |
IL_0000: nop | |
IL_0001: ldarg.0 | |
IL_0002: box !!t | |
IL_0007: ldnull | |
IL_0008: call bool [mscorlib]System.Object::ReferenceEquals(object, object) | |
IL_000d: ret | |
} | |
// --- BCL --- | |
.method public hidebysig static bool ReferenceEquals (object objA, object objB) cil managed | |
{ | |
.maxstack 8 | |
IL_0000: ldarg.0 | |
IL_0001: ldarg.1 | |
IL_0002: ceq | |
IL_0004: ret | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment