简体   繁体   English

确定字符串长度是否最有效的方法!= 0?

[英]Most efficient way to determine if a string length != 0?

I'm trying to speed up the following: 我正在努力加快以下方面的步伐:

string s; //--> s is never null

if (s.Length != 0)
{
   <do something>
}

Problem is, it appears the .Length actually counts the characters in the string, and this is way more work than I need. 问题是,看起来.Length实际上是对字符串中的字符进行计数,这比我需要的工作更多。 Anybody have an idea on how to speed this up? 有人知道如何加快速度吗?

Or, is there a way to determine if s[0] exists, w/out checking the rest of the string? 或者,有没有办法确定s [0]是否存在,w / out检查字符串的其余部分?

EDIT: Now that you've provided some more context: 编辑:现在您已经提供了更多上下文:

  • Trying to reproduce this, I failed to find a bottleneck in string.Length at all. 试图重现这一点,我没有找到string.Length的瓶颈。 The only way of making it faster was to comment out both the test and the body of the if block - which isn't really fair. 使其更快的唯一方法是注释掉if块的测试和正文 - 这不是很公平。 Just commenting out the condition slowed things down, ie unconditionally copying the reference was slower than checking the condition. 只是注释掉条件会减慢速度,即无条件地复制引用比检查条件要慢。

  • As has been pointed out, using the overload of string.Split which removes empty entries for you is the real killer optimization. 正如已经指出的那样,使用string.Split的重载为你删除空条目是真正的杀手优化。

  • You can go further, by avoiding creating a new char array with just a space in every time. 您可以通过避免每次只创建一个空格来创建一个新的char数组。 You're always going to pass the same thing effectively, so why not take advantage of that? 你总是会有效地传递同样的东西,为什么不利用它呢?

  • Empty arrays are effectively immutable. 空数组实际上是不可变的。 You can optimize the null/empty case by always returning the same thing. 您可以通过始终返回相同的内容来优化null / empty案例。

The optimized code becomes: 优化的代码变为:

private static readonly char[] Delimiters = " ".ToCharArray();
private static readonly string[] EmptyArray = new string[0];

public static string[] SplitOnMultiSpaces(string text)
{
    if (string.IsNullOrEmpty(text))
    {
        return EmptyArray;
    }

    return text.Split(Delimiters, StringSplitOptions.RemoveEmptyEntries);
}

