Neden String.Empty gibi Char.Empty yok?


259

Bunun bir sebebi var mı? Çok fazla boş karakter kullanmanız gerekiyorsa, çok sayıda boş karakter kullandığınızda aynı duruma girdiğiniz için soruyorum.

Düzenleme: Bu kullanımın nedeni şuydu:

myString.Replace ('c', '')

Bu yüzden 'c'lerin tüm örneklerini myString'den kaldırın.


1
Evet, bu kelimeyi daha iyi bir kelime eksikliği için kullandım. yani "" yerine String.Empty kullanmanın önerilen yolu.
Joan Venge

3
Bazen yanlışlıkla yanlış yazmayla ilgili endişeleriniz varsa, neden sadece bir uzantı yöntemindeki işlevselliği satırları boyunca sarmıyorsunuz RemoveAll(this string s, params char[] toRemove)? Niyet açık bir şekilde iletilecek ve hiçbir şeyi bulamadığınız için risk almayacaksınız.
bzlm

12
@.Henk - string.Empty kullanmamın tek nedeni, Empty tarafından sağlanan null nesnesini boş tırnaklardan daha iyi bulmamdır. Boş tırnak işaretleri bir birleştirme sorunu veya tıkalı bir düşünceden kaynaklanabilir ya da bu kodun gerçek amacı olabilir, oysa Boş açıkça geliştiricinin veriye sahip olmamasını istediğini söyler.
Ritch Melton

3
"" İle dize arasında bir fark vardır. Boşalt. Kimsenin umurunda değil, ama "" bir nesne yaratırken string.Empty zaten yapılmış olanı kullanır. Ama yine, o kadar küçük ki, sadece özel durumlar bir fark yaratacaktır
marcelo-ferraz

1
@ marcelo-ferrazm, hakkında ""bir nesne yaratır : Hayır, yapmaz.
Henk Holterman

Yanıtlar:


272

Boş bir karakter diye bir şey yoktur. En yakın '\0'Unicode "null" karakteri. Bunu dizgi değişmezleri içine yerleştirebildiğiniz veya kendi başına kolayca ifade edebildiğiniz göz önüne alındığında, bunun için neden ayrı bir alan istesin ki? Aynı şekilde, "karıştırılması kolaydır ""ve " "" argümanlar için geçerli değildir '\0'.

Nerede kullanmak istediğinize ve neden daha iyi olacağını düşündüğünüze bir örnek verebilirseniz, bu yardımcı olabilir ...


2
\ 0 'bayt dizisinin sonu' karakteri değil mi? Yoksa başka bir şeyle mi karıştırıyorum?
Bertvan

5
@Bertvan: Neden bir bayt dizisinin sonunda bir karakter olsun ki ? Yine de, "boş sonlandırılmış" dizeler için kullanılır, evet.
Jon Skeet

35
Char.MinValue '\ 0' dan daha iyidir
Aliostad

10
@Aliostad: İlgi alanı dışında, benzer bir alan Int32.Zeroolsaydı, 0 harfi yerine bunu kullanır mıydınız ? Değilse, buradaki fark nedir?
Jon Skeet

7
@Adam, @Jon - zil kodu nedir? Ya da daha iyi geri al, düşün düşün ... Ya da belki de Char.Backspace yazmanın daha iyi olduğunu düşünmek yerine? Başka bir neden - terminatör için '0' yazmanın daha iyi olduğunu söylüyorsunuz, bunun yerine Char.Terminator deyin, ancak öyle değil - yazım hatası yapmak çok kolay (tamamen derlenmiş, yukarıya bakın), ama yazmaya çalışın Char.Termnator. Kontrol edilemeyen, ham değerlerden kaçınmam için yeterli nedenler var (bu tür aptal yazım hataları nedeniyle uzay görevleri başarısız oldu).
greenoldman

87

Bir karakter, dizeden farklı olarak, sabit bir boyuta sahip ayrı bir şeydir. Bir dize gerçekten karakter kabıdır.

Yani Char.Empty bu bağlamda gerçekten bir anlam ifade etmiyor. Bir karakteriniz varsa, boş değil.


3
Kesinlikle doğru. Bir kabın boş olup olmadığını sormak mantıklıdır. Bir int veya float veya char boş istemek mantıklı değil.
TED

1
@Joe: Eğer bir dize (boş olmayan) karakterlerden oluşan bir koleksiyonsa, bir dize nasıl boş olabilir? Muhtemelen aptalca, üzgünüm ...
user1477388

9
Bir dize tek tek nesneler olmadığı için koleksiyondur. Bir kova kaya düşünün. Boş bir kayaya sahip olamam. Ama boş bir kova alabilirim.
Joe

2
Ben "char ilkel, değer türü ve bir dize ilkel olmayan, başvuru türü" olarak ifade ediyorum.
samis

3
Gerçek cevap bu.
Gandalf458

31

Boş bir karakter diye bir şey yoktur. Her zaman bir şeyler içerir . '\ 0' bile bir karakterdir.


28

Char.MinValue'\ 0' ile aynı olanı kullanın . Ancak dikkatli olun aynı değildir String.Empty.


Teşekkürler, daha önce görmedim. MyString.Replace ('c', Char.MinValue) içinde çalışıp çalışmadığını biliyor musunuz? Denemeliyim.
Joan Venge


12

Dizenin tamamına ihtiyacınız yoksa, gecikmeli yürütme işleminden yararlanabilirsiniz:

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

Hatta birden fazla karakteri birleştirebilirsiniz ...

string veryLongText = "abcdefghijk...";

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

... ve sadece ilk 7 karakter değerlendirilecek :)

DÜZENLEME: ya da daha iyisi:

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

ve kullanımı:

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

@Joan: teşekkürler ... "Genius" biraz abartılı olsa bile: P (Kaldırırken performansları hakkında bilmiyorumChars büyük bir dizi olacak ...)
Notoriousxl

1
Dün unuttum: "firstFiveCharsWithoutCsAndDs" sonuç değişkenini nasıl kullandığınıza dikkat edin. Başka bir "verim" yöntemine (LINQ gibi) geçirmek istemiyorsanız, hemen "Take (5)" den sonra ".ToArray ()" çağırın ... aksi takdirde, "RemoveChars + Take" "geleneksel" bir tarzda değişkene her eriştiğinizde (örneğin, üzerinde "Sayım ()" adını her verdiğinizde veya "verim iadesi" olmadan bir foreach içinde geçiş yaptığınızda zincir çalıştırılır
Notoriousxl

+1 güzel düşünce. ancak bu temel yaklaşım kadar sürdürülebilir veya verimli
olamaz

1
@nawfal verimlilik açısından haklısınız, ancak bence myString.Except ("c") myString.Replace ('c', ''): P'den daha iyi beyan ediyor: ve oldukça iyi ölçekleniyor: myString.Except ( "aeiou"))
Notoriousxl

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

Tamam, bu harfleri kaldırmak için özellikle zarif değildir, çünkü .Replace yöntemi dize parametrelerini alan bir aşırı yüke sahiptir. Ancak bu, satır başlarını, satır beslemelerini, sekmeleri vb. Kaldırmak için çalışır. Bu örnek sekme karakterlerini kaldırır:

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

6

aynı sebep yok int.Empty. Kaplar boş olabilir. Skaler değerler olamaz. 0 (boş değil) demek istiyorsanız, kullanın '\0'. Eğer demek istiyorsan null, kullan null:)


2
char bir ValueType olduğundan null mümkün değildir. Char kullanmak zorunda mısın? ona null atama yapabilmek.
Femaref

onu nulllable yapabilirsiniz. cevabımı gör
paquetp

5

Karakter değeri tipidir, bu nedenle değeri boş olamaz. (Bir Nullable kabına sarılmadıkça).

Boş olamaz çünkü içinde bazı sayısal kodlar bulunur ve her kod bir karakterle eşleştirilir.


4

