Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"is null" expression efficiency #19803

Closed
madelson opened this issue May 26, 2017 · 2 comments
Closed

"is null" expression efficiency #19803

madelson opened this issue May 26, 2017 · 2 comments
Labels
Area-Compilers Resolution-Duplicate The described behavior is tracked in another issue

Comments

@madelson
Copy link

madelson commented May 26, 2017

#With the new ability to write x is null in C# 7, I anticipate questions on whether this is preferable/equivalent to x == null as we role out C# 7 at my workplace.

Looking at the generated IL code, it seems that x == null generally does a better job since x is null always calls Object.Equals(a, b). This seems especially costly for Nullable<T>, since in that case we get a boxing operation. Interestingly, the null pattern in switch statements does not seem to have this issue.

For the sake of simplicity, it would be nice if x is null had the exact same performance as x == null and
case null:, avoiding a (very minor) performance gotcha.

Version Used: C# 7 (via LinqPad)

Steps to Reproduce:

  1. I wrote the following C# code and compiled in LinqPad with optimization on:
public class Program
{
	public static void Main(string[] args) { }

	public bool IsNullA(int? a)
	{
		switch (a)
		{
			case null: return true;
			default: return false;
		}
	}

	public bool IsNullB(int? a)
	{
		return a is null;
	}

	public bool IsNullC(object s)
	{
		switch (s)
		{
			case null: return true;
			default: return false;
		}
	}

	public bool IsNullD(object s)
	{
		return s is null;
	}
}
  1. This produces the following IL:
Program.IsNullA:
IL_0000:  ldarg.1     
IL_0001:  stloc.0     
IL_0002:  ldloca.s    00 
IL_0004:  call        System.Nullable<System.Int32>.get_HasValue
IL_0009:  brfalse.s   IL_0015
IL_000B:  ldloca.s    00 
IL_000D:  call        System.Nullable<System.Int32>.GetValueOrDefault
IL_0012:  stloc.1     
IL_0013:  br.s        IL_0017
IL_0015:  ldc.i4.1    
IL_0016:  ret         
IL_0017:  ldc.i4.0    
IL_0018:  ret         

Program.IsNullB:
IL_0000:  ldloca.s    00 
IL_0002:  initobj     System.Nullable<System.Int32>
IL_0008:  ldloc.0     
IL_0009:  box         System.Nullable<System.Int32>
IL_000E:  ldarg.1     
IL_000F:  box         System.Nullable<System.Int32>
IL_0014:  call        System.Object.Equals
IL_0019:  ret         

Program.IsNullC:
IL_0000:  ldarg.1     
IL_0001:  stloc.0     
IL_0002:  ldloc.0     
IL_0003:  brtrue.s    IL_0007
IL_0005:  ldc.i4.1    
IL_0006:  ret         
IL_0007:  ldc.i4.0    
IL_0008:  ret         

Program.IsNullD:
IL_0000:  ldnull      
IL_0001:  ldarg.1     
IL_0002:  call        System.Object.Equals
IL_0007:  ret        

Expected Behavior:
IsNullA should use a HasValue call for the null check and IsNullD should use a branch instruction.

Actual Behavior:
IsNullA and IsNullD both use Object.Equals(a, b).

@alrz
Copy link
Member

alrz commented May 26, 2017

#13247

@sharwell
Copy link
Member

@madelson Thank you for the comprehensive report with the descriptive IL blocks. I'm closing this as a duplicate, but know that it's still very much appreciated to now have this extra information available. 👍

@sharwell sharwell added Community The pull request was submitted by a contributor who is not a Microsoft employee. Resolution-Duplicate The described behavior is tracked in another issue and removed Community The pull request was submitted by a contributor who is not a Microsoft employee. labels May 26, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Resolution-Duplicate The described behavior is tracked in another issue
Projects
None yet
Development

No branches or pull requests

4 participants