Что состоит в том, чтобы определить самый эффективный путь, пуста ли необрезанная строка в C#?

Сколько полей у вас в таблице Email_Subs?

Если ваших ответов больше одного, ваш запрос никогда не будет работать.

Запрос INSERT имеет несколько морфологий. Случай, когда вы можете опустить имена полей, имеет место только тогда, когда вы передаете значения всех полей в том же порядке, в котором они появляются в определении таблицы.

Если ваш стол выглядит так ...

+------+---------+
| id   | email   |
+------+---------+

Тогда запрос вставки может быть одним из следующих:

  1. INSERT INTO Email_Subs (email) VALUES ($ someSanatizedData)
  2. INSERT INTO Email_Subs (id, электронная почта) VALUES ($ someUniqueId, $ someSanatizedData)
  3. INSERT INTO Email_Subs (email, id) VALUES ($ someSanatizedData, $ someUniqueId)
  4. INSERT INTO Email_Subs VALUES ($ someUniqueId, $ 114]
  5. ... и многие другие
14
задан Damovisa 5 May 2009 в 02:32
поделиться

8 ответов

Редактировать: Новые тесты:

Test orders:
x. Test name
Ticks: xxxxx //Empty String
Ticks: xxxxx //two space
Ticks: xxxxx //single letter
Ticks: xxxxx //single letter with space
Ticks: xxxxx //long string
Ticks: xxxxx //long string  with space

1. if (myString.Trim().Length == 0)
ticks: 4121800
ticks: 7523992
ticks: 17655496
ticks: 29312608
ticks: 17302880
ticks: 38160224

2.  if (myString.Trim() == "")
ticks: 4862312
ticks: 8436560
ticks: 21833776
ticks: 32822200
ticks: 21655224
ticks: 42358016


3.  if (myString.Trim().Equals(""))
ticks: 5358744
ticks: 9336728
ticks: 18807512
ticks: 30340392
ticks: 18598608
ticks: 39978008


4.  if (myString.Trim() == String.Empty)
ticks: 4848368
ticks: 8306312
ticks: 21552736
ticks: 32081168
ticks: 21486048
ticks: 41667608


5.  if (myString.Trim().Equals(String.Empty))
ticks: 5372720
ticks: 9263696
ticks: 18677728
ticks: 29634320
ticks: 18551904
ticks: 40183768


6.  if (IsEmptyOrWhitespace(myString))  //See John Skeet's Post for algorithm
ticks: 6597776
ticks: 9988304
ticks: 7855664
ticks: 7826296
ticks: 7885200
ticks: 7872776

