Це популярне питання. Важливо зрозуміти, що задає автор питання, і чим він відрізняється від того, що, мабуть, є найпоширенішою потребою. Щоб відмовити від неправильного використання коду там, де він не потрібен, я відповів першим пізніше.
Загальна потреба
Кожна рядок має набір символів та кодування. Коли ви перетворюєте System.Stringоб'єкт у масив, у System.Byteвас все ще є набір символів та кодування. У більшості звичок ви знаєте, який набір символів та кодування вам потрібен, і .NET спрощує "копіювання з перетворенням". Просто виберіть відповідний Encodingклас.
// using System.Text;
Encoding.UTF8.GetBytes(".NET String to byte array")
Перетворення може потребувати обробки випадків, коли цільовий набір символів або кодування не підтримує символ, що знаходиться в джерелі. У вас є кілька варіантів: виняток, заміна або пропуск. Політикою за замовчуванням є заміна '?'.
// using System.Text;
var text = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes("You win €100"));
// -> "You win ?100"
Зрозуміло, що конверсії не обов'язково без втрат!
Примітка. Для System.Stringнабору символів джерелом є Unicode.
Єдина заплутана річ у тому, що .NET використовує ім'я набору символів для імені одного конкретного кодування цього набору символів. Encoding.Unicodeслід називати Encoding.UTF16.
Це все для більшості звичаїв. Якщо це те, що вам потрібно, перестаньте читати тут. Дивіться цікаву статтю Джоела Спольського, якщо ви не розумієте, що таке кодування.
Конкретна потреба
Тепер автор запитує: "Кожна рядок зберігається як масив байтів, так? Чому я просто не можу мати ці байти?"
Він не хоче перетворення.
Від специфікації C # :
Для обробки символів і рядків у C # використовується кодування Unicode. Тип char являє собою кодову одиницю UTF-16, а тип рядка являє собою послідовність кодових одиниць UTF-16.
Отже, ми знаємо, що якщо попросимо конвертувати нуль (тобто з UTF-16 в UTF-16), ми отримаємо бажаний результат:
Encoding.Unicode.GetBytes(".NET String to byte array")
Але щоб уникнути згадки про кодування, ми повинні зробити це іншим способом. Якщо проміжний тип даних прийнятний, для цього існує концептуальний ярлик:
".NET String to byte array".ToCharArray()
Це не дає нам потрібного типу даних, але відповідь Мехрдада показує, як перетворити цей масив Char у масив байтів за допомогою BlockCopy . Однак це копіює рядок двічі! І він занадто явно використовує специфічний для кодування код: тип даних System.Char.
Єдиний спосіб дістатися до фактичних байтів, в яких зберігається рядок, - це використовувати покажчик. fixedЗаява дозволяє приймати адреса значень. Від специфікації C #:
[Для] виразу рядка типу, ... ініціалізатор обчислює адресу першого символу в рядку.
Для цього компілятор записує код пропускання через інші частини об'єкта рядка RuntimeHelpers.OffsetToStringData. Отже, щоб отримати необроблені байти, просто створіть вказівник на рядок і скопіюйте кількість потрібних байтів.
// using System.Runtime.InteropServices
unsafe byte[] GetRawBytes(String s)
{
if (s == null) return null;
var codeunitCount = s.Length;
/* We know that String is a sequence of UTF-16 codeunits
and such codeunits are 2 bytes */
var byteCount = codeunitCount * 2;
var bytes = new byte[byteCount];
fixed(void* pRaw = s)
{
Marshal.Copy((IntPtr)pRaw, bytes, 0, byteCount);
}
return bytes;
}
Як вказував @CodesInChaos, результат залежить від витривалості машини. Але автор питання цим не займається.