Чому немає Char.Empty, як String.Empty?


259

Чи є для цього причина? Я прошу, бо якщо вам потрібно було використовувати багато порожніх символів, то ви потрапляєте в ту саму ситуацію, що і коли ви використовуєте багато порожніх рядків.

Редагувати: Причиною цього використання стало таке:

myString.Replace ('c', '')

Тож видаліть усі екземпляри c з myString.


1
Так, я використав це слово для відсутності кращого слова. тобто рекомендований спосіб використання String.Empty замість "".
Джоан Венге

3
Якщо ви стурбовані випадковим помилковим введенням "", чому б просто не просто перегорнути функціональність методом розширення за лініями RemoveAll(this string s, params char[] toRemove)? Про наміри буде чітко повідомлено, і ви не ризикуєте нічого заплутати.
bzlm

12
@Henk - Єдина причина, що я використовую string.Empty, тому що я знаходжу нульовий об’єкт, наданий Empty, виражає наміри краще, ніж порожні лапки. Порожні лапки можуть бути наслідком проблеми злиття, або помилкової думки, або це може бути фактичний намір цього коду, тоді як Empty явно говорить мені, що розробник зазначав, що для цього рядка немає даних.
Річ Мелтон

3
Існує різниця між "" та рядком. Порожньо. Не те, що когось хвилює, але "" створює об'єкт, тоді як string.Empty використовує вже створений. Але знову ж таки, він настільки малий, що лише для особливих ситуацій він міг би змінити
marcelo-ferraz

1
@ marcelo-ferrazm, про ""створює об’єкт : Ні, це не так.
Хенк Холтерман

Відповіді:


271

Немає такого поняття, як порожній знак. Найближчий ти можеш отримати - '\0'нульовий символ Unicode. З огляду на те, що ви можете вбудувати це в рядкові літерали або висловити його самостійно дуже легко, чому б ви хотіли для нього окреме поле? Так само аргументи " легко сплутати ""і " "" не застосовуються '\0'.

Якщо ви можете навести приклад того, де ви хочете його використовувати, і чому ви думаєте, що це було б краще, це може допомогти ...


2
Чи не символ \ 0 є кінцем байтового масиву? Або я плутаю щось із іншим?
Бертван

5
@ Bertvan: Чому в кінці байтового масиву буде символ ? Він використовується для рядків з "нульовим завершенням", хоча так.
Джон Скіт

35
Char.MinValue кращий, ніж '\ 0'
Аліостад

10
@Aliostad: Якщо б не було подібного поля для Int32.Zero, ви б використали це замість буквального 0? Якщо ні, то яка різниця тут?
Джон Скіт

7
@Adam, @Jon - що таке код для дзвоника? Або краще повернути простір, подумайте, подумайте ... А може, замість того, щоб думати, просто краще написати Char.Backspace? Ще одна причина - ви кажете, що краще написати "0" для термінатора, натомість скажіть Char.Terminator, однак це не так - занадто просто зробити друк (повністю складений, див. Вище), але спробуйте написати Char.Termnator. Для мене є достатньо причин, щоб уникнути неперевірених, сирих цінностей (космічні місії не вдалися через дурні подібні помилки).
greenoldman

87

Чар на відміну від струни - це дискретна річ із фіксованим розміром. Рядок - це дійсно контейнер символів.

Отже, Char.Empty насправді не має сенсу в цьому контексті. Якщо у вас є чарівниця, вона не порожня.


3
Точно правильно. Є сенс запитати, чи є контейнер порожнім чи ні. Немає сенсу запитувати про те, чи int чи float чи char порожні.
ТЕД

1
@Joe: Тоді як рядок може бути порожнім, якщо рядок - це сукупність (не порожніх) символів? Напевно, дурний, вибач ...
користувач1477388

9
Оскільки рядок не є окремими об'єктами, це колекція. Придумайте відро скель. Я не можу мати порожню скелю. Але у мене може бути порожнє відро.
Джо

2
Я б назвав це як "char - примітив, тип значення, а рядок - непримітивний, тип відліку".
Саміс

3
Це справжня відповідь.
Gandalf458


28

Використовуйте, Char.MinValueщо працює так само, як "\ 0". Але будьте обережні, це не те саме, що String.Empty.


Дякую, я цього раніше не бачив. Чи знаєте ви, чи працює він у myString.Replace ('c', Char.MinValue)? Я повинен спробувати.
Джоан Венге


12

Якщо вам не потрібен весь рядок, ви можете скористатися затримкою виконання:

