Stop reading good practices! This only creates vices of programming and illusion that is learning to program better. Study the basics, understand why things work that way, research and see for yourself, or ask experts who can be challenged and evaluated by others, as you are now doing (in the past, it was more reliable, as if they were good, so it's not that reliable either.)
Have you done the tests? The right way? Are you sure you saw which one is slower? In the right situation? Be very careful with tests that have no environmental control. I see a lot of error when the person is going to test and then it gives different results from reality. And even if right, in normal use it may be that the result is different from the actual and correct test because the code does not run in isolation. I did the test of the response of Rodolfo 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 looks at the whole context (and it's not that difficult in certain cases) and you could see that most of it is not needed and eliminate everything.
Okay, intuitively I even think I'm right, but only a correct test can guarantee.
The first one does something different from the others, so we are already comparing oranges with bananas. It checks to see if the string is null before checking the contents. If the semantics is different already complicates the comparison. Then I have to ask: can you guarantee that the string is not null?
I've already given a answer about the subject and this method actually does only two things: it checks to see if it is null and if its size is 0. Then we can conclude that .NET itself prefers to check the size, and makes sense, because it avoids a comparison with memory indirection and numerically compares a constant. There we can see that
IsNullOrWhiteSpace() is potentially much less performative and wasted resources if not what it needs, and the semantics are different in certain situations.
If you can guarantee that it is not null then the third option is better. I can state this without testing for 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 switch to a more performative code. And this 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. Anyway, everything can influence.
If you want to ensure the best performance do not count that there will be optimization. But rarely is this really necessary.
Of course, I would avoid the second whenever possible because it tends not to be optimized. I would discard the first if I ensure that it is not null, which I usually guarantee already and even more in C # 8.
If someone finds a reason to use another form, they need to justify it.
As a useful note in C # 8 it will be possible to ensure that
string and other types by reference are never null at compile time, then any null comparison is unnecessary, unless the type is declared nullable (
This part does not make sense anymore because the question was edited, but it may be useful for other people.
Finally in this specific case posted in the question I would do so:
If I declare a variable of type
string and do not put any value it will be null for sure, it does not have anything else to do, nor does it need to check if it is null, even more if it has something. Of course, examples 2 and 3 will give an error. So it's not good practice, it just makes sense to do nothing. I responded considering that the example was an error and the intent is in another context.