.NET içinde karakter kodlaması

Bu makale, char .NET tarafından kullanılan acter kodlama sistemlerine giriş sağlar. Makalede, , String , ve türlerinin Char Rune StringInfo Unicode, UTF-16 ve UTF-8 ile nasıl çalışaları açıklanmıştır.

Burada char acter terimi, bir okuyucunun tek bir görüntüleme öğesi olarak algıladığı genel anlamda kullanılır. Yaygın örnekler arasında "a" harfi, "@" simgesi ve emoji " 🐂 ". Bazen grapheme kümelerinin bölümünde açıklandıklarından, bir eylemci aslında birden çok bağımsız char görüntü öğeden oluşur.

ve string char türleri

Sınıfın bir örneği string bazı metinleri temsil eder. , string mantıksal olarak 16 bitlik değerlerin dizisidir ve her biri yapının bir char örneğidir. . string Length özelliği char örnekteki örnek sayısını string döndürür.

Aşağıdaki örnek işlev, bir içinde yer alan tüm örneklerin onaltılı olarak char yer alan değerlerini string yazdırır:

string"Hello" ifadesini bu işleve iletir ve aşağıdaki çıkışı elde etmek için:

PrintChars("Hello");
"Hello".Length = 5
s[0] = 'H' ('\u0048')
s[1] = 'e' ('\u0065')
s[2] = 'l' ('\u006c')
s[3] = 'l' ('\u006c')
s[4] = 'o' ('\u006f')

Her char acter tek bir değerle temsil char edilen. Bu düzen, dünyanın dillerinin çoğu için geçerli olur. Örneğin, iki Çince eylemcinin çıkışı şu şekildedir: nǐ hǎo char merhaba:

PrintChars("你好");
"你好".Length = 2
s[0] = '你' ('\u4f60')
s[1] = '好' ('\u597d')

Ancak bazı diller ve bazı semboller ve emojiler için tek bir char acter'ı temsil etmek için iki char örnek gerekir. Örneğin, char Osage dilinde Osage anlamına gelen char sözcükte acter'ları ve örnekleri karşılaştırın:

PrintChars("𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟");
"𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟".Length = 17
s[0] = '�' ('\ud801')
s[1] = '�' ('\udccf')
s[2] = '�' ('\ud801')
s[3] = '�' ('\udcd8')
s[4] = '�' ('\ud801')
s[5] = '�' ('\udcfb')
s[6] = '�' ('\ud801')
s[7] = '�' ('\udcd8')
s[8] = '�' ('\ud801')
s[9] = '�' ('\udcfb')
s[10] = '�' ('\ud801')
s[11] = '�' ('\udcdf')
s[12] = ' ' ('\u0020')
s[13] = '�' ('\ud801')
s[14] = '�' ('\udcbb')
s[15] = '�' ('\ud801')
s[16] = '�' ('\udcdf')

Yukarıdaki örnekte, boşluk char dışında her bir eylemci iki örnekle temsil char edildi.

Aşağıdaki örnekte bir ox emojisini gösteren gibi tek bir Unicode emojisi char de iki s ile temsil ediliyor:

"🐂".Length = 2
s[0] = '�' ('\ud83d')
s[1] = '�' ('\udc02')

Bu örnekler, örnek sayısını gösteren değerinin görüntülenen eylemci sayısını string.Length char göstermey char olduğunu gösterir. Tek bir char örnek tek başına bir acter'ı temsil etmek zorunda char değildir.

Tek char bir acter ile eşilen char çiftlere vekil çiftler adı verilmektedir. Nasıl olduklarını anlamak için Unicode ve UTF-16 kodlamasını anlamalısınız.

Unicode kod noktaları

Unicode, çeşitli platformlarda ve çeşitli dillerde ve betiklerde kullanım için uluslararası bir kodlama standardıdır.

Unicode Standardı, 1,1 milyondan fazla kod noktası tanımlar. Kod noktası, 0 ile U+10FFFF (ondalık 1.114.111) arasında bir tamsayı değeridir. Bazı kod noktaları harflere, sembollere veya emojiye atanır. Diğerleri, metin veya eylemcilerin nasıl görüntülendiğinden (örneğin yeni satıra ilerleyin) char denetim altına alan eylemlere atanır. Birçok kod noktası henüz atanmamıştır.

