With an equal comparison of literal values, does the order of the operands make sense?

I'm used to writing code like (just an example)

Request.QueryString["xxxx"] != null 

Someone recently said that

 null != Request.QueryString["xxxx"] 

gives better performance.

I am curious to know if this really makes any difference or not, and if so, how?

Note ~ This is just an example. Generally speaking

Whether

 Constant [Operator] Actual Value (eg 1 == Convert.ToInt32(textbox1.text)) 

better than

 Actual Value [Operator] Constant (eg Convert.ToInt32(textbox1.text) == 1) 

thanks

+6
source share
4 answers

No, that’s not the case at all. Comparison operators must evaluate both sides, so there is no benefit in setting constants on the left. But having them on the left side (Yoda style) reduces coding errors in languages ​​where you are allowed to use the assignment operator inside the conditional expression, and you did not accidentally specify the comparison operator == as a single = :

 // What you intended to write if (a == 6) ... // What you wrote instead if (a = 6) ... // --> always true as the value of a is changed to 6 // What if Yoda style is used if (6 = a) ... // --> compile time error 
+3
source

what

This is the coding style used for languages ​​with many implicit type conversions (friendly by the name of Yoda from the Star Wars character due to his OSV word order). Sometimes it is even forcibly applied and required along the project guidelines to prevent some errors from typos. Different languages ​​have different variations and extensions of this style, but I will limit this answer to C and C #.

Why yes

For example, in C you can write:

 int a = CalculateValue(); if (a = CalculateAnotherValue()) { /* Do something */ } 

This code will assign a value returned from CalculateValue() , after which it will overwrite the value with the result CalculateAnotherValue() , and if it is not zero, it will execute the code. This is probably not what is intended, but the assignment in the if is a mistake. In your example, using NULL , you could have:

 if (pBuffer = NULL) 

Again, perhaps this is not what you want (and this is a pretty common mistake), you will assign NULL to the pointer, and the condition will always be false. If you write:

 if (NULL = pBuffer) 

It will not compile (because you cannot assign a value to a literal) and you will get a compile-time error.

This kind of compile-time check is not the only reason to use this coding style, see this C # code (very general):

 if (text != null && text.Equals("something", StringComparison.InvariantCulture) DoSomething(); 

It can be reduced to:

 if ("something".Equals(text, StringComparison.InvariantCulture)) DoSomething(); 

Why not

In C #, this usually doesn't matter. This is a practice inherited from C / C ++. Since C # expressions are not automatically converted to bool , the following code will not compile:

 if (Request.QueryString["PartnerID"] = null) 

Then this practice is useless in C # (@IlianPinzon pointed out an exception in the comments), it did not use anything about performance to avoid such errors.

In the last example, in the "Why Yes" section, the readability problem, write "something".Equals(text) is to say "if the guy is happy" and not "if the guy is happy."

Performance

Starting with these functions:

 static bool TestRight(object value) { return value == null; } static bool TestLeft(object value) { return null == value; } 

They produce the following IL:

 .maxstack 2 .locals init ([0] bool CS$1$0000) L_0000: nop L_0001: ldnull L_0002: ldarg.0 L_0003: ceq L_0005: stloc.0 L_0006: br.s L_0008 L_0008: ldloc.0 L_0009: ret 

The only difference is in lines L_0001 and L_0002, they are simply replaced, but the order of its operands does not change the behavior of ceq . Even if you override the Equals() method, the JIT compiler will generate the same assembly code for both expressions (because the comparison will always be done using Equals() , NULL is unsigned).

Things can be more complicated if the comparison is related to custom equality matching, in this case there is no rule, and this will depend on the effective implementation of op_Equals . For example, this implementation == :

 public static bool operator==(MyType lhs, MyType rhs) { if (Object.ReferenceEquals(lhs, rhs)) return true; if (Object.ReferenceEquals(lhs, null)) return false; return lhs.Equals(rhs); } 

In this case, if the first operand is NULL , execution will be slightly faster (because MyType.Equals() will not even be called), but this performance increase is very small: you save one comparison, several jumps and a virtual function call. In addition, you can rewrite a function faster in the opposite case (in case you really think about it).

Here's a little test in which MyType.Equals(object) just returns true for any non- NULL parameter. The test will Int32.MaxValue times:

  Operation Total time (ms)
 lhs == null 10521
 null == lhs 2346

It seems that the “optimized” version, which avoids the unnecessary call to Equals() , is five times faster, but note that the number of loops is very large and the actual implementation of Equals() empty, a true implementation will reduce the relative overhead of calling the function (and, maybe you will have something else than this micro-optimization ). For system classes, you cannot rely on this information, for example, String.Equals() will always be called by operators (it does not matter for order), but you cannot assume that one code path is faster, and this fact will not change in future versions (or for different CPU architectures).

+15
source

This is a matter of style. Someone prefers to write

 if (N == var) ... 

simply because if you missed one = (the usual case for beginners)

 if (N = var) 

where N is a constant, the compiler will throw an error.

When

 if (var = N) 

it can give you a warning and cannot (depends on the compiler and flags). Therefore, it is sometimes difficult to find where the problem is.

The performance of both options is the same. Choose your style and follow it.

+2
source

Constant [Operator] Actual Value is known as the Yoda condition because it is like "if it is blue, it is sky" or "if it is high, it is man."

Using this style of condition was popular in C / C ++, where you could assign a value to a variable by typing = instead of == . In C #, it makes no sense to use Yoda conditions.

Also, I have doubts that it has the best performance. Even if he has a performance advantage, it will be very small. A match is less than a lack of readability.

0
source

Source: https://habr.com/ru/post/916977/


All Articles