public static class StringExtensions
{
    public static IEnumerable<char> RemoveChar(this IEnumerable<char> originalString, char removingChar)
    {
        return originalString.Where(@char => @char != removingChar);
    }
}

Ви навіть можете комбінувати кілька символів ...

string veryLongText = "abcdefghijk...";

IEnumerable<char> firstFiveCharsWithoutCsAndDs = veryLongText
            .RemoveChar('c')
            .RemoveChar('d')
            .Take(5);

... і лише перші 7 символів будуть оцінені :)

EDIT: або, ще краще:

public static class StringExtensions
{
    public static IEnumerable<char> RemoveChars(this IEnumerable<char> originalString,
        params char[] removingChars)
    {
        return originalString.Except(removingChars);
    }
}

та його використання:

        var veryLongText = "abcdefghijk...";
        IEnumerable<char> firstFiveCharsWithoutCsAndDs = veryLongText
            .RemoveChars('c', 'd')
            .Take(5)
            .ToArray(); //to prevent multiple execution of "RemoveChars"

@Joan: дякую ... навіть якщо "Genius" це трохи перебільшено: P (я не знаю про його виступи, коли видаленняChars стане великим масивом ...)
Notoriousxl

1
Вчора я забув: зверніть увагу на те, як ви використовуєте змінну результатів "firstFiveCharsWithoutCsAndDs". Якщо ви не хочете передати його іншому методу "урожайності" (наприклад, LINQ), негайно викликайте ".ToArray ()" після "Take (5)" ... в іншому випадку, "RemoveChars + Take" ланцюг буде виконуватися щоразу, коли ви отримуєте доступ до змінної «традиційним» способом (наприклад, кожен, коли ви називаєте на неї «Count ()», або коли ви переходите в передбачення без «прибутковості»)
Notoriousxl

+1 приємне мислення. але це не може бути настільки
ретельним

1
@nawfal-ефективність, ви праві, але я думаю, що myString.Except ("c") є декларативнішим, ніж myString.Replace ('c', ''): P (і він масштабує досить добре: myString.Except ( "aeiou"))
Notoriousxl

7
myString = myString.Replace('c'.ToString(), "");

Гаразд, це не особливо елегантно для видалення букв, оскільки метод .Replace має перевантаження, яка приймає рядкові параметри. Але це працює для видалення повернень каретки, каналів рядків, вкладок тощо. Цей приклад видаляє символи вкладок:

myString = myString.Replace('\t'.ToString(), "");

6

тієї ж причини немає int.Empty. Контейнери можуть бути порожніми. Скалярних значень бути не може. Якщо ви маєте на увазі 0 (який не порожній), тоді використовуйте '\0'. Якщо ви маєте на увазі null, то використовуйте null:)


2
null не можливий, оскільки char - це ValueType. Вам доведеться використовувати char? бути в змозі призначити нуль.
Femaref

ти можеш зробити це незмінним. дивіться мою відповідь
paquetp

5

Значок char - тип значення, тому його значення не може бути нульовим. (За винятком випадків, коли він не загорнутий в ємність, що обтягується).

Оскільки він не може бути нульовим, в ньому міститься якийсь числовий код, і кожен код відображається на деякий символ.


4

Не відповідь на ваше запитання, але для позначення типових умов charможна використовувати просто

default(char)

що те саме, char.MinValueщо в свою чергу те саме, що \0. Не слід використовувати, якщо для чогось на зразок порожнього рядка.


1

Не відповідає на ваше перше запитання - але для конкретної проблеми, яку ви виникли, ви можете просто використовувати рядки замість знаків, правда ?:

myString.Replace("c", "")

Є причина, з якої ви цього не хочете робити?


1

Ви також можете відновити свій рядковий символ за символом, виключаючи символи, від яких ви хочете позбутися.

Ось спосіб розширення для цього:

    static public string RemoveAny(this string s, string charsToRemove)
    {
        var result = "";
        foreach (var c in s)
            if (charsToRemove.Contains(c))
                continue;
            else
                result += c;

        return result;
    }

Це не гладко або вигадливо, але добре працює.

Використовуйте так:

string newString = "My_String".RemoveAny("_"); //yields "MyString"

Використовуйте StringBuilderдля result. Чому б не обмотати return s.Replace(charsToRemove,"");?
aloisdg переходить на codidact.com

1

Якщо ви хочете видалити символи, які відповідають певній умові, ви можете скористатися цим:

string s = "SoMEthInG";
s = new string(s.Where(c => char.IsUpper(c)).ToArray());

(У рядку залишаться лише великі літери.)