Burada, görünen Unicode ts bağlantılarına sahip kod noktası char atamalarına bazı örnekler verilmiştir:

Ondalık Onaltılık Örnek Description
10 U+000A Yok SATıR BESLEME
97 U+0061 a LATIN KÜÇÜK HARF A
562 U+0232 Ȳ MAKRON ILE LATIN BÜYÜK HARFI Y
68,675 U+10C43 𐱃 ESKI EDIC LETTER ORKHON AT
127,801 U+1F339 🌹 ROSE emojisi

Kod noktaları, söz dizimi kullanılarak özel olarak U+xxxx adlandırılır; burada, altılık kodlanmış xxxx tamsayı değeridir.

Tüm kod noktaları aralığı içinde iki alt düzen vardır:

  • aralığındaki Temel Çok Dilde Düzlem (BMP). U+0000..U+FFFF Bu 16 bit aralık, dünyanın yazma sistemlerinin çoğunu kapsayacak kadar 65.536 kod noktası sağlar.
  • aralığındaki ek kod U+10000..U+10FFFF noktaları. Bu 21 bitlik aralık, daha az iyi bilinen diller ve emojiler gibi diğer amaçlar için kullanılan bir milyondan fazla ek kod noktası sağlar.

Aşağıdaki diyagramda BMP ile ek kod noktaları arasındaki ilişki göstermektedir.

BMP ve ek kod noktaları

UTF-16 kod birimleri

16 bit Unicode Dönüştürme Biçimi (UTF-16), Unicode kod noktalarını temsil etmek için 16 bit kod birimleri kullanan bir char eylemci kodlama sistemidir. .NET, bir içinde metni kodlamak için UTF-16 string kullanır. Örnek, char 16 bit kod birimini temsil eder.

Tek bir 16 bit kod birimi, Temel Çok Dilde Düzlemin 16 bit aralığındaki herhangi bir kod noktasını temsil ediyor olabilir. Ancak ek aralıkta bir kod noktası için iki char örnek gerekir.

Vekil çiftler

İki 16 bit değerin tek bir 21 bit değere çevirisi, vekil kod noktaları (ondalık U+D800 U+DFFF 55.296 ile 57.343) arasında adlı özel bir aralık tarafından kolaylaştırıldı.

Aşağıdaki diyagramda BMP ile vekil kod noktaları arasındaki ilişki göstermektedir.

BMP ve vekil kod noktaları

Yüksek yedek kod noktası ( ) hemen ardından düşük vekil kod noktası () geldiğinde, çift aşağıdaki formül kullanılarak ek kod noktası U+D800..U+DBFF olarak U+DC00..U+DFFF yorumlanır:

code point = 0x10000 +
  ((high surrogate code point - 0xD800) * 0x0400) +
  (low surrogate code point - 0xDC00)

Ondalık basamak kullanan formül şu şekildedir:

code point = 65,536 +
  ((high surrogate code point - 55,296) * 1,024) +
  (low surrogate code point - 56,320)

Yüksek yedek kod noktası, düşük yedek kod noktasından daha yüksek bir sayı değerine sahip değil. 20 bit kod noktası aralığının yüksek sıra 10 bitlerini hesaplamak için kullanılan yüksek yedek kod noktası "yüksek" olarak adlandırılan bir değerdir. Düşük yedek kod noktası, 10 bitlik düşük sırayı hesaplamak için kullanılır.

Örneğin, vekil çiftine karşılık gelen ve aşağıdaki gibi 0xD83C 0xDF39 hesaplanan gerçek kod noktası:

actual = 0x10000 + ((0xD83C - 0xD800) * 0x0400) + (0xDF39 - 0xDC00)
       = 0x10000 + (          0x003C  * 0x0400) +           0x0339
       = 0x10000 +                      0xF000  +           0x0339
       = 0x1F339

Ondalık basamak kullanılarak yapılan hesaplamanın aynısı şu şekildedir:

actual =  65,536 + ((55,356 - 55,296) * 1,024) + (57,145 - 56320)
       =  65,536 + (              60  * 1,024) +             825
       =  65,536 +                     61,440  +             825
       = 127,801

Yukarıdaki örnek, daha önce "\ud83c\udf39" bahsedilen kod noktasının UTF-16 U+1F339 ROSE ('🌹') kodlaması olduğunu gösteriyor.