7. is (string.IsNullOrEmpty(myString.Trim())  //Cloud's suggestion
ticks: 4302232
ticks: 10200344
ticks: 18425416
ticks: 29490544
ticks: 17800136
ticks: 38161368

И используемый код:

public void Main()
{

    string res = string.Empty;

    for (int j = 0; j <= 5; j++) {

        string myString = "";

        switch (j) {

            case 0:
                myString = "";
                break;
            case 1:
                myString = "  ";
                break;
            case 2:
                myString = "x";
                break;
            case 3:
                myString = "x ";
                break;
            case 4:
                myString = "this is a long string for testing triming empty things.";
                break;
            case 5:
                myString = "this is a long string for testing triming empty things. ";

                break;
        }

        bool result = false;
        Stopwatch sw = new Stopwatch();

        sw.Start();
        for (int i = 0; i <= 100000; i++) {


            result = myString.Trim().Length == 0;
        }
        sw.Stop();


        res += "ticks: " + sw.ElapsedTicks + Environment.NewLine;
    }


    Console.ReadKey();  //break point here to get the results
}
19
ответ дан 1 December 2019 в 06:21
поделиться

Проверка длины строки на нулевое значение является наиболее эффективным способом проверки пустой строки, поэтому я бы сказал номер 1:

if (myString.Trim().Length == 0)

Единственный способ еще больше оптимизировать это - избежать обрезки с помощью скомпилированного регулярного выражения (Edit: это на самом деле намного медленнее, чем с помощью Trim (). Length).

Edit: предложение использовать Length пришло из директивы FxCop. Я также только что проверил это: это в 2-3 раза быстрее, чем по сравнению с пустой строкой. Однако оба подхода все еще чрезвычайно быстры (мы говорим о наносекундах) - поэтому вряд ли имеет значение, какой вы используете. Тримминг - это гораздо более узкое место

3
ответ дан 1 December 2019 в 06:21
поделиться

myString.Trim (). Длина == 0 Взятие: 421 мс

myString.Trim () == '' заняло: 468 мс

если (myString.Trim (). Equals ("")) Взял: 515 мс

if (myString.Trim () == String.Empty) Взял: 484 мс

if (myString. Trim (). Equals (String.Empty)) Взятие: 500 мс

if (string.IsNullOrEmpty (myString.Trim ())) Взятие: 437 мс

В моих тестах это выглядит как myString.Trim (). Length == 0 и, что удивительно, string.IsNullOrEmpty (myString.Trim ()) всегда были самыми быстрыми. Приведенные выше результаты являются типичным результатом выполнения 10 000 000 сравнений.

4
ответ дан 1 December 2019 в 06:21
поделиться

Я действительно не знаю, что быстрее; хотя мое внутреннее чувство говорит номер один. Но вот еще один метод:

if (String.IsNullOrEmpty(myString.Trim()))
4
ответ дан 1 December 2019 в 06:21
поделиться

(РЕДАКТИРОВАТЬ: см. Внизу поста для тестов по различным микро-оптимизациям метода)

Не обрезайте его - это может создать новую строку, которая вам на самом деле не нужна , Вместо этого просмотрите строку для любых символов, которые не являются пробелами (для любого определения, которое вы хотите). Например:

public static bool IsEmptyOrWhitespace(string text)
{
    // Avoid creating iterator for trivial case
    if (text.Length == 0)
    {
        return true;
    }
    foreach (char c in text)
    {
        // Could use Char.IsWhiteSpace(c) instead
        if (c==' ' || c=='\t' || c=='\r' || c=='\n')
        {
            continue;
        }
        return false;
    }
    return true;
}

Вы также можете рассмотреть, что вы хотите, чтобы метод делал, если text равен null .

Возможны дальнейшие микрооптимизации для экспериментов:

  • Is foreach быстрее или медленнее, чем использование цикла для , как показано ниже? Обратите внимание, что с помощью цикла для вы можете удалить тест « if (text.Length == 0) » в начале.

     для (int i = 0; i < text.Length; i ++)
    {
     char c = text [i];
     // ...
    
  • То же, что и выше, но поднять вызов Length . Обратите внимание, что это не подходит для нормальных массивов, но может быть полезно для строк. Я не проверял это.

     int length = text.Length;
    для (int i = 0; i <длина; i ++)
    {
     char c = text [i];
    
  • В теле цикла есть ли разница (по скорости) между тем, что у нас есть, и:

     if (c! = '' && c! = '\ T' && c! = '\ r '&& c! =' \ n ')
    {
     вернуть ложь;
    }
    
  • Будет ли переключатель / корпус быстрее?

     переключатель (с)
    {
     case '': case '\ r': case '\ n': case '\ t':
     вернуть ложь; 
    }
    

Обновление поведения Trim

Я только что посмотрел, как Trim может быть настолько эффективным, как этот. Кажется, что Trim создаст новую строку только в случае необходимости. Если он может вернуть этот или "" , он будет:

using System;

class Test
{
    static void Main()
    {
        CheckTrim(string.Copy(""));
        CheckTrim("  ");
        CheckTrim(" x ");
        CheckTrim("xx");
    }

    static void CheckTrim(string text)
    {
        string trimmed = text.Trim();
        Console.WriteLine ("Text: '{0}'", text);
        Console.WriteLine ("Trimmed ref == text? {0}",
                          object.ReferenceEquals(text, trimmed));
        Console.WriteLine ("Trimmed ref == \"\"? {0}",
                          object.ReferenceEquals("", trimmed));
        Console.WriteLine();
    }
}

Это означает, что очень важно, чтобы любые тесты в этом вопросе использовали смесь данных:

  • Пустая строка
  • Пробелы
  • Пробелы, окружающие текст
  • Текст без пробелов

Конечно, баланс «реального мира» между этими четырьмя невозможно предсказать ...

Тесты Я провел несколько тестов исходных предложений по сравнению с моими, и мои, кажется, выиграли во всем, что я бросаю в него, что удивляет меня, учитывая результаты в других ответах. Однако я также провел сравнение различий между foreach , для с использованием text.Length , для с использованием text.Length один раз, а затем обратный порядок итераций и для с длиной подъема.

По сути, цикл для очень немного быстрее, но подъем проверки длины делает его медленнее чем foreach . Реверсирование для направления петли немного медленнее, чем foreach . Я сильно подозреваю, что JIT делает здесь интересные вещи с точки зрения удаления повторяющихся проверок границ и т. Д.

Код: (см. мою запись в блоге для фреймворка, против которого она написана)

using System;
using BenchmarkHelper;

public class TrimStrings
{
    static void Main()
    {
        Test("");
        Test(" ");
        Test(" x ");
        Test("x");
        Test(new string('x', 1000));
        Test(" " + new string('x', 1000) + " ");
        Test(new string(' ', 1000));
    }

    static void Test(string text)
    {
        bool expectedResult = text.Trim().Length == 0;
        string title = string.Format("Length={0}, result={1}", text.Length, 
                                     expectedResult);

        var results = TestSuite.Create(title, text, expectedResult)
/*            .Add(x => x.Trim().Length == 0, "Trim().Length == 0")
            .Add(x => x.Trim() == "", "Trim() == \"\"")
            .Add(x => x.Trim().Equals(""), "Trim().Equals(\"\")")
            .Add(x => x.Trim() == string.Empty, "Trim() == string.Empty")
            .Add(x => x.Trim().Equals(string.Empty), "Trim().Equals(string.Empty)")
*/
            .Add(OriginalIsEmptyOrWhitespace)
            .Add(IsEmptyOrWhitespaceForLoop)
            .Add(IsEmptyOrWhitespaceForLoopReversed)
            .Add(IsEmptyOrWhitespaceForLoopHoistedLength)
            .RunTests()                          
            .ScaleByBest(ScalingMode.VaryDuration);

        results.Display(ResultColumns.NameAndDuration | ResultColumns.Score,
                        results.FindBest());
    }

    public static bool OriginalIsEmptyOrWhitespace(string text)
    {
        if (text.Length == 0)
        {
            return true;
        }
        foreach (char c in text)
        {
            if (c==' ' || c=='\t' || c=='\r' || c=='\n')
            {
                continue;
            }
            return false;
        }
        return true;
    }

    public static bool IsEmptyOrWhitespaceForLoop(string text)
    {
        for (int i=0; i < text.Length; i++)
        {
            char c = text[i];
            if (c==' ' || c=='\t' || c=='\r' || c=='\n')
            {
                continue;
            }
            return false;
        }
        return true;
    }

    public static bool IsEmptyOrWhitespaceForLoopReversed(string text)
    {
        for (int i=text.Length-1; i >= 0; i--)
        {
            char c = text[i];
            if (c==' ' || c=='\t' || c=='\r' || c=='\n')
            {
                continue;
            }
            return false;
        }
        return true;
    }

    public static bool IsEmptyOrWhitespaceForLoopHoistedLength(string text)
    {
        int length = text.Length;
        for (int i=0; i < length; i++)
        {
            char c = text[i];
            if (c==' ' || c=='\t' || c=='\r' || c=='\n')
            {
                continue;
            }
            return false;
        }
        return true;
    }
}

Результаты:

============ Length=0, result=True ============
OriginalIsEmptyOrWhitespace             30.012 1.00
IsEmptyOrWhitespaceForLoop              30.802 1.03
IsEmptyOrWhitespaceForLoopReversed      32.944 1.10
IsEmptyOrWhitespaceForLoopHoistedLength 35.113 1.17

============ Length=1, result=True ============
OriginalIsEmptyOrWhitespace             31.150 1.04
IsEmptyOrWhitespaceForLoop              30.051 1.00
IsEmptyOrWhitespaceForLoopReversed      31.602 1.05
IsEmptyOrWhitespaceForLoopHoistedLength 33.383 1.11

============ Length=3, result=False ============
OriginalIsEmptyOrWhitespace             30.221 1.00
IsEmptyOrWhitespaceForLoop              30.131 1.00
IsEmptyOrWhitespaceForLoopReversed      34.502 1.15
IsEmptyOrWhitespaceForLoopHoistedLength 35.690 1.18

============ Length=1, result=False ============
OriginalIsEmptyOrWhitespace             31.626 1.05
IsEmptyOrWhitespaceForLoop              30.005 1.00
IsEmptyOrWhitespaceForLoopReversed      32.383 1.08
IsEmptyOrWhitespaceForLoopHoistedLength 33.666 1.12

============ Length=1000, result=False ============
OriginalIsEmptyOrWhitespace             30.177 1.00
IsEmptyOrWhitespaceForLoop              33.207 1.10
IsEmptyOrWhitespaceForLoopReversed      30.867 1.02
IsEmptyOrWhitespaceForLoopHoistedLength 31.837 1.06

============ Length=1002, result=False ============
OriginalIsEmptyOrWhitespace             30.217 1.01
IsEmptyOrWhitespaceForLoop              30.026 1.00
IsEmptyOrWhitespaceForLoopReversed      34.162 1.14
IsEmptyOrWhitespaceForLoopHoistedLength 34.860 1.16

============ Length=1000, result=True ============
OriginalIsEmptyOrWhitespace             30.303 1.01
IsEmptyOrWhitespaceForLoop              30.018 1.00
IsEmptyOrWhitespaceForLoopReversed      35.475 1.18
IsEmptyOrWhitespaceForLoopHoistedLength 40.927 1.36
15
ответ дан 1 December 2019 в 06:21
поделиться

Так как я только начал, я не могу комментировать, вот и он.

if (String.IsNullOrEmpty(myString.Trim()))

Вызов Trim () завершится ошибкой, если myString равен нулю, так как вы не можете вызывать методы в объекте это null ( NullReferenceException ).

Таким образом, правильный синтаксис будет выглядеть примерно так:

if (!String.IsNullOrEmpty(myString))
{
    string trimmedString = myString.Trim();
    //do the rest of you code
}
else
{
    //string is null or empty, don't bother processing it
}
1
ответ дан 1 December 2019 в 06:21
поделиться
public static bool IsNullOrEmpty(this String str, bool checkTrimmed)
{
  var b = String.IsNullOrEmpty(str);
  return checkTrimmed ? b && str.Trim().Length == 0 : b;
}
0
ответ дан 1 December 2019 в 06:21
поделиться

String.IsNullOrWhitespace в .NET 4 Beta 2 также воспроизводится в этом пространстве и не требует специальной записи

3
ответ дан 1 December 2019 в 06:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: