Почему нет 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 30.11.11
1
@ marcelo-ferrazm, about ""создает объект : нет, это не так.
Хенк

Ответы:

272

Там нет такого понятия, как пустой символ. Самое близкое, что вы можете получить '\0', это «нулевой» символ Unicode. Учитывая, что вы можете встроить это в строковые литералы или очень легко выразить его самостоятельно, зачем вам отдельное поле для него? Точно так же аргументы «легко спутать ""и " "» не применимы для'\0' .

Если бы вы могли привести пример, где вы хотели бы использовать его и почему вы думаете, что это будет лучше, это могло бы помочь ...

Джон Скит
источник
2
Разве \ 0 не является символом конца байтового массива? Или я что-то путаю?
Бертван,
5
@Bertvan: Почему в конце байтового массива должен быть символ ? Он используется для строк с нулевым символом в конце, да.
Джон Скит
35
Char.MinValue лучше, чем '\ 0'
Aliostad
10
@Aliostad: Из интереса, если бы существовало похожее поле Int32.Zero, вы бы использовали это вместо литерала 0? Если нет, то в чем здесь разница?
Джон Скит
7
@ Адам, @ Джон - какой код у Белла? Или лучше вернуться на задний план, подумайте подумать ... Или, может быть, вместо того, чтобы думать, что лучше написать Char.Backspace? Другая причина - вы говорите, что лучше написать '0' для терминатора, вместо этого, скажем, Char.Terminator, однако это не так - слишком легко сделать опечатку (полностью скомпилированную, см. Выше), но попробуйте написать Char.Termnator. У меня достаточно причин избегать необработанных, необработанных значений (космические миссии провалились из-за таких глупых опечаток).
Гринольдман
87

Символ, в отличие от строки, является дискретной вещью с фиксированным размером. Строка действительно контейнер символов.

Так что Char.Empty не имеет смысла в этом контексте. Если у вас есть символ, он не пустой.

Джо
источник
3
Совершенно верно. Имеет смысл спросить, пуст контейнер или нет. Нет смысла спрашивать int или float или char пуст.
TED
1
@Joe: Тогда как строка может быть пустой, если строка представляет собой набор (непустых) символов? Наверное, глупо, извините ...
user1477388
9
Поскольку строка - это не отдельные объекты, это коллекция. Подумайте о ведре камней. Я не могу иметь пустой камень. Но у меня может быть пустое ведро.
Джо
2
Я бы сказал, что «char - это примитив, тип значения, а строка - не примитив, ссылочный тип».
Самис
3
Это настоящий ответ.
Gandalf458
31

Нет такого понятия, как пустой персонаж. Это всегда содержит что-то . Даже '\ 0' является символом.

Филипп Лейберт
источник
28

Используйте, Char.MinValueкоторый работает так же, как '\ 0'. Но будьте осторожны, это не то же самое, что String.Empty.

Aliostad
источник
Спасибо, не видел этого раньше. Вы знаете, работает ли он в myString.Replace ('c', Char.MinValue)? Я должен попробовать.
Джоан Венге
19

Вы могли бы использовать обнуляемые символы.

char? c
paquetp
источник
Это позволяет ''? Или просто ноль?
Джоан Венге
В вашем случае вы можете сделать это: myString.Replace ("c", (c == null? "": C.ToString ()))
paquetp
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 символов :)

РЕДАКТИРОВАТЬ: или, еще лучше:

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"
Notoriousxl
источник
@Joan: спасибо ... даже если «Genius» немного преувеличен: P (я не знаю о его действиях, когда RemovalChars станет большим массивом ...)
Notoriousxl
1
Вчера я забыл: обратите внимание на то, как вы используете переменную результата "firstFiveCharsWithoutCsAndDs". Если вы не хотите передавать его другому методу yield (например, LINQ), немедленно вызовите «.ToArray ()» после «Take (5)» ... в противном случае, «RemoveChars + Take» цепочка будет выполняться каждый раз, когда вы обращаетесь к переменной «традиционным» способом (например, каждый раз, когда вы вызываете «Count ()» для нее или когда вы пересекаете ее в foreach без «yield return»)
Notoriousxl
+1 приятно думать. но это не может быть столь же легко обслуживаемым или эффективным, как базовый подход :)
nawfal
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:)

tenfour
источник
2
null невозможен, так как char является ValueType. Вы должны использовать чар? чтобы иметь возможность присвоить ему значение null.
Femaref
Вы должны сделать это обнуляемым. посмотри мой ответ
paquetp
5

Символ является типом значения, поэтому его значение не может быть нулевым. (Если только он не обернут в контейнер Nullable).

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

epotter
источник
4

Не ответ на ваш вопрос, но для обозначения по умолчанию charвы можете использовать просто

default(char)

который такой же, char.MinValueкоторый в свою очередь такой же, как \0. Не следует использовать if для чего-то вроде пустой строки.

Навфал
источник
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"
C. Tewalt
источник
Используйте StringBuilderдля result. Почему бы не обернуть return s.Replace(charsToRemove,"");?
aloisdg переходит на codidact.com
1

Если вы хотите удалить символы, которые удовлетворяют определенному условию, вы можете использовать это:

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

(Это оставит только заглавные символы в строке.)

Другими словами, вы можете «использовать» строку как IEnumerable<char> , внести в нее изменения, а затем преобразовать ее обратно в строку, как показано выше.

Опять же , это позволяет не только удалить определенный символ из лямбда - выражения, хотя вы можете сделать это , если вы измените лямбда - выражения , как это: c => c != 't'.

Florien
источник
0

Как насчет BOM , магического персонажа, который Microsoft добавляет для запуска файлов (по крайней мере, XML)?

Арто Виитанен
источник
Формулировка в Википедии здесь весьма неудачная; В этом контексте спецификация не является символом. И в чем конкретно твой вопрос? :)
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в базу данных, если это пробел.

LCJ
источник
0

Я знаю, что этот файл довольно старый, но недавно я столкнулся с проблемой необходимости многократной замены, чтобы сделать имя файла безопасным. Во-первых, в последней .NET string.Replace функция 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

использование

myString.Replace ("c", "")
Chintan
источник
2
Это дубликат ответа Иана Грейнджера от 2013 года.
Джо Гайетти
-3

Самый простой способ удалить символ из строки - обрезать его

cl = cl.Trim(' ');

Удаляет все пробелы в строке

MrSmudge
источник
Это полезно, если вы хотите использовать .Replace ('c', '') с обратной стороной удаления других пробелов. Но это более полезно, чем множество других ответов.
января
1
Нет, это не так! Обрезка удаляет только символы из начала и конца строки, а не посередине
userSteve