2

What would be your reason not to write

list.Count.Equals(0) 

when you probably write

list.Count == 0

Is there a technical/semantical reason?

Elisabeth
  • 20,496
  • 52
  • 200
  • 321
  • 3
    The second case is more readable, isn't it? – abatishchev Feb 15 '13 at 08:01
  • 2
    It depends on what `list` actually is (`Equals` may have different override than `operator==`, but it's just stupid). In general, `list.Any()` is the preferred way to check for empty list. – Artem Koshelev Feb 15 '13 at 08:02
  • 2
    @ArtemKoshelev: It rather depends on what `list.Count` actually is. – O. R. Mapper Feb 15 '13 at 08:13
  • As the answer by [daryal](http://stackoverflow.com/users/410443/daryal) shows, this question can very well be supported by facts and specific expertise. I therefore vote for reopening it. – O. R. Mapper Feb 15 '13 at 12:59
  • @ArtemKoshelev - I would agree that, for performance, `!Any()` is clearly preferred if you only have an `IEnumerable`, and is likely preferred if you only have an `ICollection`, however the variable `list` suggests they have at least `IList`, in which case `Count` is known to be cheap, so it becomes a matter of taste. "stupid" is an extreme judgment. OTOH, your comment did get me to consider why I still use "Count == 0"; its really just a habit from years of old-school programming; no longer justified. – ToolmakerSteve Nov 27 '18 at 09:01

4 Answers4

5

I think there is no difference between two statements for this specific case. Since you are checking the equality of int values; == operator and Equals do exactly the same operation.

But for some other cases, for example for the following case, they may return different values;

Double.NaN == Double.NaN // is false
Double.NaN.Equals(Double.NaN) // is true

Generally, for value types you may go with ==; but if it is a reference type, better to go with Equals.

For int the disassembly of a sample is displayed below; the generated assembly codes differ, so the performace is expected to differ;

            int a = 10;
00000080  mov         dword ptr [ebp-40h],0Ah 
                int b = 9;
00000087  mov         dword ptr [ebp-44h],9 

                bool x = a == b;
0000008e  mov         eax,dword ptr [ebp-40h] 
00000091  cmp         eax,dword ptr [ebp-44h] 
00000094  sete        al 
00000097  movzx       eax,al 
0000009a  mov         dword ptr [ebp-48h],eax 
                bool y = a.Equals(b);
0000009d  lea         ecx,[ebp-40h] 
000000a0  mov         edx,dword ptr [ebp-44h] 
000000a3  call        6B8803C0 
000000a8  mov         dword ptr [ebp-60h],eax 
000000ab  movzx       eax,byte ptr [ebp-60h] 
000000af  mov         dword ptr [ebp-4Ch],eax 
daryal
  • 14,643
  • 4
  • 38
  • 54
3

The two main reasons are

  1. list.Count == 0 is easier to read (most important)

  2. list.Count.Equals(0) is slower

SecurityMatt
  • 6,593
  • 1
  • 22
  • 28
  • 5
    Why do you think it's slower? I think operator overload for int uses Equals override. – abatishchev Feb 15 '13 at 08:02
  • For me the reason is equals is for reference types not value types like integer. – Elisabeth Feb 15 '13 at 08:04
  • 1
    Equals on int does not get boxed. – Alex Feb 15 '13 at 08:07
  • 2
    @SecurityMatt Equals does and does not expect an object. There are two method overrides; expecting an object and expecting an integer. If the method expecting an integer is employed, there will be no conversion. – daryal Feb 15 '13 at 08:13
  • 4
    @abatishchev: It doesn't. In C# it compiles to the ADD opcode, which then jits to a single ADD operation on the processor. No method is invoked when you do Int == Int, but a method IS invoked if you call int.Equals(0). . – SecurityMatt 11 mins ago – SecurityMatt Feb 15 '13 at 08:16
  • @SecurityMatt is actually right, if the outcome of `list.Count == 0` is not stored, this is executes about 3 times less instructions in size & 2.5 times less in time compared to the 'Equals(0)' *regardless* if the output of the the equals check is stored!!! If the output is stored from `var listIsEmpty.Count==0` it's still about 2 times faster = SecurityMath is right [all code examined was optimized| timings all according to the IA32], I actually downvoted his answer sorry - upvoated another! you are good will follow you, if you edit this asnwer I will upvote, sorry again – user1416420 Feb 15 '13 at 09:15
  • Sorry Matt, have a nice day – user1416420 Feb 15 '13 at 09:18
  • @user1416420: no worries. You too. – SecurityMatt Feb 15 '13 at 09:19
2

list.Count == 0 has better readability and its shorter imo. If performance is negligible, always go with whats more readable and displays the intention the clearest way.

As for technical reasons: If you compare the two generated IL sequences.

  IL_0029:  callvirt   instance int32 class [mscorlib]System.Collections.Generic.List`1<string>::get_Count()
  IL_002e:  stloc.s    CS$0$0001
  IL_0030:  ldloca.s   CS$0$0001
  IL_0032:  ldc.i4.0
  IL_0033:  call       instance bool [mscorlib]System.Int32::Equals(int32) 
  // Equals(obj int) internally uses the method this == obj;

vs.

  IL_007f:  callvirt   instance int32 class [mscorlib]System.Collections.Generic.List`1<string>::get_Count()
  IL_0084:  ldc.i4.0
  IL_0085:  ceq

one could argue that the == operator is faster because it uses less instructions, noone really knows how it gets optimized though.

Running a quick benchmark with JIT warmup and different sequences on which is called first, you'll notice that (At least on my machine) on an iteration over 100000000 elements, == is about 25 ms faster.

Alex
  • 7,901
  • 1
  • 41
  • 56
  • "== is about 25 ms faster" - not useful unless you say how much the total was. If it was out of 100 ms, that would be quite significant. if it was out of 10000 ms, not so much :) – ToolmakerSteve Nov 27 '18 at 09:11
0

I think more readable would be

if (list.IsEmpty()) { ... } 

I'm not a C# expert, so you better check here Recommended way to check if a sequence is empty how to make it work.

Community
  • 1
  • 1
denis.solonenko
  • 11,645
  • 2
  • 28
  • 23
  • But `IsEmpty` is not a built-in method. In the answer you are referring to, the person **creates** that as an extension method. Obviously people can create whatever extension methods they want, but that would still beg the question of what is best to put inside that extension method... which is what needs to be answered here, in this question. – ToolmakerSteve Nov 27 '18 at 09:15