Test for string fill

Asked

Viewed 1,894 times

9

When reading a post on good programming practices, more related to validating the filling of strings, I came across the following:

Very slow check:

string ret = String.Empty;

if (string.IsNullOrEmpty(ret))

Slow check:

string ret = String.Empty;

if (ret == "")

Performative Verification:

string ret = String.Empty;

if (ret.Length == 0)

When I saw this I was very doubtful, because in the place where I work many people had already told me to use the string.IsNullOrEmpty, but after seeing it I’m questioning myself.

So if anyone can shed some light on why this difference in performance, or even if this information is real, it would be interesting.

And if there really is an ideal way between these 3 ways to verify the completion of a string, the other 2 can be "discarded", or use varies from case to case?

  • I would declare string Ret = String.Empty; only

  • Thanks for the remark, I’ll edit the question. I put it that way only to exemplify the existence of that string, but it can generate doubt because, in this case, always give Nullpointer in examples 2 and 3.

5 answers

9


Stop reading good practices! This only creates programming addictions and illusion that is learning to program better. Study the fundamentals, understand why things work that way, research and see for yourself or ask experts who can be challenged and evaluated by other people, as you are doing now (in the past was more reliable, today the site evaluates answers with problems as if they were good, so it is also not as reliable).

Did you do the tests? The right way? Are you sure you saw which one is slower? In the right situation? Be very careful with tests that do not have control of the environment. I see a lot of error when the person goes to test and then gives results different from reality. And even if it works, in normal use it may be that the result is different from the actual test and correct, because the code does not run alone. I did the test of Rodolfo’s answer and in my machine, under the conditions of my solution, gave different result, including in different executions the result was not very consistent.

It does not happen, but it could have a compiler that analyzes the whole context (and it is not so difficult in certain cases) and could see that most of it is not necessary and delete everything.

Okay, intuitively I believe I’m right, but only a correct test can guarantee.

The first one does something different from the others, so we’re already comparing oranges with bananas. It checks whether the string is null before checking the content. If the semantics is different already complicates the comparison. Then I have to ask: can you ensure that the string is not null?

I already gave one answer on the subject and this method actually does only two things: it checks if it is null and if its size is 0. So we can already conclude that itself . NET prefers to check the size, and makes sense, because it avoids a comparison with indirect of memory and compares numerically a constant. There we can verify that the IsNullOrWhiteSpace() is potentially much less performative and wasteful of resources if not what you need, and semantics is different in certain situations.

If you can guarantee it’s not null, then the third option is better. I can state this without testing by the knowledge I have, but it could have some optimization and not be different. Nothing prevents the compiler or Jitter identify what you want and exchange it for a more performatic code. And that can change from version to version, so if you want accurate information, you need to test the version you’re going to use on the platform you’re going to use. Finally, everything can influence.

If you want to ensure the best performance don’t tell us there will be optimization. But rarely is this really necessary.

And of course, I would avoid the latter whenever possible because it tends not to be optimized. I’d rule out the first one if I made sure it’s not null, which I usually guarantee now and more in C# 8.

If anyone finds a reason to use another way, they need to justify.

As a useful note, in C# 8 it is possible to ensure that the string and other reference types are never null at compile time, so any comparison with null is unnecessary unless the type is declared as null (string?).


Note

This part no longer makes sense because the question has been edited, but it can be useful for other people.

Finally in that specific case posted on the question I would do so (that’s right, it’s not viewing error):

 
 
 

If I declare a variable of type string and not putting any value it will be null for sure, you have nothing else to do, nor need to check if it is null, even more if you have something. And of course, examples 2 and 3 will go wrong. So it’s not good practice, it just makes sense to do nothing. I answered considering that the example was a mistake and the intention is in another context.

  • This, examples 2 and 3 do not have the string started but it was not intended to provoke Nullpointerexception, it was only to exemplify the existence of that string itself. Thank you for the attention and response, cleared my doubt.

  • When it is so, put any text, until empty if it is the case.