String.Length absolutely does not count the letters in the string. String.Length绝对计算字符串中的字母。 The value is stored as a field - although I seem to remember that the top bit of that field is used to remember whether or not all characters are ASCII (or used to be, anyway) to enable other optimisations. 该值存储为一个字段 - 尽管我似乎记得该字段的最高位用于记住所有字符是否都是ASCII(或者过去常常用于启用其他优化)。 So the property access may need to do a bitmask, but it'll still be O(1) and I'd expect the JIT to inline it, too. 所以属性访问可能需要做一个位掩码,但它仍然是O(1)并且我希望JIT也可以内联它。 (It's implemented as an extern , but hopefully that wouldn't affect the JIT in this case - I suspect it's a common enough operation to potentially have special support.) (它是作为一个extern实现的,但希望在这种情况下不会影响JIT - 我怀疑这是一个足够普遍的操作,可能有特殊的支持。)

If you already know that the string isn't null, then your existing test of 如果您已经知道该字符串不为null,那么您现有的测试

if (s.Length != 0)

is the best way to go if you're looking for raw performance IMO. 如果你正在寻找原始性能IMO,那么这是最好的方法。 Personally in most cases I'd write: 我个人在大多数情况下写道:

if (s != "")

to make it clearer that we're not so much interested in the length as a value as whether or not this is the empty string. 更清楚的是,我们对长度的兴趣并不像是否为空字符串。 That will be slightly slower than the length test, but I believe it's clearer. 这将比长度测试略慢,但我相信它更清晰。 As ever, I'd go for the clearest code until you have benchmark/profiling data to indicate that this really is a bottleneck. 与以往一样,我会选择最清晰的代码,直到你有基准/分析数据来表明这确实一个瓶颈。 I know your question is explicitly about finding the most efficient test, but I thought I'd mention this anyway. 我知道你的问题明确是关于找到最有效的测试,但我想我还是会提到这个。 Do you have evidence that this is a bottleneck? 你有证据证明这一个瓶颈吗?

EDIT: Just to give clearer reasons for my suggestion of not using string.IsNullOrEmpty : a call to that method suggests to me that the caller is explicitly trying to deal with the case where the variable is null, otherwise they wouldn't have mentioned it. 编辑:只是给我的使用的建议更明确的理由string.IsNullOrEmpty :该方法的调用建议,我认为主叫明确设法应付其中变量是空的情况下,否则他们就不会提及它。 If at this point of the code it counts as a bug if the variable is null, then you shouldn't be trying to handle it as a normal case. 如果在代码的这一点上,如果变量 null则将其视为错误,那么您不应该尝试将其作为正常情况处理。

In this situation, the Length check is actually better in one way than the inequality test I've suggested: it acts as an implicit assertion that the variable isn't null. 在这种情况下, Length检查实际上比我建议的不等式测试更好 :它充当隐式断言,即变量不为空。 If you have a bug and it is null, the test will throw an exception and the bug will be detected early. 如果你有一个bug而且它 null,那么测试将抛出一个异常,并且会及早发现bug。 If you use the equality test it will treat null as being different to the empty string, so it will go into your "if" statement's body. 如果使用相等性测试,它会将null视为与空字符串不同,因此它将进入“if”语句的主体。 If you use string.IsNullOrEmpty it will treat null as being the same as empty, so it won't go into the block. 如果使用string.IsNullOrEmpty它会将null视为与empty相同,因此它不会进入块。

String.IsNullOrEmpty is the preferred method for checking for null or zero length strings. String.IsNullOrEmpty是检查null或零长度字符串的首选方法。

Internally, it will use Length. 在内部,它将使用长度。 The Length property for a string should not be calculated on the fly though. 但是,不应该动态计算字符串的Length属性。

If you're absolutely certain that the string will never be null and you have some strong objection to String.IsNullOrEmpty, the most efficient code I can think of would be: 如果您完全确定该字符串永远不会为null并且您对String.IsNullOrEmpty有强烈的反对意见,那么我能想到的最有效的代码是:

if(s.Length > 0)
{
    // Do Something
}

Or, possibly even better: 或者,甚至可能更好:

if(s != "")
{
    // Do Something
}

Accessing the Length property shouldn't do a count -- .NET strings store a count inside the object. 访问Length属性不应该进行计数 - .NET字符串在对象内部存储计数。

The SSCLI/Rotor source code contains an interesting comment which suggests that String.Length is (a) efficient and (b) magic: SSCLI / Rotor源代码包含一个有趣的注释,表明String.Length是(a)有效的和(b)魔术:

// Gets the length of this string
//
/// This is a EE implemented function so that the JIT can recognise is specially
/// and eliminate checks on character fetchs in a loop like:
/// for(int I = 0; I < str.Length; i++) str[i]
/// The actually code generated for this will be one instruction and will be inlined.
//
public extern int Length {
    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    get;
}

Here is the function String.IsNullOrEmpty - 这是函数String.IsNullOrEmpty -

if (!String.IsNullOrEmpty(yourstring))
{
  // your code
}

根据您在答案中描述的意图,为什么不尝试在Split上使用此内置选项:

s.Split(new[]{" "}, StringSplitOptions.RemoveEmptyEntries);
String.IsNullOrWhiteSpace(s);

如果s为null或Empty,或者s仅由空格字符组成,则返回true。

As always with performace: benchmark. 与性能一样:基准。
Using C# 3.5 or before, you'll want to test yourString.Length vs String.IsNullOrEmpty(yourString) 使用C#3.5或之前,您将要测试yourString.Length vs String.IsNullOrEmpty(yourString)

using C# 4, do both of the above and add String.IsNullOrWhiteSpace(yourString) 使用C#4,执行上述两个操作并添加String.IsNullOrWhiteSpace(yourString)

Of course, if you know your string will never be empty, you could just attempt to access s[0] and handle the exception when it's not there. 当然,如果你知道你的字符串永远不会是空的,你可以尝试访问s[0]并在不存在时处理异常。 That's not normally good practice, but it may be closer to what you need (if s should always have a non-blank value). 通常不是好的做法,但它可能更接近你需要的(如果s应该总是有一个非空白值)。

        for (int i = 0; i < 100; i++)
        {
            System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
            string s = "dsfasdfsdafasd";

            timer.Start();
            if (s.Length > 0)
            {
            }

            timer.Stop();
            System.Diagnostics.Debug.Write(String.Format("s.Length != 0 {0} ticks       ", timer.ElapsedTicks));

            timer.Reset();
            timer.Start();
            if (s == String.Empty)
            {
            }

            timer.Stop();
            System.Diagnostics.Debug.WriteLine(String.Format("s== String.Empty {0} ticks", timer.ElapsedTicks));
        }

Using the stopwatch the s.length != 0 takes less ticks then s == String.Empty 使用秒表,s.length!= 0需要更少的刻度,然后s == String.Empty

after I fix the code 在我修复代码之后

只需使用String.Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries) ,它将为您完成所有操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM