user28661
user28661

Reputation: 61

c# performance: type comparison vs. string comparison

Which is faster? This:

bool isEqual = (MyObject1 is MyObject2)

Or this:

bool isEqual = ("blah" == "blah1")

It would be helpful to figure out which one is faster. Obviously, if you apply .ToUpper() to each side of the string comparison like programmers often do, that would require reallocating memory which affects performance. But how about if .ToUpper() is out of the equation like in the above sample?

Upvotes: 5

Views: 11119

Answers (7)

MPavlak
MPavlak

Reputation: 2221

I don't feel like any of these answers address the actual question. Let's say the string in this example is the type's name and we're trying to see if it's faster to compare a type name or the type to determine what it is.

I put this together and to my surprise, it's about 10% faster to check the type name string than the type in every test I ran. I intentionally put the simplest strings and classes into play to see if it was possible to be faster, and turns out it is possible. Not sure about more complicated strings and type comparisons from heavily inherited classes. This is of course a micro-op and may possibly change at some point in the evolution of the language I suppose.

In my case, I was considering a value converter that switches based on this name, but it could also switch over the type since each type specifies a unique type name. The value converter would figure out the font awesome icon to show based on the type of item presented.

using System;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApp1
{
    public sealed class A
    {
        public const string TypeName = "A";
    }

    public sealed class B
    {
        public const string TypeName = "B";
    }

    public sealed class C
    {
        public const string TypeName = "C";
    }

    class Program
    {
        static void Main(string[] args)
        {
            var testlist = Enumerable.Repeat(0, 100).SelectMany(x => new object[] { new A(), new B(), new C() }).ToList();

            int count = 0;

            void checkTypeName()
            {
                foreach (var item in testlist)
                {
                    switch (item)
                    {
                        case A.TypeName:
                            count++;
                            break;
                        case B.TypeName:
                            count++;
                            break;
                        case C.TypeName:
                            count++;
                            break;
                        default:
                            break;
                    }
                }
            }

            void checkType()
            {
                foreach (var item in testlist)
                {
                    switch (item)
                    {
                        case A _:
                            count++;
                            break;
                        case B _:
                            count++;
                            break;
                        case C _:
                            count++;
                            break;
                        default:
                            break;
                    }
                }
            }

            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i < 100000; i++)
            {
                checkTypeName();
            }
            sw.Stop();
            Console.WriteLine(sw.Elapsed);
            sw.Restart();
            for (int i = 0; i < 100000; i++)
            {
                checkType();
            }
            sw.Stop();
            Console.WriteLine(sw.Elapsed);
        }
    }
}

Upvotes: -1

labilbe
labilbe

Reputation: 3594

The first one is used to compare types not values. If you want to compare strings with a non-sensitive case you can use:

string toto = "toto";
string tata = "tata";

bool isEqual = string.Compare(toto, tata, StringComparison.InvariantCultureIgnoreCase) == 0;    

Console.WriteLine(isEqual);     

Upvotes: 4

Benjamin Podszun
Benjamin Podszun

Reputation: 9837

If I understand the question and you really want to compare reference equality with the plain old "compare the contents": Build a testcase and call object.ReferenceEquals compared against a == b.

Note: You have to understand what the difference is and that you probably cannot use a reference comparison in most scenarios. If you are sure that this is what you want it might be a tiny bit faster. You have to try it yourself and evaluate if this is worth the trouble at all..

Upvotes: 0

Soviut
Soviut

Reputation: 91655

I'd assume that comparing the objects in your first example is going to be about as fast as it gets since its simply checking if both objects point to the same address in memory.

As it has been mentioned several times already, it is possible to compare addresses on strings as well, but this won't necessarily work if the two strings are allocated from different sources.

Lastly, its usually good form to try and compare objects based on type whenever possible. Its typically the most concrete method of identification. If your objects need to be represented by something other than their address in memory, its possible to use other attributes as identifiers.

Upvotes: 0

Michael Burr
Michael Burr

Reputation: 340446

I'm a little confused here.

As other answers have noted, you're comparing apples and oranges. ::rimshot::

If you want to determine if an object is of a certain type use the is operator.

If you want to compare strings use the == operator (or other appropriate comparison method if you need something fancy like case-insensitive comparisons).

How fast one operation is compared to the other (no pun intended) doesn't seem to really matter.


After closer reading, I think that you want to compare the speed of string comparisions with the speed of reference comparisons (the type of comparison used in the System.Object base type).

If that's the case, then the answer is that reference comparisons will never be slower than any other string comparison. Reference comparison in .NET is pretty much analogous to comparing pointers in C - about as fast as you can get.

However, how would you feel if a string variable s had the value "I'm a string", but the following comparison failed:

if (((object) s) == ((object) "I'm a string")) { ... }

If you simply compared references, that might happen depending on how the value of s was created. If it ended up not being interned, it would not have the same reference as the literal string, so the comparison would fail. So you might have a faster comparison that didn't always work. That seems to be a bad optimization.

Upvotes: 11

JoshL
JoshL

Reputation: 10998

Comparing strings with a "==" operator compares the contents of the string vs. the string object reference. Comparing objects will call the "Equals" method of the object to determine whether they are equal or not. The default implementation of Equals is to do a reference comparison, returning True if both object references are the same physical object. This will likely be faster than the string comparison, but is dependent on the type of object being compared.

Upvotes: 0

Frode Lillerud
Frode Lillerud

Reputation: 7394

According to the book Maximizing .NET Performance the call

bool isEqual = String.Equals("test", "test");

is identical in performance to

bool isEqual = ("test" == "test");

The call

bool isEqual = "test".Equals("test");

is theoretically slower than the call to the static String.Equals method, but I think you'll need to compare several million strings in order to actually detect a speed difference.

My tip to you is this; don't worry about which string comparison method is slower or faster. In a normal application you'll never ever notice the difference. You should use the way which you think is most readable.

Upvotes: 5

Related Questions