6

The code version "performatic" will give error System.NullReferenceException if the variable is null, I believe you will have to change to if (ret == null || ret.Length == 0).

I took the following test:

static void Main(string[] args)
    {
        string ret = null;

        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        for (int i = 0; i <= 100000; i++)
        {
            // if (string.IsNullOrEmpty(ret)) Console.WriteLine($"{i} empty string");
            if (string.IsNullOrEmpty(ret)) Console.WriteLine($"{i} empty string");
        }

        stopWatch.Stop();
        // Get the elapsed time as a TimeSpan value.
        TimeSpan ts = stopWatch.Elapsed;

        // Format and display the TimeSpan value.
        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
            ts.Hours, ts.Minutes, ts.Seconds,
            ts.Milliseconds / 10);
        Console.WriteLine("RunTime " + elapsedTime);

        Console.ReadKey();
    }

Here are the results:

if (Ret == null || Ret. Length == 0)

Runtime 00:00:07.95

if (string.Isnullorempty(Ret))

Runtime 00:00:08.43

I confess that I never cared about this type of optimization, I use string.IsNullOrWhiteSpace() which already checks also white spaces, but of course has to do case by case what is best to use.

  • Thank you for the reply!

5

I believe that the question of the performance of the first two examples is related to the fact that they are validating the content of string, where in the third example, more performant, we’re just validating the size.

string.IsNullOrEmpty(ret)

In this example, the method IsNullOrEmpty represents, internally, ret == null || ret == string.Empty, where we are basically making two comparisons to validate the result.

Bearing in mind that ret == string.Empty represents string.Equals(ret, String.Empty) where it basically compares whether the 1st object is equal to the 2nd, given whether one of them is null and even comparing character to character in a loop, understand why it is the option slower (because we still have the comparison with the null).

ret == ""

In this case, as explained above, ret == "" represents string.Equals(ret, "") that "drags" some complexity in the comparison and is therefore slow but less than the previous one because it does not have the "extra" validation of the ret == null.

ret.Length == 0

This is the fastest option if we want to validate whether a string is empty (no characters) or not, but is not the most secure, since the string have value null will give rise to an exception of System.NullReferenceException.

If we are sure string will not be never null, then it will be a good option.

Completion

Each case is a case, and it all depends on the context.

The safest way will surely be to use IsNullOrEmpty when we do not know if the content will be null or not, and evil for badly better better to prevent, but... we need to evaluate which of the options, taking into account what we have, will be more viable for use.

  • Thank you for the reply and attention!

4

One way to understand performance is to test:

class Program
{
    static void Main(string[] args)
    {
        string test = StrintToTest();

        while(true)
        {
            Console.WriteLine("Press any key. ESC to exit");
            var key = Console.ReadKey();
            if (key.Key == ConsoleKey.Escape) break;

            Console.WriteLine(ElapsedTime("==", () => (test == "")));
            Console.WriteLine(ElapsedTime("Length", () => (test.Length == 0)));
            Console.WriteLine(ElapsedTime("IsNullOrEmpty", () => (string.IsNullOrEmpty(test))));
            Console.WriteLine(ElapsedTime("null or Len", () => (test == null || test.Length == 0)));
            Console.WriteLine();
        }

    }

    public static string ElapsedTime(string what, Func<bool> method)
    {
        var time = new Stopwatch();

        time.Start();
        long i = 0;
        long total = 1000000;
        while (i++ < total)
            method.Invoke();
        time.Stop();

        return string.Format("{0,15} - Elapsed {1,9:f5} ms", what, time.Elapsed.TotalMilliseconds);
    }

    public static string StrintToTest()
    {
        return "The quick brown fox jumps over the lazy dog";
    }
}

In my machine the result was:

             == - Elapsed   7,48910 ms
         Length - Elapsed   6,62160 ms
  IsNullOrEmpty - Elapsed   5,81710 ms
    null or Len - Elapsed   7,22380 ms

It seems fair that checking the size is more efficient than comparing two strings.

Call the method IsNullOrEmpty class string took less time than the others in this test. While investigating the Framework . Net source code for the method IsNullOrEmpty we have the following:

public static bool IsNullOrEmpty(String value) {
    return (value == null || value.Length == 0);
}

So there seems to be some compiler optimization when you use the class method string. Will be?

The question of performance, you need to do the tests to choose the one that is best, but understand that performance is very relative. Code execution should consider many factors of the execution environment that you do not control and most applications do not need performance optimization at this level of instructions.

What is left then are issues that have more to do with the organization of the program/code. "Clean code", "readable code", "organized code" or code that follows some kind of pattern or style. This is what we end up calling code written with good practices.

Entering into personal opinion, I remember that in the past, whenever we joined a development team we looked for "the guide to good practices". In fact, this guide was more targeted so that the code would be in a certain standardized way because people have a lot of different experiences in various places and each ended up writing the code differently. It wasn’t a question of the code being good or bad, fast or slow, it was a question of the code being understood more quickly by anyone on the team. If your team can have this privilege, I don’t see how it can get in the way or be bad, then before you follow good practice, you may need to understand what good practice means in that community/team you’re in.

  • Your test tests the infrastructure of delegate than anything else.

  • "There are several ways to prepare Neston. Invent your."

  • What does that have to do with anything?

  • You don’t know the propaganda?

  • What does that have to do with anything?

  • It has to do with the fact that the code is comparing times and you thought it was exaggerated that I use a feature that has nothing to do with the purpose of the test. But I think it’s just another way of doing it and it’s valid. The phrase encourages people to do the same thing in different ways.

  • Then put to make a factorial of a large number together, since what you are testing does not matter. To do wrong is not valid, now it is worse because it is saying that to do something without criterion, without knowledge, that does not produce the expected result is valid, and it is not. I think you do not understand what to invent, it is not this: https://www.wonderslist.com/wp-content/uploads/2017/03/Shoe-umbrellas-600x400.jpg. Inventing something that produces a bad result is inventing fashion, not inventing useful.

  • What does a factorial have to do with the question of string checking?

  • Now you’re beginning to understand, what it has to do with testing the performance of a delegate with testing a simple comparison? You are arguing that this is valid.

  • I use the same black box to test four different things. Why do you care what’s in the black box if the time lost inside the black box is the same for any input it receives?

  • It matters because it takes time and it’s not little and you’re testing time, so distort the results, you’re testing the time of delegate, if it goes for other things together, then put the factorial too, according to what you’re saying now makes no difference.

  • Yes, it takes time, but the question here is comparison and not measuring the absolute time of an instruction.

  • If the delegate takes 10 of time (whatever this 10 is) and the comparison takes 1 in a case and 2 in the second, you will have result 11 and 12 and seems almost equal, but if you take the time of the delegate is twice as long as you really want to compare.

  • It’s still valid because I’m not wondering if it’s double or triple, only if it’s bigger or smaller. To mitigate these differences between calls is that the code runs 1,000,000 times.

  • I give up, want to do wrong do.

  • What you’re saying is that a very large measure interferes in a very small measure and I understand that part of the statistic, but that’s not the case here because I’m not doing quantitative study, but comparative study. I also put in response that performance at the level of instruction is quite relative and underlined the word in this test to be in no doubt as to the answer. I think this is enough.

Show 11 more comments

2

If you want to evaluate whether a string has value, C# has a function of the primitive type itself string.

Ex:

string.IsNullOrEmpty("abc");

If you want to evaluate whether a string has value, abstracting blank spaces, C# has a function of the primitive type itself string.

Ex:

string.IsNullOrWhiteSpace("abc");

Regardless of language, you can evaluate:

var mstr= ''; if(mstr == null) return true;

And the result will be false.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.