C#. Удаление значений (values) из ключа Реестра

Преамбула

Задача довольно простая, имеется ключ в разделе Реестра Windows, необходимо удалить оттуда все значения (values).

Термины и определения

Реестр — иерархическая база данных, хранящая основные настройки системы и программ.
Корневой ключ (в некоторых источниках просто ключ или раздел Реестра), это один из основных ключей Реестра. Обычно присутствуют следующие:

HKEY_CLASSES_ROOT (HKCR) — Зарегистрированные типы файлов, объекты COM и ActiveX
HKEY_CURRENT_USER (HKCU) — Настройки текущего пользователя, в данный момент вошедшего в систему.
HKEY_LOCAL_MACHINE (HKLM) — Общие настройки для всех пользователей данного компьютера.
HKEY_USERS (HKU) — Профили всех пользователей данной машины.
HKEY_CURRENT_CONFIG (HKCC) — Профили оборудования, информация о драйверах.

Подключ/Subkey (иногда Ключ, если корневой раздел называется корневым разделом или корневым ключом) Реестра — путь в Реестре, аналогичный пути к каталогу (папке) файловой системы. Обычно каждый подключ хранит или настройки для конкретного случая. Например, настройки конкретной программы или профиль конфигурации оборудования. Выглядит примерно так: Software\TestKey (в полном виде, вместе с корневым ключом, например: HKEY_CURRENT_USER\Software\TestKey).

Подключ может содержать как и другие подключи, так и значения (values), представляющие собой поименованные переменные, содержащие значения конкретного параметра

Обзорная статья про Реестр Windows на Википедии

Тестовый ключ

Для тестирования создадим тестовый ключ, который не будет влиять на какие либо программы и компоненты ОС. Это можно сделать, как вручную, с помощью программы Regedit, так и в автоматическом режиме, с помощью reg-файла, например, такого:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\TestKey]
"value0"="text0"
"value1"="text1"
"value2"="text2"
"value3"="text3"
"value4"="text4"
"value5"="text5"

Файл на GitHub

Можно создать и reg-файл для удаления тестового ключа из Реестра, если что-то пойдет не так:

Windows Registry Editor Version 5.00

[-HKEY_CURRENT_USER\Software\TestKey]

Файл на GitHub

Решение

1. Подключаем пространство имен Microsoft.Win32:

using Microsoft.Win32;

2. Создаем переменную с именем подключа Реестра и переменную типа RegistryKey. Этот объект и будет рулить нужной веткой Реестра:

string subkey = "Software\\TestKey";
RegistryKey key = null;

3. Любые операции с Реестром могут привести к ошибкам, потому их как и операции ввода-вывода желательно оборачивать в try..catch:

try
{
    //тут будет код.
}
catch (Exception ex)
{
    Console.WriteLine("ERROR: " + ex.Message);
}

4. Открываем (под)ключ Реестра:

key = Registry.CurrentUser.OpenSubKey(subkey, true);

Внимание! Если необходимо писать в ключ Реестра, обязательно устанавливаем второй параметр функции OpenSubKey в true, т.к. в противном случае, мы получим ошибку UnauthorizedAccessException: Не удалось выполнить запись в раздел реестра.

Обсуждение на Cyberforum

5. Получить список значений в (под)ключе можно функцией GetValueNames(), которая выдает строковый массив с именами значений Реестра.

6. Получаем имена всех значений и в цикле удаляем их с помощью функции DeleteValue(имя_параметра);

foreach (string valname in key.GetValueNames())
{
    Console.WriteLine("Delete value: " + valname);
    key.DeleteValue(valname);
}

7. Закрываем (под)ключ Реестра.

key.Close();

Все получилось:

Код целиком

На PasteBin

Тестовый пример

Пример на GitHub

C#, генератор файлов (нужного количества и с определенным содержимым).

Описание задачи

Итак, требуется написать программу, которая генерирует заданное количество файлов с определенным содержимым. Содержимое задается или в качестве байтового паттерна (т.е. если программе указать 0xFF, то файл будет заполнен указанным количеством байт со значением 0xFF) или случайных байт. Файлам также можно задать расширение, или сделать и имя файла случайным.

Программа

Выполнена в виде консольной программы, запускаемой со следующими параметрами:

Использование: filegen.exe <количество_файлов> <размер>[K|M|G] <расширение|/R> [байтовый_паттерн|/R]

<количество_файлов> - количество файлов
<размер> - размер:

   по умолчанию - байты
   K - килобайты
   M - мегабайты
   G - гигабайты

<расширение> - расширение файла или /R - случайное имя файла
[байтовый_паттерн] - байтовый паттерн (HEX): от 0x00 до 0xFF, по умолчанию 0x00 или /R случайные байты

Использованные алгоритмы

1. С#, Заполнение массива одним значением. (копия)
2. C#, заполнение массива случайными числами. (копия)
3. C#, Количество цифр (разрядов) числа. (копия)
4. C#. Перевод кило- мега- и гигабайтов в байты. (копия)

Пример программы

На GitHub

C#. Перевод кило- мега- и гигабайтов в байты

Преамбула

Простая учебная задача, но почему-то до моего решения долюбились, в конце объясню, почему долюбились, и почему, в случае C#, это зря было.

Решение

И так, задача состоит в том, чтобы всякие кратные единицы перевести в байты (кому надо обратную задачу, либо все во все — пишите в комментарии). Для этого достаточно сделать следующую функцию, исходя из того, что 1 Кб == 1024 Б, 1 Мб = 1024 Кб, 1 Гб = 1024 Мб. В функцию добавим некую переменную-модификатор, для консольного приложения было проще сделать строковую, в ином случае, может и есть сделать отдельный Enum для единиц, но я обошелся строковой.
Переменная-модификатор (modificator) принимает строковые значения G(g), M(m) и K(k), соответственно для гига- мега- и килобайта.

Функция получается такая:

public static ulong ToBytes(ulong bytes, string modificator)
{
    ulong Ret = 0;
    switch (modificator)
    {
        case "":
            {
                Ret = bytes;
            } break;
        case "K":
        case "k":
            {
                Ret = bytes * 1024;
            } break;
        case "M":
        case "m":
            {
                Ret = bytes * 1024 * 1024;
            } break;
        case "G":
        case "g":
            {
                Ret = bytes * 1024 * 1024 * 1024;
            } break;
        default:
            {
                throw new ArgumentException("Wrong modificator ["
                    + modificator + "]. Set K(k), M(m), G(g)");
            }                    
    }

    return Ret;
}

Почему не стал заморачиваться с Enum’ом

Задача была очень простая, чисто учебная. Консольная программа принимает в качестве одного параметра число с единицей без пробела, т.е. команда вида program.exe 10G, должна вывести количество байт. Надо ли Enum городить, ну красиво было бы, но до Enum‘ов они не добрались 🙂

В основной программе надо отрезать последний символ из параметра, проверить ли является он нужной буквой (K/M/G) и пересчитать. Если буквы нету, а только цифры — значит оно уже сразу байты.

В функции Main() отрезаем последний символ от первого параметра командной строки, если он K/M/G, считаем, что все остальное число, отрезаем его, а все остальное пытаемся сконвертировать в ulong (Int64) и передать функции ToBytes() с отрезанным символом, как модификатором для расчета. Если нет — просто считаем, что вся строка число, пытаемся конвертировать, а функции передаем пустой модификатор.

Ошибки конвертации ловим try/catch:

string size_s = args[1];

try
{
    string mdf = size_s.Substring(size_s.Length - 1, 1);
    if ((mdf != "K") && (mdf != "k") && (mdf != "M") && (mdf != "m") &&
        (mdf != "G") && (mdf != "g"))
    {
        mdf = "";
        //in parameter only numbers or param wrong...
    }
    else // remove modificator
    {
        size_s = size_s.Substring(0, size_s.Length - 1);
    }
    BytesCount = ToBytes(Convert.ToUInt64(size_s), mdf);
}
catch (Exception ex)
{
    Console.WriteLine("Wrong <size> parameter!");
    Console.WriteLine(ex.Message);
    Console.Write("Press Enter...");
    Console.ReadLine();
    return 2;
}

Пример целиком на GitHub

Почему долюбились

За вот эти вот конструкции:

Ret = bytes * 1024;
Ret = bytes * 1024 * 1024;
Ret = bytes * 1024 * 1024 * 1024;

Типа «ну тут числа, ты бы их сначала перемножил, результат записал , а потом на переменную помножил».

Почему зря.

Дебилы, бля, как говорил Лавров. В интерпретируемых языках или старом Трупопоскакале под DOS, может это и какой-то рояль играет, но в C# компилятор перемножает константы до сборки экзешника, а 1024*1024*1024 для компилятора константы, во время компиляции. Т.е. процессору скормят 1073741824. А код останется более понятен и читабелен.

Наконец понял, почему устьподзалупинский (маськовский) суд запрещает аниме «Инуясики» (или «Инуяшики»)

Аниме, так-то про пенсионера, который в результате несчастного случая с НЛО, получает новое тело и превращается в боевого робота. Правда вместе с ним, такие же способности получает и омежка, которым в детстве был известный всем Владимир Таврический Хуйло.

Хуйло начинает валить всех направо и налево, руководствуясь принципом: «друзьям все — остальным пиздец», так что от него даже друг сваливает (это прямо предсказание, запомните этот твит). Причем валит даже не по делу, а ради удовольствия.

А Дед, он воюет со злом, пиздит гопников, выпиливает бандитов, да и охотится за Хуйлом (правда, весьма вяло).

Понятно, что такое молодежи показывать нельзя.

Попробуй этому пенсионеру повысить пенсионный возраст, скажет ведь: «То, что вы делаете, недостойно» — и развесит по фонарям и ПФ РФ, и роскрысдию и ФСО.
Тем более, уничтожил самую крутую банду нараёне, как так-то? Прямая отсылка к самой крутой банде в ГОРФ, т.е. к нашему, а не анимешному Хуйлу и его друзьям-подхуйловникам.
Ну и, естественно, японцы, того не желая, наступили на мантру пропаганды всея ГОРФ — «Деды Воевали»!

Нельзя показывать, ну никак нельзя.

ЗЫ. Гей-секс там был, но исключительно в негативной коннотации, как отношения между старшим бандитом и подчиненным. Хотя и это, наверное, задело зоновский роскомсуд, т.к. такой гей-секс в ГОРФ вполне разрешен. А его тут с негативной стороны показывают.

ЗЗЫ. Антагонист, впрочем, тоже сделал полезную вещь, хотя и в стиле роскомнадзора — перебил кучу анонов с местного двача. А потом даже исправился и помог планету спасти.

Ничего Хорошего Молотов Коктейль (Nothing Good — Molotov)

Запретили песенку на территории ГОРФ, ублюдки сраные из роскомговна. По поводу нам скидывали интервью Барта, фронтмена группы «Ничего хорошего», но оно безблагодатно проебано куда-то, тяжко иметь 40+ аккаунтов в соцсетях, и потом разобраться, где с кем переписывался.

Прямая ссылка: https://www.youtube.com/watch?v=RLV53ix4GVM

Текст

Под катом

C#, добавление лидирующих нолей к строковому представлению числа, более оптимальный способ.

Преамбула

Здесь (копия) я показал довольно неоптимальный способ решения данной задачи, но его можно оптимизировать с помощью стандартных функций. Напомню суть задачи: даны числа, скажем, от 1 до 1000, необходимо вывести их на экран или в файл последовательно, добавив лидирующие ноли, исходя из максимального числа. Если максимум 1000, то числа должны быть выведены так:
0001
0002
0003
...
0100
0101
0102
...
1000

Если максимум 100, то:

001
002
...
099
100

Подготовка

Как и в предыдущей версии решения, понадобится задать максимальное число (в тестовых примерах опять же, зададим его статически), например:

int maxnum = 150;

И опять же, понадобится функция, вычисляющая количество цифр (разрядов) числа (копия). Например, такая:

static int CountDigitsRec(int n)
{
    n = (int)Math.Abs(n);
    if (n <= 9)
    {
        return 1;
    }
    else
    {
        return CountDigitsRec(n / 10) + 1;
    }
}

Форматирование строки

C# автоматически умеет форматировать строки, используя специальные паттерны описания формата, задаваемые в виде строки. Основные паттерны перечислены в таблице ниже:

C / c Задает формат денежной единицы, указывает количество десятичных разрядов после запятой
D / d Целочисленный формат, указывает минимальное количество цифр
E / e Экспоненциальное представление числа, указывает количество десятичных разрядов после запятой
F / f Формат дробных чисел с фиксированной точкой, указывает количество десятичных разрядов после запятой
G / g Задает более короткий из двух форматов: F или E
N / n Также задает формат дробных чисел с фиксированной точкой, определяет количество разрядов после запятой
P / p Задает отображения знака процентов рядом с число, указывает количество десятичных разрядов после запятой
X / x Шестнадцатеричный формат числа

Для форматирования строки, содержащей целое число, необходимо использовать паттерн d.

Форматирование во время вывода строки на консоль.

Отформатировать строку можно сразу во время вывода на консоль, функцией Console.Write()/Console.WriteLine():

int num = 125
Console.Write ("0:d4", num) //вывод: 0125

или

int num = 25
Console.Write ("0:d4", num) //вывод: 0025

Пример:

static void Main(string[] args)
{
    int maxnum = 150;
    string FormatPattern = "{0:d" + 
        CountDigitsRec(maxnum).ToString() + "}";

    for (int i = 0; i <= maxnum; i++)
    {
        Console.WriteLine(FormatPattern, i);
    }

    Console.WriteLine("Press Enter...");
    Console.ReadLine();
}

Пример на GitHub

Использование String.Format()

Функция String.Format() может сделать аналогичную операцию, но отличается тем, что вывод функции можно сохранить в строковую переменную и использовать далее, а не просто вывести на консоль.

Пример:

static void Main(string[] args)
{
    int maxnum = 1150;
    string FormatPattern = "{0:d" +
        CountDigitsRec(maxnum).ToString() + "}";
    string TempFile = Path.GetTempFileName();
    string Result = "";
    List<string> WriteList = new List<string>();

    for (int i = 0; i <= maxnum; i++)
    {
        Result = String.Format(FormatPattern,i);
        Console.WriteLine(Result);
        WriteList.Add(Result);
    }

    File.WriteAllLines(TempFile, WriteList.ToArray());

    Console.WriteLine("Test file: " + TempFile);
    Console.WriteLine("Press Enter...");
    Console.ReadLine();
}

В цикле результат работы функции String.Format() возвращается в переменную Result, значение которой выводится на консоль и сохраняется в List<string> WriteList для дальнейшей записи в файл.

Пример на GitHub

Примечание: в источнике есть еще варианты форматирования строк, ознакомьтесь.

Источник

Форматирование и интерполяция строк (копия на mega.nz, PDF)

Неологизм, рожденный замечательной опечаткой.

Накрымлся

Пример: «Ваш проект накрымлся кремлевской звездой!»

Накрымлось

Пример: «Всё общество поддержки Путина на Западе полностью накрымлось после нового расследования Bellingcat.»

Проклятый старый комп (еще одна пародия на КиШ)

В локальной сети
Стоит старинный комп,
Закрыт весь доступ,
Пароль висит большой на нем.

Сказать я пытался
Троянов нет на компе,
Но тут же раздался,
Ужасный голос в винде

Голос в Винде…
[Визг свиньи Касперского]

Мне больно видеть Интернет,
Скорей бы отключить вас всех.
Я очень много много лет
Мечтаю о крутом компе