Unicode skaler değerleri

Unicode skaler değeri terimi, vekil kod noktaları dışında tüm kod noktalarına başvurur. Başka bir deyişle skaler değer, bir acter atanmış veya gelecekte bir acter atanabilir herhangi char bir char kod noktasıdır. Burada "Karakter", bir kod noktasına atanabilir ve metin veya eylemcilerin nasıl görüntülenmiyor olduğunu kontrol altına alan eylemler gibi char şeyleri içerir.

Aşağıdaki diyagramda skaler değer kod noktaları göstermektedir.

Skaler değerler

RuneSkaler değer olarak tür

.NET Core 3.0'dan itibaren tür System.Text.Rune bir Unicode skaler değerini temsil eder. Rune.NET Core 2.x veya 4.x .NET Framework kullanılamaz.

RuneOluşturucular, sonuçta elde edilen örneğin geçerli bir Unicode skaler değer olduğunu doğrular, aksi takdirde bir özel durum oluştururlar. Aşağıdaki örnek, giriş geçerli skaler değerleri temsil ettiği Rune için örnekleri başarıyla örnekleyen kodu gösterir:

Aşağıdaki örnek bir özel durum oluşturur çünkü kod noktası vekil aralığındadır ve bir vekil çiftinin parçası değildir:

Kod noktası ek aralığın ötesinde olduğundan aşağıdaki örnek bir özel durum oluşturur:

Rune kullanım örneği: büyük/son harfi değiştirme

bir alan ve skaler değer olan bir kod noktasıyla çalıştığını varsayan BIR API, bir yedek çifti ise char char düzgün çalışmıyor. Örneğin, bir içinde her birini Char.ToUpperInvariant çağıran aşağıdaki yöntemi char string düşünün:

, input string küçük deseret harfini () içeriyorsa, bu er kod büyük 𐑉 harfe ( ) 𐐡 dönüştürmez. Kod, her char.ToUpperInvariant vekil kod noktasında ve üzerinde ayrı U+D801 U+DC49 çağrılar. Ancak tek başına küçük harf olarak tanımlamak için yeterli bilgiye sahip değildir, bu nedenle U+D801 char.ToUpperInvariant tek başına bırakır. Ayrıca aynı U+DC49 şekilde işlemeye de devam ediyor. Sonuç olarak, içinde '𐑉' küçük harf '𐐡' büyük input string harfe 𐐡.

Bir büyük harfe doğru şekilde dönüştürmek için iki string seçenek şunlardır:

  • String.ToUpperInvariant-by- string iterating yerine char girişte çağrısı. char Yöntemin string.ToUpperInvariant her yedek çiftinin her iki parçasına da erişimi vardır, bu nedenle tüm Unicode kod noktalarını doğru şekilde işebilir.

  • Aşağıdaki örnekte gösterildiği gibi Unicode skaler değerlerini örnekler yerine Rune char örnek olarak yeniden deneyin. Örnek geçerli bir Unicode skaler değer olduğundan, skaler değer üzerinde çalışması bekilen Rune API'lere geçiril olabilir. Örneğin, aşağıdaki Rune.ToUpperInvariant örnekte gösterildiği gibi çağrısı doğru sonuçlar verir:

Diğer Rune API'ler

türü Rune çoğu API'nin analoglarını char ortaya çıkarır. Örneğin, aşağıdaki yöntemler statik API'leri türe char yansıtıyor:

Bir örnekten ham skaler değeri Rune almak için özelliğini Rune.Value kullanın.

Bir örneği Rune bir diziye geri dönüştürmek char için veya yöntemini Rune.ToString Rune.EncodeToUtf16 kullanın.

Herhangi bir Unicode skaler değeri tek bir veya bir vekil çiftle temsil edilebilir olduğu için, herhangi bir örnek en fazla char Rune 2 char örnekle temsil edilebilir. Bir Rune.Utf16SequenceLength örneği temsil etmek için kaç örneğin gerekli olduğunu görmek için char Rune kullanın.

.NET türü hakkında daha fazla Rune bilgi için bkz. Rune API başvurusu.

Grapheme kümeleri

Bir acter birden çok kod noktası birleşiminden kaynaklansa da genellikle "acter" yerine kullanılan daha açıklayıcı bir terim char char grapheme kümesidir. .NET'te eşdeğer terim, metin öğesidir.

string"a", "á", "á" ve " örneklerini 👩🏽‍🚒 düşünün. İşletim sisteminiz bunları Unicode standardı tarafından belirtilen şekilde ele alıyorsa, bu örneklerin her biri tek bir metin öğesi veya string grapheme kümesi olarak görünür. Ancak son ikisi birden fazla skaler değer kod noktasıyla temsil edildi.

  • string"a", bir skaler değerle temsil edilen ve bir örnek char içerir.

    • U+0061 LATIN SMALL LETTER A
  • string"á", bir skaler değerle temsil edilen ve bir örnek char içerir.

    • U+00E1 LATIN SMALL LETTER A WITH ACUTE
  • "á", "á" ile aynı görünüyor ancak iki skaler değerle temsil string edildi ve iki örnek char içeriyor.

    • U+0061 LATIN SMALL LETTER A
    • U+0301 COMBINING ACUTE ACCENT
  • Son olarak string , " " dört 👩🏽‍🚒 skaler değerle temsil eder ve yedi char örnek içerir.

    • U+1F469 WOMAN (ek aralık, vekil çift gerektirir)
    • U+1F3FD EMOJI MODIFIER FITZPATRICK TYPE-4 (ek aralık, vekil çift gerektirir)
    • U+200D ZERO WIDTH JOINER
    • U+1F692 FIRE ENGINE (ek aralık, vekil çift gerektirir)

Önceki örneklerden bazılarında (bir araya gelen vurgu değiştiricisi veya dış görünüm değiştiricisi gibi) kod noktası ekranda tek başına öğe olarak görüntülenmez. Bunun yerine, önünde gelen bir metin öğesinin görünümünü değiştirmeye hizmet verir. Bu örnekler, tek bir " acter" veya "grapheme kümesi" olarak kabul etmek için birden çok skaler değer char gerektirebileceklerini gösterir.

bir grapheme kümelerini listeley string için, aşağıdaki StringInfo örnekte gösterildiği gibi sınıfını kullanın. Swift'i biliyorsanız . NET türü StringInfo kavramsal olarak Swift'in türüne character benzer.

Örnek: char count Rune , ve text element instances

.NET API'lerde grapheme kümesine metin öğesi adı ve verir. Aşağıdaki yöntem, bir içinde char , ve metin öğesi örnekleri arasındaki Rune farkları string gösteriyor:

Bu kodu .NET Framework .NET Core 3.1 veya önceki bir sürümde çalıştırdıysanız emojinin metin öğesi sayısı olarak 4 gösterir. Bunun nedeni StringInfo sınıfındaki .NET 5'te düzeltilen bir hatadır.

Örnek: string örnekleri bölme

Örnekleri string bölerken vekil çiftleri ve grapheme kümelerini bölmekten kaçının. Bir içinde her 10 eylemciye satır sonu eklemek için aşağıdaki yanlış char kod örneğini göz önünde bulundurabilirsiniz: string

Bu kod örnekleri numaralandırı olduğundan, 10 sınırı katmana bölen bir vekil çift bölünecek ve bunlar arasına char char yeni bir satır gelecektir. Vekil kod noktaları yalnızca çift olarak anlamlı olduğundan, bu ekleme veri bozulmasına neden olur.

Örnekler yerine örnekleri (skaler değerler) numaralarsanız veri bozulması potansiyeli Rune ortadan char kaldırılmış değildir. Bir dizi Rune örnek, 10 sınırı katmana alan bir grapheme kümesi char oluşturur. Grapheme kümesi bölünmüşse, doğru yorumlandırılemez.

Aşağıdaki örnekte olduğu gibi grapheme kümelerini veya metin öğelerini sayarak bunu bozmak string daha iyi bir yaklaşımdır:

Ancak daha önce belirtildiği gibi , .NET 5 dışında .NET uygulamaları için sınıf bazı StringInfo grapheme kümelerini yanlış işleyebilir.

UTF-8 ve UTF-32

Yukarıdaki bölümlerde UTF-16'ya odaklanmıştık çünkü .NET örnekleri kodlamak için bunu string kullanır. Unicode için başka kodlama sistemleri de vardır : UTF-8 ve UTF-32. Bu kodlamalar sırasıyla 8 bit kod birimlerini ve 32 bit kod birimlerini kullanır.