Іншими словами, ви можете "використовувати" рядок як an IEnumerable<char>, вносити зміни до нього, а потім перетворювати його в рядок, як показано вище.

Знову ж , це дозволяє не тільки видалити певний символ з лямбда - вираження, хоча ви можете зробити це , якщо ви зміните лямбда - вираження , як це: c => c != 't'.


0

Як щодо BOM , магічного персонажа, який Microsoft додає для запуску файлів (принаймні XML)?


Формулювання у Вікіпедії тут досить прикро; BOM не є персонажем у цьому контексті. І яке саме ваше питання? :)
bzlm

@onemach, тож, чи myString.Replace ('c', '')можна цього досягти myString.Replace ('c', UTF_BOM). Тоді я б сказав, що відповідь "як не про ...".
bzlm

0

якщо ви хочете усунути порожній знак у рядку, наступне буде спрацьовувати, просто перетворіть у будь-яке представлення типу даних, яке ви хочете. Дякую,

private void button1_Click(object sender, EventArgs e)
    {

        Int32 i;

        String name;

        Int32[] array_number = new int[100];

        name = "1 3  5  17   8    9    6";

        name = name.Replace(' ', 'x');

        char[] chr = name.ToCharArray();


        for (i = 0; i < name.Length; i++)
        {
            if ((chr[i] != 'x'))
            {
                array_number[i] = Convert.ToInt32(chr[i].ToString());
                MessageBox.Show(array_number[i].ToString());
            }

        }

    }

0

Щодо мови C #, наступне може не мати особливого сенсу. І це не пряма відповідь на питання. Але птахівництво - це те, що я робив в одному зі своїх бізнес-сценаріїв

        char? myCharFromUI = Convert.ToChar(" ");
        string myStringForDatabaseInsert = myCharFromUI.ToString().Trim();
        if (String.IsNullOrEmpty(myStringForDatabaseInsert.Trim()))
        {
            Console.Write("Success");
        }

nullІ white spaceмали різні бізнес потоки в моєму проекті. Під час вставки в базу даних мені потрібно вставити empty stringв базу даних, якщо це пробіл.


0

Я знаю, що ця досить стара, але останнім часом я зіткнувся з проблемою, коли потрібно зробити кілька замін, щоб захистити ім’я файлу. По-перше, в останньому рядку .NET. Замініть функцію null - еквівалент порожньому символу. Сказавши це, чого не вистачає .Net - це проста заміна всього, що замінить будь-який символ у масиві потрібним символом. Будь ласка, посилайтесь на код нижче (працює в LinqPad для тестування).

// LinqPad .ReplaceAll and SafeFileName
void Main()
{

    ("a:B:C").Replace(":", "_").Dump();                     // can only replace 1 character for one character => a_B_C
    ("a:B:C").Replace(":", null).Dump();                    // null replaces with empty => aBC
    ("a:B*C").Replace(":", null).Replace("*",null).Dump();  // Have to chain for multiples 

    // Need a ReplaceAll, so I don't have to chain calls


    ("abc/123.txt").SafeFileName().Dump();
    ("abc/1/2/3.txt").SafeFileName().Dump();
    ("a:bc/1/2/3.txt").SafeFileName().Dump();
    ("a:bc/1/2/3.txt").SafeFileName('_').Dump();
    //("abc/123").SafeFileName(':').Dump(); // Throws exception as expected

}


static class StringExtensions
{

    public static string SafeFileName(this string value, char? replacement = null)
    {
        return value.ReplaceAll(replacement, ':','*','?','"','<','>', '|', '/', '\\');
    }

    public static string ReplaceAll(this string value, char? replacement, params char[] charsToGo){

        if(replacement.HasValue == false){
                return string.Join("", value.AsEnumerable().Where(x => charsToGo.Contains(x) == false));
        }
        else{

            if(charsToGo.Contains(replacement.Value)){
                throw new ArgumentException(string.Format("Replacement '{0}' is invalid.  ", replacement), "replacement");
            }

            return string.Join("", value.AsEnumerable().Select(x => charsToGo.Contains(x) == true ? replacement : x));
        }

    }

}


-3

Найпростіший спосіб видалити символ із рядка - обрізати його

cl = cl.Trim(' ');

Видаляє всі пробіли в рядку


Це корисно, якщо хочеться використовувати .Replace ('c', '') зі зворотним боком видалення інших пробілів. Але це корисніше, ніж багато інших відповідей.
Jan

1
Ні, це неправильно! Обріжте лише видалення знаків із початку та кінця рядка, а не посередині
користувачSteve
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.