Мне слишком тесно на XP
И я мечтаю об одном,
Скорей пароль свой поломать,
Проникнуть в какдый каждый комп!

Будь проклят каждый комп!

Был вирус в БИОС,
Крутой и жутко злой
Админ не понял
Как комп спасти от заразы той.

Админы не стали
Тогда харддиск форматить
Пароли поставив, решили пива попить,
И забухали…

Мне больно видеть Интернет,
Скорей бы отключить вас всех.
Я очень много много лет
Мечтаю о крутом компе

Мне слишком тесно на XP
И я мечтаю об одном,
Скорей пароль свой поломать,
Проникнуть в какдый каждый комп!

Будь проклят каждый комп!

И это место стороной
Обходит нетский люд,
И антивирусы твердят —
Там вирусы живут!

C#, добавление лидирующих нолей к строковому представлению числа.

Преамбула

Задача опять же учебная, но может пригодиться и в реальной программе. Итак, нам даны числа, скажем, от 1 до 1000, необходимо вывести их на экран или в файл последовательно, добавив лидирующие ноли, исходя из максимального числа. Если максимум 1000, то числа должны быть выведены так:
0001
0002
0003
...
0100
0101
0102
...
1000

Если максимум 100, то:

001
002
...
099
100

Решение

Нам понадобится максимальное число, в тестовом примере мы его жестко зададим:

int maxnumber = 1998;

Далее, понадобится получить количество цифр числа. Это мы уже делали, причем разными способами (копия), выбираем подходящий.

Создаем отдельный класс (в примере AddLZ) и добавляем туда функцию:

public static int CountDigitsRec(int n)
{
    n = (int)Math.Abs(n);
    if (n <= 9)
    {
        return 1;
    }
    else
    {
        return CountDigitsRec(n / 10) + 1;
    }
}

В основной программе получаем количество цифр числа:

int maxdigits = AddLZ.CountDigitsRec(maxnumber);

Далее в цикле перебираем все числа, и скармливаем их функции, которая будет добавлять лидирующие ноли (AddLZ.AddLeaderZeroString(maxdigits, i));

for (int i = 0; i <= maxnumber ; i++)
{
    string Result = AddLZ.AddLeaderZeroString(maxdigits, i);
    //...
}

На вход функции подается два параметра — максимальное количество цифр и текущее число.

Внутри функции

Получаем строковое представление текущего числа:

string scurnum = ((int)Math.Abs(curnum)).ToString();

Получаем длину строки из лидирующих нолей, которая должна быть равна количеству цифр максимального числа, минус длина (количество цифр) текущего числа. Оно получено выше.

int LenLZ = maxnum - scurnum.Length;

Далее, надо сформировать строку нужной длины из одного символа ('0') (копия):

StringBuilder sb = new StringBuilder(maxnum);
for (int i = 0; i < LenLZ; i++)
{
    sb.Append('0');
}

Далее добавляем строковое представление текущего числа:

sb.Append(scurnum);

И возвращаем значение:

return sb.ToString();

Функция целиком

public static string AddLeaderZeroString(int maxnum, int curnum)
{
    string scurnum = ((int)Math.Abs(curnum)).ToString();
    int LenLZ = maxnum - scurnum.Length;

    StringBuilder sb = new StringBuilder(maxnum);
    for (int i = 0; i < LenLZ; i++)
    {
        sb.Append('0');
    }
    sb.Append(scurnum);

    return sb.ToString();
}

Исходники

Тестовый пример на GitHub
Класс AddLZ

Карельские коты получили книгу Алины Витухновской

Завтра приедет котокурьер из милой котокомпании и доставит книжку заказчику и котам из ЮВА. Котокомпанию нам рекламировать нельзя, т.к. права такого не имею. Но доставляют быстро, 15 рабочих дней максимум по всему миру. Карельские коты им делали сайт, так что у них кроме гонорара еще три промокода на бесплатную доставку по всей планете. Уже два.