UTF-16 gibi UTF-8 de bazı Unicode skaler değerleri temsil etmek için birden çok kod birimi gerektirir. UTF-32, tek bir 32 bit kod biriminde herhangi bir skaler değeri temsil ediyor olabilir.

Aynı Unicode kod noktasının bu üç Unicode kodlama sistemi içinde nasıl temsil olduğunu gösteren bazı örnekler aşağıda verilmiştir:

Scalar: U+0061 LATIN SMALL LETTER A ('a')
UTF-8 : [ 61 ]           (1x  8-bit code unit  = 8 bits total)
UTF-16: [ 0061 ]         (1x 16-bit code unit  = 16 bits total)
UTF-32: [ 00000061 ]     (1x 32-bit code unit  = 32 bits total)

Scalar: U+0429 CYRILLIC CAPITAL LETTER SHCHA ('Щ')
UTF-8 : [ D0 A9 ]        (2x  8-bit code units = 16 bits total)
UTF-16: [ 0429 ]         (1x 16-bit code unit  = 16 bits total)
UTF-32: [ 00000429 ]     (1x 32-bit code unit  = 32 bits total)

Scalar: U+A992 JAVANESE LETTER GA ('ꦒ')
UTF-8 : [ EA A6 92 ]     (3x  8-bit code units = 24 bits total)
UTF-16: [ A992 ]         (1x 16-bit code unit  = 16 bits total)
UTF-32: [ 0000A992 ]     (1x 32-bit code unit  = 32 bits total)

Scalar: U+104CC OSAGE CAPITAL LETTER TSHA ('𐓌')
UTF-8 : [ F0 90 93 8C ]  (4x  8-bit code units = 32 bits total)
UTF-16: [ D801 DCCC ]    (2x 16-bit code units = 32 bits total)
UTF-32: [ 000104CC ]     (1x 32-bit code unit  = 32 bits total)

Daha önce belirtildiği gibi, bir vekil çiftten tek bir UTF-16 kod birimi tek başına anlamsızdır. Aynı şekilde, tek bir UTF-8 kod birimi skaler değeri hesaplamak için kullanılan iki, üç veya dört sıralı ise tek bir UTF-8 kod birimi kendisi için anlamsızdır.

Endianness

.NET'te, bir'in UTF-16 kod birimleri, 16 bit tamsayılar ( örnekler) dizisi olarak bitişik string char bellekte depolanır. Tek tek kod birimlerinin bitleri, geçerli mimarinin sonluluğuna göre ortaya çıkar.

Küçük bir endian mimarisinde, UTF-16 kod noktalerinden oluşan değeri, bayt olarak string [ D801 DCCC ] belleğe [ 0x01, 0xD8, 0xCC, 0xDC ] konabilir. Aynı büyük endian mimarisinde string bayt olarak belleğe atılacaktır. [ 0xD8, 0x01, 0xDC, 0xCC ]

Birbirleriyle iletişim kuran bilgisayar sistemleri, kablodan geçen verilerin temsili üzerinde fikir birliği olmalıdır. Çoğu ağ protokolü, metin iletilirken standart olarak UTF-8 kullanır ve kısmen küçük endian makinesiyle iletişim kuran büyük endian makinelerinden kaynaklanmayacak sorunları önlemek için kullanılır. UTF-8 kod noktalerinden oluşan, endianness ne olursa olsun her zaman bayt string [ F0 90 93 8C ] olarak temsil [ 0xF0, 0x90, 0x93, 0x8C ] eder.

.NET uygulamaları, metin ileterek UTF-8'i kullanmak için genellikle aşağıdaki örnekte olduğu gibi kod kullanır:

string stringToWrite = GetString();
byte[] stringAsUtf8Bytes = Encoding.UTF8.GetBytes(stringToWrite);
await outputStream.WriteAsync(stringAsUtf8Bytes, 0, stringAsUtf8Bytes.Length);

Önceki örnekte Encoding.UTF8.GetBytes yöntemi UTF-16 kodunu bir Unicode skaler değer dizisine geri döndürür, ardından bu string skaler değerleri UTF-8'e yeniden kodlar ve sonuçta elde edilen diziyi bir diziye byte yer verir. Encoding.UTF8.GetString yöntemi, bir UTF-8 dizisini byte UTF-16'ya dönüştürerek ters dönüştürmeyi string gerçekleştirir.

