C# 'Is' Operator Performance

C# 'is' operator performance

Using is can hurt performance if, once you check the type, you cast to that type. is actually casts the object to the type you are checking so any subsequent casting is redundant.

If you are going to cast anyway, here is a better approach:

ISpecialType t = obj as ISpecialType;

if (t != null)
{
// use t here
}

?: Operator Vs. If Statement Performance

IMHO, optimize for readability and understanding - any run-time performance gains will likely be minimal compared to the time it takes you in the real-world when you come back to this code in a couple months and try to understand what the heck you were doing in the first place.

Performance of == vs Equals in generic C# class

The reason being that == defaults to reference equality and that makes no sense for value types, the answer will always be false. Because there is no language mechanism to constrain generic types based upon static methods, the compiler simply disallows this as it can't verify that T really has an overloaded == operator.

On the other hand if you constraint T to class it will compile just fine because reference equality does make sense for reference types.

The solution is of course IEquatable<T>; in any sanely implemented struct IEquatable<T>.Equals(T t) will give you value equality semantics and == should behave consistently.

And answering your question, no there is not. If you really need the speed of int == int you will need to implement a non generic specialized class.

C# is operator - is that reflection?

Referencing ECMA-335, the is operator generates the isinst object model IL instruction (Partition III §4.6), which is part of the base instruction set as opposed to being part of the Reflection library (Partition IV §5.5).

Edit: The is operator is extremely efficient compared to the reflection library. You could perform basically the same test much more slowly via reflection:

typeof(T).IsAssignableFrom(obj.GetType())

Edit 2: You are not correct about the efficiency of the castclass and isinst instructions (which you've now edited out of the post). They are highly optimized in any practical VM implementation. The only real performance issue involved is the potential for castclass to throw an exception, which you avoid by using the C# as operator and a test for null (for reference types) or the is operator followed by a cast (for value types).

Is there any performance difference between ++i and i++ in C#?

There is no difference in the generated intermediate code for ++i and i++ in this case. Given this program:

class Program
{
const int counter = 1024 * 1024;
static void Main(string[] args)
{
for (int i = 0; i < counter; ++i)
{
Console.WriteLine(i);
}

for (int i = 0; i < counter; i++)
{
Console.WriteLine(i);
}
}
}

The generated IL code is the same for both loops:

  IL_0000:  ldc.i4.0
IL_0001: stloc.0
// Start of first loop
IL_0002: ldc.i4.0
IL_0003: stloc.0
IL_0004: br.s IL_0010
IL_0006: ldloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
IL_000c: ldloc.0
IL_000d: ldc.i4.1
IL_000e: add
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: ldc.i4 0x100000
IL_0016: blt.s IL_0006
// Start of second loop
IL_0018: ldc.i4.0
IL_0019: stloc.0
IL_001a: br.s IL_0026
IL_001c: ldloc.0
IL_001d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0022: ldloc.0
IL_0023: ldc.i4.1
IL_0024: add
IL_0025: stloc.0
IL_0026: ldloc.0
IL_0027: ldc.i4 0x100000
IL_002c: blt.s IL_001c
IL_002e: ret

That said, it's possible (although highly unlikely) that the JIT compiler can do some optimizations in certain contexts that will favor one version over the other. If there is such an optimization, though, it would likely only affect the final (or perhaps the first) iteration of a loop.

In short, there will be no difference in the runtime of simple pre-increment or post-increment of the control variable in the looping construct that you've described.

Performance of If/Else If versus OR-operator in C#

It depends. You have to thoroughly benchmark your specific use case. But, without knowing the details, I would say: neither

Start by checking the generated IL code and/or JIT Asm at sharplap.io. It should give you some hints. Looks like Case1 yields smaller code size. That might affect inlining during optimization.

You could also try to have four separate for-loops to possibly maximize performance. It all depends on the CPU cache. This concept has been discussed before. I suggest you read these answers/discussions:

  • Two loop bodies or one (result identical)
  • Performance of breaking apart one loop into two loops

how to decide on a bool operators usage, performance issues vs readability

This question is somewhat subjective...

"i tend to assume that ready made operators like Equals would go
through more processing actions."

" when and why would you choose ! over Equals , And both over
'traditional' == "

the Equals method as part of an instance of an object is used to check for equality of that instance against another, whilst the == and != operators are static and are therefore unbound from any object instance. Instead these are like a special static method that accepts two arguments (of usually the same type) and compares them.

Consider the following example:

public class CustomObject
{
int someValue, anotherValue;

public bool Equals(CustomObject obj)
{
return (this.someValue == obj.someValue && this.anotherValue == obj.anotherValue);
}

public static bool operator ==(CustomObject a, CustomObject b)
{
return a.Equals(b);
}

public static bool operator !=(CustomObject a, CustomObject b)
{
return !(a == b);
}
}

In this example, the Equals method is used to produce a result of the comparison of values in the CustomObject against another instance of the same type. The == operator for CustomObject simply calls Equals on one of the parameter objects and performs an equality check against the other. The != operator simply negates the == and produces the opposite result. Therefore, == and != do not have much performance overhead over Equals, because they both call that method anyway.

Best practices:

if a condition is boolean by nature there is no need to use Equals, != or ==, but you should use ! to negate a boolean condition.

For example:

if(IsPostBack) // this is good

if(IsPostBack == true) // this is unnecessary

if(!IsPostBack) // this is good

if(IsPostBack == false) // this is unnecessary

If a condition is not boolean by nature, or you are comparing two boolean values, or you are comparing an enumeration, or other value type then use of != or == is acceptable.

For example:

if(a == b) // this is good

if(a != b) // this is good

If a condition is not boolean by nature and the objects you are comparing do not have the == or != operators implemented, then using Equals is acceptable. Note, using != and == are prohibited with generics since it is not known at compile time that != or == are implemented on the objects represented by the generic objects type parameters.

For example:

if(a.Equals(b)) //this is good

if(!a.Equals(b)) // this is good

if(a.Equals(b) == true) // this is unnecessary

Unexpected performance results when comparing dictionary lookup vs multiple is operators in .NET 4.7

I'm by no means an IL performance guru, but if you decompile and especially look at the IL, this make sense.

The is operator is only 4 opcodes (ldarg, isinst, ldnull, cgt), and each switch part only 7 in total with the goto added in. The action part of Switch to call Empty() is then another 6, giving 17*7+6 = 125 max.

By contrast Dictionary.TryGetValue may only be one method call, but inside this it is doing a lot of work hashing, looping and comparing values:

http://referencesource.microsoft.com/#mscorlib/system/collections/generic/dictionary.cs,2e5bc6d8c0f21e67

public bool TryGetValue(TKey key, out TValue value) {
int i = FindEntry(key);
if (i >= 0) {
value = entries[i].value;
return true;
}
value = default(TValue);
return false;
}

http://referencesource.microsoft.com/#mscorlib/system/collections/generic/dictionary.cs,bcd13bb775d408f1

private int FindEntry(TKey key) {
if( key == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}

if (buckets != null) {
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) {
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
}
}
return -1;
}

The for loop inside FindEntry alone is 31 opcodes for each loop, giving a max of 527 opcodes just for this part.

This is very basic analysis but it is easy to see that the switch should be more performant. As is often the case tho, you need to consider performance versus readability and maintainability. If using a Dictionary lookup gives you nicer code, it is rare that the performance loss (15ns) will outweigh that benefit.



Related Topics



Leave a reply



Submit