C#, сгенерировать строку нужной длины из одного символа.

Преамбула

Продолжаем задачки по генерации всяких паттернов. Недавно мы генерировали массив, заполненный одним значением (копия). Теперь будем генерировать строку из одного символа, но нужной длины. Строку из случайных символов мы уже делали

Теперь будем делать строку-паттерн из одного заранее заданного символа.

Заведем три переменных:

int strlen = 100000; // длинна строки
string symbol = "a"; // символ заполнения
string Result = ""; // результирующая строка

«В лоб», с использованием стандартной конкатенации строк

Т.е. в цикле for, используя конструкцию s=s+"a":

for (int i = 0; i < strlen; i++)
{
    Result = Result + symbol;
}

С использованием StringBuilder

StringBuilder sb = new StringBuilder(strlen);
for (int i = 0; i < strlen; i++)
{
    sb.Append(symbol);
}

Result = sb.ToString();

Тесты

For + standart string concatenation: 00:00:05.7493288
Test For + StringBuilder.Append: 00:00:00.0030001

Даже на 10000 символов видна разница, здесь показана на 100000, а 500000 для for я вообще не дождался.

Примечание: Тут мы делали строку заданной длины из одного паттерна, поэтому StringBuilder был уместен, т.к. он напрямую работает с памятью, и не использует механизм .NET, которому нужно строку скопировать, а потом добавить символ. См. ссылку ниже.

Эффективная конкатенация строк в .NET

Тестовый пример на GitHub

C#, Количество цифр (разрядов) числа.

Пост из серии «спрашивали — отвечаем», довольно стандартная учебная задача, никакой особой военной хитрости нет, но раз уж, что б нет то.

Преобразование числа в строку и подсчет символов

Самый простой, дубовый, но самый медленный по времени выполнения способ. Обычно в школе за него по рукам бьют 🙂

static int CountDigitsStr(int n)
{
    return ((int)Math.Abs(n)).ToString().Length;
}

Получаем модуль числа [(int)Math.Abs(n)], чтоб исключить ситуацию, если в n окажется отрицательное число, преобразуем число в строку и получаем количество символов в строке, т.е. количество цифр числа.

Подсчет цифр делением нацело

Способ заключается в том, чтобы последовательно делить число на 10, оставляя от деления целую часть, пока целая часть не станет равна 0.

Можно сделать в двух вариантах.

В цикле:

static int CountDigitsCycle(int n)
{
    n = (int)Math.Abs(n); //берем модуль числа
    int count = 0; //заводим счетчик
    if (n == 0) count = 1; // n == 0? Цифра одна.
    while (n != 0) //пока n не равно 0
    {
        n = n / 10; //делим число на 10
        count++; //прибавляем счетчик
    }
    return count;
}

Какая-то специальная функция для деления нацело в C# не нужна, при делении переменной цельночисленного типа (byte, sbyte, short, ushort, int, uint, long, ulong) на целое число или цельночисленную переменную, результатом будет целое число, т.е. деление нацело произойдет автоматически.

Рекурсией:

static int CountDigitsRec(int n)
{
    n = (int)Math.Abs(n);
    if (n <= 9)
    {
        return 1;
    }
    else
    {
       return CountDigitsRec(n / 10) + 1;
    }
}

Использование десятичного логарифма.

static int CountDigitsLog10(int n)
{
    if (n == 0)
    {
        return 1;
    }
    return (int)Math.Log10(Math.Abs(n)) + 1;
}

Фразочка про ТБ при работе со взрывчатыми веществами.

По мотивам исторического выпуска Юлии Латыниной.

Потому что без ТеБе — вы ни людям ни сэбэ!

Выпуск смотреть здесь. И там есть кошка (ну или кот) доступа!

С#, Заполнение массива одним значением.

Преамбула

Практического значения эта задача обычно не имеет (на самом деле применение есть, покажу позже), но, тем не менее, иногда ее дают в качестве учебной задачи. Попробуем ее решить на C#.