Uyarı

UTF-8 İnternet'te sıradan bir yer olduğu için, kablodan ham baytları okumak ve verileri UTF-8 gibi ele almak cazip olabilir. Ancak, gerçekten de iyi oluşturulmuş olduğunu doğrulamalı. Kötü amaçlı bir istemci, hizmetinize yanlış UTF-8 göndermektedir. Bu veriler üzerinde iyi oluşturulmuş gibi çalışırsanız, uygulamanıza hata veya güvenlik deliklerine neden olabilir. UTF-8 verilerini doğrulamak için, gelen verileri bir 'ye dönüştürürken doğrulama gerçekleştirecek Encoding.UTF8.GetString gibi bir yöntem string kullanabilirsiniz.

İyi formed kodlaması

İyi formed Unicode kodlaması, belirsiz ve hatasız bir şekilde Unicode skaler değerler dizisine çözülen kod string birimleridir. İyi oluşturulmuş veriler UTF-8, UTF-16 ve UTF-32 arasında serbestçe ve ileri geri koda sızabilirsiniz.

Bir kodlama dizisinin iyi biri olup olmadığı sorusu, bir makinenin mimarisinin endianlığıyla ilgili değildir. Kötü oluşturulmuş bir UTF-8 dizisi hem büyük endian hem de küçük endian makinelerde aynı şekilde kötü oluşturulmuştur.

Aşağıda, kötü oluşturulmuş kodlamalara bazı örnekler verilmiştir:

  • UTF-8'de, sırası tarafından [ 6C C2 61 ] izlenilenemay nedeniyle C2 kötü 61 oluştu.

  • UTF-16'da, düşük vekil başka bir düşük vekil tarafından izleneyeneden dizi (veya C# içinde ) kötü [ DC00 DD00 ] string "\udc00\udd00" DC00 DD00 oluşur.

  • UTF-32'de, Unicode skaler değer aralığının dışında olduğundan dizi [ 0011ABCD ] 0011ABCD kötü oluşur.

.NET'te örnekler neredeyse her zaman iyi string UTF-16 verileri içerir, ancak bu garanti edilemez. Aşağıdaki örnekler, örneklerde kötü utF-16 verileri oluşturan geçerli C# string kodunu gösterir.

  • Kötü oluşturulmuş bir değişmez:

    const string s = "\ud800";
    
  • Yedek string çifti bölen bir alt:

    string x = "\ud83e\udd70"; // "🥰"
    string y = x.Substring(1, 1); // "\udd70" standalone low surrogate
    

gibi Encoding.UTF8.GetString API'ler hiçbir zaman kötü sıyrı string olmayan örnekler dönmez. Encoding.GetString ve Encoding.GetBytes yöntemleri, girişte kötü oluşturulmuş dizileri algılar ve char çıktıyı oluştururken acter değiştirme işlemi gerçekleştirin. Örneğin, girişte ASCII olmayan bir baytı Encoding.ASCII.GetString(byte[]) görüyorsa (U+0000..U+007F aralığının dışında), döndürülen örneğine bir '?' string ekler. Encoding.UTF8.GetString(byte[]) , döndürülen örnekteki kötü UTF-8 U+FFFD REPLACEMENT CHARACTER ('�') dizilerini ile string değiştirir. Daha fazla bilgi için bkz. Unicode Standardı,Bölüm 5.22 ve 3.9.

Yerleşik sınıflar, kötü oluşturulmuş diziler görülürken eylem değiştirme gerçekleştirmek yerine bir özel durum atacak Encoding char şekilde de yalıtabilirsiniz. Bu yaklaşım genellikle eylemci değiştirmenin kabul edilemey char olabileceği güvenlik duyarlı uygulamalarda kullanılır.

byte[] utf8Bytes = ReadFromNetwork();
UTF8Encoding encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
string asString = encoding.GetString(utf8Bytes); // will throw if 'utf8Bytes' is ill-formed

Yerleşik sınıfları kullanma hakkında bilgi için bkz. Encoding char .NET'te acter kodlama sınıflarını kullanma.

Ayrıca bkz.