Değil bir Sorunuzun cevabı, ancak varsayılan belirtmek için charsadece kullanabilirsiniz

default(char)

ki aynı char.MinValueolanla aynıdır \0. Ancak boş bir dize gibi bir şey için kullanmamalısınız.


1

İlk sorunuza cevap vermiyor - ancak karşılaştığınız sorun için karakter yerine dizeleri kullanabilirsiniz, değil mi ?:

myString.Replace("c", "")

Bunu yapmak istememenizin bir nedeni var mı?


1

Kurtulmak istediğiniz karakterler hariç, dize karakterinizi karaktere göre yeniden oluşturabilirsiniz.

İşte bunu yapmak için bir uzantı yöntemi:

    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;
    }

Kaygan veya süslü değil, ama iyi çalışıyor.

Bunun gibi kullanın:

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

Bir kullan StringBuilderiçin result. Neden sarılmıyorsunuz return s.Replace(charsToRemove,"");?
aloisdg taşınma codidact.com

1

Belirli bir koşulu karşılayan karakterleri kaldırmak istiyorsanız, bunu kullanabilirsiniz:

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

(Bu, dizede yalnızca büyük harfli karakterler bırakacaktır.)

Başka bir deyişle, dizeyi " IEnumerable<char> , üzerinde değişiklik yapabilir ve sonra yukarıda gösterildiği gibi bir dizgeye dönüştürebilirsiniz.

Böyle Lambda ifade değiştirirseniz bunu rağmen Yine, bu, çünkü lambda ifade belirli kömürü çıkarmak için sadece sağlar: c => c != 't'.


0

Microsoft'un dosyaların başlangıcına eklediği büyülü karakter BOM'a (en azından XML) ne dersiniz ?


Wikipedia'daki ifadeler oldukça talihsiz; Malzeme Listesi bu bağlamda bir karakter değildir. Ve sorunuz tam olarak nedir? :)
bzlm

@ onemach, yani, myString.Replace ('c', '')tarafından elde edilip edilemeyeceği myString.Replace ('c', UTF_BOM). Sonra cevabın "nasıl olmasın ..." olduğunu söyleyebilirim .
bzlm

0

Eğer dizede boş karakterleri ortadan kaldırmak istiyorsanız aşağıdakiler işe yarar, sadece istediğiniz herhangi bir veri tipi gösterimine dönüştürün. Teşekkürler,

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 # dili açısından, aşağıdakiler pek mantıklı olmayabilir. Ve bu soruya doğrudan bir cevap değil. Ancak iş senaryomdan birinde yaptığım şey

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

nullVe white spacevardı farklı iş Projemdeki akar. Veritabanına eklerken, empty stringboşluk ise veritabanına eklemek gerekir .


0

Bu oldukça eski olduğunu biliyorum, ama son zamanlarda bir dosya adını güvenli hale getirmek için birden fazla değişiklik yapmak zorunda bir sorunla karşılaştı. İlk olarak, en son .NET string.Replace işlevi null, boş karaktere eşdeğerdir. Bunu söyledikten sonra, .Net'te eksik olan şey, bir dizideki herhangi bir karakteri istenen karakterle değiştirecek olan basit bir değişikliktir. Lütfen aşağıdaki koda başvurmaktan çekinmeyin (test için LinqPad'de çalışır).

// 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

kullanım

myString.Replace ("c", "")

2
Bu 2013'ten Ian Grainger tarafından verilen yanıtın kopyası.
Joe Gayetty

-4

Dizeden bir karakteri battaniyeden çıkarmanın en kolay yolu Kırpmaktır

cl = cl.Trim(' ');

Bir dizedeki tüm boşlukları kaldırır


Birisi kullanmak istiyorsanız bu yararlıdır. '(' C ',' ') diğer boşlukları kaldırmanın dezavantajı ile değiştirin. Ama verilen diğer cevaplar çok daha yararlı.
Ocak

1
Hayır, bu yanlış! Trim sadece ortada olmayan bir dizenin başlangıcından ve sonundaki karakterleri kaldırır
userSteve
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.