Примечание: Создаваемый по умолчанию массив, автоматически заполняется нолями (0x00).
А нам, как раз, наоборот, надо создать массив с паттерном 0xFF или 0xAA.

Решение «в лоб»

Я думаю, оно всем понятно. Создать массив и заполнить его нужными значениями:

int items = 536870912;
byte[] tArr = new byte[items];

for (int i = 0; i < items; i++)
{
    tArr[i] = 0xFF;
}

Тут мы в цикле присваиваем каждому элементу массива значение 0xFF.

— Оно медленное.
+ Оно простое и с использованием безопасного кода.

В лоб + Array.Copy

Некто попытался оптимизировать прошлое решение, используя Array.Copy(), думая, что эта функция быстрее работает с памятью.

Что решение «в лоб», что «Array.Copy()» с распополамленным циклом работают одинаково, точнее, получилось даже медленнее (в конце статьи будет итоговая таблица):

int items = 536870912;
byte[] tArr = new byte[items];
tArr[0] = 0xFF;
for (int i = 1; i <= items / 2; i *= 2)
{
    Array.Copy(tArr, 0, tArr, i, i);
    Array.Copy(tArr, 0, tArr, i, items - i);
}

P/Invoke способ с использованием внешних библиотек

Прямая работа с памятью сильно обходит .NET по скорости, так что самый оптимальный способ для такой задачи — использовать небезопасный код.

public static class FillArray
{
    [DllImport("msvcrt.dll",
    EntryPoint = "memset",
    CallingConvention = CallingConvention.Cdecl,
    SetLastError = false)]

    private static extern IntPtr MemSet(IntPtr dest, int value, int count);

    public static byte[] FillBytes(int Length, byte Value)
    {
        byte[] Arr = new byte[Length];
        GCHandle GCH = GCHandle.Alloc(Arr, GCHandleType.Pinned);
        MemSet(GCH.AddrOfPinnedObject(), (int)Value, Length);
        return Arr;
    }

В свою программу мы импортировали функцию memset из библиотеки msvcrt.dll, т.е. смогли получить контроль над памятью. И заполнили нужным числом массив. Поскольку, за нас это делали библиотеки C++ и функции ОС, все оказалось быстро.

Сравнительная таблица скорости работы разных алгоритмов заполнения массива (массив 500 Мб).

For 00:00:04.4212528
For+Array.Copy() 00:00:04.6952685
MemSet (msvcrt.dll) 00:00:00.2360135
Random bytes (RNGCryptoServiceProvider) 00:00:06.1143497

Сравнение алгоритмов в источнике.

Тестовый пример (для этого и предыдущего [копия] поста) на GitHub

Источник

C#, заполнение массива случайными числами.

Преамбула

Можно сказать, учебная задача. Итак, дан массив типа byte[], необходимо заполнить его случайными числами. И случайные числа нужны понадежнее. Ну хорошо, аппаратный ГСЧ конструировать не будем 🙂 Хотя как-нибудь надо и этот вариант рассмотреть.

Решение

Все решается довольно стандартными методами:

1. Подключаем пространство имен System.Security.Cryptography:

using System.Security.Cryptography;

2. Создаем массив байт нужной длины:

byte[] Arr = new byte[666];

3. Создаем RNGCryptoServiceProvider, т.е. генератор случайных чисел системного криптопровайдера.

RngCsp = new RNGCryptoServiceProvider();

4. Заполняем массив:

RngCsp.GetBytes(Arr);

Примечание: Это довольно простое решение «в лоб», и хоть Майкрософт гарантирует нам, что числа будут прям случайные-случайные, в самом MSDN показан пример с выкрутасами (см. в источниках).

Примечание #2: Метод стандартный для C#, но довольно медленный. Даже медленнее, чем заполнение гигантского массива на 500 Мб одним числом, в примерном приближении и довольно неточно заполнение массива заняло почти 6 секунд:

Random bytes (RNGCryptoServiceProvider): 00:00:05.8453343

Источник

RNGCryptoServiceProvider Class