Re: String.Empty vs. string literal by TaylorMichaelL
TaylorMichaelL
Wed Apr 20 07:11:02 CDT 2005
We'll have to agree to disagree. I feel, like many others, that FxCop and
related tools are a wonderful addition to our toolsets. Especially since I
can create company-mandated requirements and enforce them as well. I concur
that each rule should be evaluated to determine if it applies (that is why
they have exclusions) but I think the lump decision that FxCop gives bad
"commands" is wrong. Let everybody else decide how and if they want to use
the tool. That wasn't the point of this posting anyway.
I'm not sure about your numbers because I haven't looked but I use to write
real-time compilers for a living and I know that if I put a string comparison
in there QA would hunt me down. Integer comparisons are always faster. In
the case of checking for null or length == 0 there will be 1 or 2 int
comparisons and 1 callvirt. Given that callvirt would hopefully be optimized
out when JITed this leaves 1 to 2 int comparisons.
In the case of str == "" and str == String.Empty they both call op_Equality
which calls Equals which finally does a reference comparison followed by the
instance equals. Therefore I would assume that if the string is empty then
all methods would compare about equal but if the string was not empty (the
general case) using these 2 statements would be far more expensive since
there are 3 method calls (possibly 1 with JITing), 1 comparison and a native
function call. My simple testcases seem to agree. When using a non-empty
string NullOrEmpty is the same or faster than String.Empty. When using an
empty string they all compare about the same.
Thanks for your input. Maybe there are some others that will have some more
insight.
Michael Taylor - 4/20/05
"Daniel O'Connell [C# MVP]" wrote:
>
> "TaylorMichaelL" <TaylorMichaelL@discussions.microsoft.com> wrote in message
> news:71F2A61B-7FE8-4836-91DE-F29D483C0D7A@microsoft.com...
> >I disagree with your assessment of FxCop. Evidently enough people like it
> > because it is part of VS 2005. I do agree that blindly following its
> > rules
> > is not the correct answer but they address that themselves in the
> > documentation for the tool. It is of primary use to library writers like
>
> Documenation isn't enough, if you take the number of people who read the
> documentation and the number of people who just jump in and use it, I'd bet
> you would have a difficult time fitting the ratio between the two in this
> message. People don't read it and assume that the defaults are "how its
> supposed to be".
>
> I personally think FxCop has had the dubious honor of recommending things to
> people that make no sense in the situation the person is actually in. Take
> this Length == 0 thing, its stupid. Why? Because you have to do two
> comparisons and make the expression a little more complex on the author and
> subsequent readers for performance gains that will, in probably more than
> 99% of libraries, have as much visible effect as an ounce of salt would have
> in Lake Michigan.
>
> Over a benchmark of 1 million comparisons x == "" is not significantly
> slower(about 70 milliseconds on a 400mhz, about 30 on my 2.0ghz), a big
> chunk of time if you are writing a high-throughput xml parser or an html
> renderer, but if you are just checking nameString to make sure someone typed
> it in correctly, its not going to give you anything. Yet FxCop recommends
> it, people follow it religiously, and you end up with oh so much more of
> that premature optimization that performance yonks are always talking about.
> Two comparisons coded to save less than a microsecond per comparison on a
> 400 mhz processor is ridiculous.
>
> Of interest, if already interned, the fastest way to actually compare two
> strings is by doing a reference comparison ( (object)x == (object)"" ). I'm
> seeing an average of 20-30 milliseconds per 1 million comparisons that way
> on my 2ghz.
>
> > myself that do not know ahead of time who their audience will be.
> > identify a lot of "design" flaws that are commonly made, such as new
> > protected members in a sealed class or non-private constructors in static
> > only classes. Some of these things the compiler could certainly figure
> > out
> > but "invisibly" making such a change could have unforeseen consequences.
> > Reflection comes to mind here. Of course it also is overjealous about
> > localization and IFormatProvider. I just turn these off. People have
> > been
> > using code review tools for decades. FxCop is just Microsoft's free
> > version.
> >
>
> That doesn't change that the tool recommends things that don't make sense
> all too often and that it comes across as a verbatim "Microsoft
> Recommendation." Advice given that is taken as a command is almost always
> badly put advice.
>
> The help on design flaws is nice, but I still think they could have done a
> *MUCH* better job on the rules enabled by default and explaining themselves.
>
> A tools worth is the net difference of those it helps and those it harms.
> The help on design flaws doesn't outweigh the number of bad perceptions
> FxCop has spread throughout developers in my mind.
>
>
> > I don't follow your comment on (value.Length == 0) and (value ==
> > String.Empty) not being equal. They are not "code-wise" equal (one being
> > an
> > int compare and the other calling a native comparer for the interned
> > strings)
> > but they are semantically equal. In both cases if the string is empty
> > they
> > are true and if the string is not empty they are false. The only real
> > difference is when the string is null. That is why the current
> > methodology
> > recommends (value == null) || (value.Length == 0). In 2.0 IsNullOrEmpty
> > will
> > remove the need for this conditional.
> >
>
> As a note, value == "" is *NOT* the same as (value == null) || (value.Length
> == 0), it is closer to (value != null) && (value.Length == 0). You basically
> have two different concepts
>
> one set is
>
> value == ""
> and
> value != null && value.Length == 0
>
> these are true only if the value *is* ""(string.Empty), but not if it is
> null or "a" or anything else
>
> the other set,
> value == null || value == ""
> and
> string.IsNullOrEmpty(value)
>
> are true if value is ""(string.Empty) *OR* if it is null.
>
> IsNullOrEmpty still has a different meaning than x == "", unquestionably.
> The difference between null and blank is as important as the difference
> between blank and "banana".
>
> I also, personally, think that
>
> if (x != null && x.Length == 0)
>
> is pretty ugly, harder to type, offers more points of error, and more
> complex to understand than just x == "" or x == string.Empty, and shouldn't
> be used just to make FxCop happy or for non-existant performance reasons.
> IsNullOrEmpty doesn't solve the problem as it is really an answer for a
> different problem.
>
> If there is no performance need, just a human cost, what sense does it make?
>
>
>