Комментарии проекта Программирование
17

Работа с небезопасным кодом в C#

» Программирование
Язык C# поддерживает указатели, однако несколько ограниченно. Ограниченность заключается в том, что применение указателей не поощряют, поскольку справедливо считается, что это может повлиять на надежность как кода, так и среды выполнения в целом.

Читать далее...
alexprey #1 - 10 месяцев назад 0
Msey:
Самый частый случай, который встречался мне на практике - это более шустрые операции с массивами и строками за счет отсутствия проверки их границ.
оптимизация работы с большими массивами данных, когда надо тоскать между функциями все эти данные и манипулировать небольшими участками массива без выделения в небольшой кусочек.
Но с недавних пор это все не актуально стало. В новом стандарте есть новые структуры данных, которые оборачивают такие небезопасные операции и непосредственное использование unsafe становится ненужным
Msey #2 - 10 месяцев назад 0
Doc, "Все структуры C# имеют значимый тип". Пофикшено.
Doc #3 - 10 месяцев назад 0
Все структуры C# имеют тип переменной
Это так переведено all C# structs are value types?
KingMaximax #4 - 10 месяцев назад 0
Hanabishi, теперь понял. Теперь мне придётся пересмотреть некоторые темы программирование, а то уже совсем что-то забываю. Уже начал путать эмулятор со строгим оптимизатором, грубо говоря.
И ещё, извиняюсь за свою неграмотность в области ЯП.
Hanabishi #5 - 10 месяцев назад 0
KingMaximax, неправильно, нельзя "обойти виртуальную машину", код в любом случае на ней выполняется. Это главное отличие C# от нативных C\C++, но речь в статье вообще не об этом.
Есть понятие управляемого и неуправляемого кода. Так вот шарп по-умолчанию использует управляемый код, это когда все данные жестко контролируются средой, ты не управляешь памятью напрямую и не можешь критически накосячить, а ненужные данные удаляются автоматически (то есть утечки памяти практически невозможны).
Но существует и возможность работать с неуправляемым кодом, использовать прямой доуступ к памяти, о чем собственно статья. Это считается небезопасным (отсюда и ключевое слово unsafe), потому что работоспособность, стабильность и защищенность программы начинает на 100% зависеть от уровня криворукости программиста.
KingMaximax #6 - 10 месяцев назад 0
Hanabishi, т.е. он пытался обойти виртуальную машину, если я правильно понял. Это как внутренняя система безопасности проверки жизненности цикла программы, что-то наподобие в этом роде. Она добавляет 100+ лишних килобайт. Но её вроде отключать можно, но лучше не надо, иначе есть риск поменять ОЗУ. Мой продвинутый друг в программировании занимался подобным, но потом перешёл на ассемблер из-за паранойности C++\C#, врать не буду, но это не совсем точные сведения. Или я снова туплю?
Hanabishi #7 - 10 месяцев назад 0
KingMaximax, какой-то странный вопрос. Синтаксически C# происходит от C, что вроде очевидно. Соответсвенно и форма записи указателей взята оттуда.
Но несмотря на внешнюю схожесть, внутри C# работает абсолютно по-другому. Даже в небезопасном контексте с прямым доступом к памяти, код все равно выполняется на виртуальной машине.
KingMaximax #8 - 10 месяцев назад 0
Мне кажется или это похоже на C++ в C#?
Не знаю, я пользуюсь mem alloc'ом в некоторых своих подопытных детишках по C++ только...
У меня свои шаманства с бубном, короче.
Hanabishi #9 - 10 месяцев назад 0
uranus, быстрее чем функции стандартной библиотеки можно добиться и не прибегая к небезопасному коду (написать собственную реализацию), тут о другом речь.
uranus #10 - 10 месяцев назад 0
Реально же практическое применение я вижу в двух вариантах:
Если не ошибаюсь, на хабре доказывали, что таким способом можно добиться большей скорости, чем у аналогичных функций стандартной библиотеки. Только не кидайте камнями, может, я не так понял просто.
ScorpioT1000 #11 - 10 месяцев назад 2
Или foreach, вообще внутри всё запаковано
Hanabishi #12 - 10 месяцев назад 2
Msey, плохой случай. Надо писать так, чтобы проверки границ в сейф коде убирались оптимизатором.
То есть допустим в случае
//a - некоторый массив
for(int i = 0; i < a.Length; i++)
проверки границ не будет. И разницы производительности с небезопасным вариантом тоже. Потому что оптимизатор умный.
Лезть ради этого в небезопасный контекст - крайне сомнительное занятие, нужно просто правильно писать в безопасном.
Msey #13 - 10 месяцев назад 0
Самый частый случай, который встречался мне на практике - это более шустрые операции с массивами и строками за счет отсутствия проверки их границ.
Hanabishi #14 - 10 месяцев назад (отредактировано ) 1
Забыл написать для чего это вообще надо. Для начала использования небезопасного кода нужно стараться избегать (помните что 95% дырок безопасности в истории это вина программиста, прозевавшего проверки в неуправляемом коде). Реально же практическое применение я вижу в двух вариантах:
  1. Если в проекте используется неуправляемая библиотека. И то очень специфически, если у вас структуры данных прибиты гвоздями. В большинстве же случаев можно обойтись маршалингом в безопасным контексте.
  2. Вы кулхацкер, который по каким-то причинам захотел использовать именно шарп. Тогда думаю вы в этой статье и не нуждаетесь. Хотя кстати я могу привести личные примеры такого применения )
Msey #15 - 10 месяцев назад 3
BrEd Pitt: по-разному бывает. Часть напишу сам, часть возьму из одного источника, часть из мсдн.
Первые статьи вообще полностью сам писал, опираясь изредка на оф. документацию, чтобы лишний раз не сморозить дезинформирующую отсебятину.
BrEd Pitt #16 - 10 месяцев назад 0
Msey, это "записки по своему опыту" или из книги какой? Читается легко и плавно, словом, тутор классный.
1

Атрибуты в C#

» Программирование
Атрибутами в C# являются классы, содержащие в себе некоторую метаинформацию, встраиваемую в сборку приложения.

Читать далее...
9

[C#, Regex] Разделить строку на слова и цитаты

» Программирование
Итак, я хотел разбить регуляркой такую сроку:
aaaaa bbb "ccc ссс"
На такой массив:
[0] = aaaaa 
[1] = bbb 
[2] = ccc ссс
Когда-то давно я уже задавал такой вопрос, на что мне ответили таким вот паттерном:
[^\s"']+|"([^"]*)"|'([^']*)'
И все бы хорошо, но теперь мне понадобилось сохранять в цитатах кавычки и апострофы, т.е. результат уже должен быть таким:
[0] = aaaaa 
[1] = bbb 
[2] = "ccc ссс"
Пробовал кавычки вносить в скобки, но это не работает.
uranus #1 - 11 месяцев назад 0
Nerevar, огромное спасибо, все работает!
Nerevar #2 - 11 месяцев назад (отредактировано ) 3
Попробуйте такую строку
new Regex(@"[^\s""']+|""([^""]*)""|'([^']*)'")
прикреплены файлы
uranus #3 - 11 месяцев назад 0
Nerevar #4 - 11 месяцев назад 0
    class Program
    {
        static void Main()
        {
            Console.OutputEncoding = Encoding.UTF8;
            string s = "aaa bbb 'ccc' \"ddd\"";
            Regex regex = new Regex(@"[^\s""']+|""([^""]*)""|'([^']*)'");
            MatchCollection matches = regex.Matches(s);
            if (matches.Count > 0)
            {
                foreach (Match match in matches)
                    Console.WriteLine(match.Value);
            }
            else
            {
                Console.WriteLine("Совпадений не найдено");
            }

            Console.Read();
        }
    }
Проверьте что выводит этот пример у вас? Используется ваш регекс
uranus #5 - 11 месяцев назад 0
Nerevar, я, наверно, не так выразился. Находит то он правильно, но мне нужно, чтобы в группу кавычки/апострофы попадали тоже, т.е. не:
"hello" world => [hello] [world]
А так:
"hello" world => ["hello"] [world]
Nerevar #6 - 11 месяцев назад (отредактировано ) 0
Твой паттерн находит все как надо - и одинарные и двойны кавычки и пробелы между словами внутри кавычек
Msey #7 - 11 месяцев назад 0
Весь код в студию.
uranus #8 - 11 месяцев назад (отредактировано ) 0
pro100master, в регулярках я почти полный ноль, можно пример? Мне проще подобное сделать без регулярок, но все же хотелось бы на них, вместо того, чтобы городить свой костыль.
pro100master #9 - 11 месяцев назад 0
тогда делай правило если пробел то разделить а если ковычка то запрешаем пробел
7

C# Делегаты и события

» Программирование
В данной статье рассматриваются базовые операции над делегатами, их производными и связующими.

Читать далее...
Devion #1 - 1 год назад (отредактировано ) 0
даже базовый тип ничего не сделает, т.к. под капотом 'i' будет находиться в экземпляре делегата, и это будет один и тот же экземпляр во всех элементах списка.
На выходе компилятора будет примерно вот такое:
    public void Do()
    {
      List<Action> actionList = new List<Action>();
      DisplayClass displayClass = new DisplayClass();
      for (displayClass.i = 0; displayClass.i < 3; displayClass.i++)
      {
        actionList.Add(new Action((object) displayClass, __methodptr(<Do>b__0)));
      }
    }

    [CompilerGenerated]
    private sealed class DisplayClass
    {
      public int i;

      internal void <Do>b__0()
      {
        Console.Write((object) this.i);
      }
    }
т.к. вся лямбда внутри контекста захваченных переменных будет формировать отдельный класс то по факту замыкания не будет, если вынести лямбду в отдельный от цикла метод.
Так же можно создать переменную со значением и записать туда i, и уже эту переменную прокинуть в лямбду, в этом случае будет создаваться отдельный экземпляр делегата каждый виток цикла (но в старых версиях компилятора это будет работать иначе, что вроде как баг, ибо для пользователя оно по факту должно выглядеть как "передача ссылки").
Бтв, тут всплывает тема с аллокацией, т.к. как ты можешь заметить создание экземпляра каждый виток цикла это дичь )
ScorpioT1000 #2 - 1 год назад (отредактировано ) 0
Про последнее, оно замыкает по ссылке даже базовый тип? Хотя вроде это везде так вроде, кроме пхп и вроде c++11, там надо явно указать.
Devion #3 - 1 год назад 0
Имхо еще что можно сделать по теме, чуть посложнее чем для новичков, но интересно:
# объяснить подробнее про вычитание списка делегатов
Например, разъяснить почему:
  Action a = () => Console.Write("A");
  Action b = () => Console.Write("B");
  Action c = () => Console.Write("C");
  Action s = a + b + c;
  (s - (b + c))();      //A
  //но при этом
  (s - (a + c))();      //ABC
Упомянуть про порядок вычитания, например
s = a + b + a;
(s - a)(); //AB, а не BA
# рассказать про аллокации, связанные с лямбдами, когда они происходят и почему, а так же почему то что оно аллоцирует может быть проблемой
например, как тут:
    string str = "str1";
    Action d1 = () => Debug.Log(str); //аллоцирует при каждом вызове метода, который объявляет d1
    Action d2 = () => Debug.Log("str1"); //аллоцирует лишь однажды
# рассказать про неявный захват переменных
Например объяснить, почему если очистить 'd1', 'a' останется в памяти до очистки 'd2'
    var a = new object();;
    var b = new object();
    
    Action d1 = () =>
    {
        Debug.Log(a);
        Debug.Log(b);
    };
    Action d2 = () => Debug.Log(b);
# ну и про замыкания само собой, т.е. почему вот это выведет 333
    var actions = new List<Action>();
    for (int i = 0; i < 3; i++)
        actions.Add(() => Console.Write(i));

    foreach (var action in actions)
        action();
ScorpioT1000 #4 - 1 год назад 0
Функшн поинтеры в С++ вполне себе типобезопасны.
То же хотел сказать) либо имели ввиду C поинтеры
Msey #5 - 1 год назад 0
Doc:
С с++ не работал, поэтому, с учетом отсутствия примера, опровергающего это:
Delegates are like C++ function pointers but are type safe.
Я остановлюсь на мсдн'овском варианте.
Doc #6 - 1 год назад 4
Делегаты похожи на указатели функций в C++, но являются объектно-ориентированными и типобезопасными
Понимаю, что перевод с МСДН, но бред. Функшн поинтеры в С++ вполне себе типобезопасны.
Isstrebitel #7 - 1 год назад (отредактировано ) 0
За ковариантность и контравариантность огромное спасибо, месяца два назад наткнулся именно на такое, где прекрасно понимал, что "вот бы такое было" - без этого было крайне неудобно, но не знал, что такое есть и так называется.
Даже не помню уже, почему у меня такое не получалось, должен же был хоть попробовать
А с тех пор только на плюсах писал, вот так вот -_-
16

Работа с файлами конфигурации приложения

» Программирование
В данной статье будет разобраны основы работы с конфигурационными файлами, секциями конфигурации и созданием своих конфигурационных разделов. Перед прочтением рекомендуется ознакомиться с языком разметки xml, индексаторами, свойствами, приведением типов и всем C# в целом.

Читать далее...
ScorpioT1000 #1 - 1 год назад 0
Devion, его форсили, т.к. была libxml, а кроме неё ничего не было, только всякие бомжовские ini
Devion #2 - 1 год назад (отредактировано ) 3
Про геймдев я сказал, т.к. это широкая стенд-элон индустрия, в вебе и сетевых аппликухах xml уже давно пережиток прошлого, за исключением некоторых протоколов (хотя нет, привет андроиду и жаве с их вьюхами)
Файлы конфигурации в xml очень жестко навязывались в дотнетах. Например
  • app.config, который, как пример, мы создаем если хотим например зареплейсить какой-нибудь референс в зависимостях проекта
  • web.config
  • банально файлы sln и csproj
  • в ксамарине шаблоны форм (причем и под платформы и "свое" в таком виде)
  • вроде как MVC тоже что-то такое тянули, но не открывал давненько, боюсь ошибиться
  • файлы ресурсов всякие
  • WPF
  • WCF
  • если зайти на msdn и поглядеть там 90% вшитых файлов конфигураций xml
Видно, что сейчас от этого отходят, например .Net Core где солюшн уже в другом формате, или стандарт online темплейтов в json сделан, и на .Net Core можно переобъявлять старые app.config на другой лад
но как суть, более старые решения там навязывали xml, мб из-за вопросов совместимости.
Понятно что xml это синтаксически перегруженный кусок говна и юзать его намеренно на новых проектах то еще удовольствие, но момент относительно "всякого нативного" в дотнете еще актуален - то что постулируют писать в xml, пишется в xml.
tysch_tysch #3 - 1 год назад 0
ScorpioT1000, который из yml? под таким разрешением несколько форматов
ScorpioT1000 #4 - 1 год назад (отредактировано ) 0
Эргалон, да, комментарии в жсон не предусмотрены, т.к. он изначально был для передачи данных по сети. Зато они есть в yml, как ранее уже описывали. yml лучше подходит для конфигурации, но он всё ещё мало поддерживается старпёрскими библиотеками.
В самой статье ни слова не было о геймдеве
Про геймдев я сказал, т.к. это широкая стенд-элон индустрия, в вебе и сетевых аппликухах xml уже давно пережиток прошлого, за исключением некоторых протоколов (хотя нет, привет андроиду и жаве с их вьюхами)
Hellfim #6 - 1 год назад 0
ScorpioT1000, А теперь прокомментируй каждую строку в джейсоне своем
Это, конечно, классно просить сделать то, для чего формат не предназначен.
и покажи редактор, который грамотно выделит синтаксис)
Notepad++ более чем достаточно
Может он и подойдет, для более маленьких конфигураций, а если у тебя конфигурация на 1000+ строк? Как ты будешь потом разгребаться, что есть где?
Ровно также как и в xml, только в xml больше тегов стоит.
писать отдельную библиотеку чисто ради единоразового чтения параметров как минимум глупо
Ну да, Newtonsoft подключить к проекту нельзя. Нужно что-то своё навелосипедить :)
alexprey #7 - 1 год назад 0
тк большинство конфигураций для расширений (логгеры, фреймворки итд) инжектятся именно в xml формате
щто, оно же через тот же конфигуратор грузится.
Msey #8 - 1 год назад (отредактировано ) 0
ScorpioT1000:
  • В самой статье ни слова не было о геймдеве, а ключевое слово под статьей unity3d чисто ради кликбейта
  • Сейчас речь идет конкретно о платформе .net, где xml - штатный язык разметки, и писать отдельную библиотеку чисто ради единоразового чтения параметров как минимум глупо (это без учета того, что конфигурационными файлами пользуются зачастую заказчики, и они могут по физиономии настучать за такие вот распространенные конфиги)
В тех проектах, за которые мне чаще всего не платят, я обычно самописными конфигами пользуюсь
Эргалон #9 - 1 год назад (отредактировано ) 0
ScorpioT1000, А теперь прокомментируй каждую строку в джейсоне своем и покажи редактор, который грамотно выделит синтаксис)
Может он и подойдет, для более маленьких конфигураций, а если у тебя конфигурация на 1000+ строк? Как ты будешь потом разгребаться, что есть где?
Devion #10 - 1 год назад 0
не знаю что за yml, знаю yaml.
для сложных типов данных как раз не xml а yaml, т.к. это больше чем разметка, есть поддержка алиасов специально для сериализации ссылочных типов
ScorpioT1000 #11 - 1 год назад -1
Msey, а в геймдеве принято не читать документацию?
Msey #12 - 1 год назад 0
ScorpioT1000:
Ох уж этот xml) там на жсон ещё не торопятся в геймдеве переходить?
На самом деле это проблемный вопрос, тк большинство конфигураций для расширений (логгеры, фреймворки итд) инжектятся именно в xml формате, и чтобы убедиться, что они читают конфиги в нескольких форматах, нужно, либо читать документацию, либо в случае ее отсутсвия чекать рефлектором.
По крайней мере в дотнете
ScorpioT1000 #13 - 1 год назад (отредактировано ) 0
Эргалон, лолшто, приведи примеры
{
	"configuration": {
		"configSections": {
			"section": {
				"name": "customSection",
				"type": "System.Configuration.NameValueSectionHandler"
			}
		},
		"startup": {
			"supportedRuntime": {
				"version": "v4.0",
				"sku": ".NETFramework,Version=v4.6.1"
			}
		},
		"customSection": {
			"add": {
				"key": "KeyFromCustomSection",
				"value": "valueFromCustomSection"
			}
		}
	}
}
H #14 - 1 год назад 0
xml формат не для хранения конфигов имхо, а для передачи сложных типов данных (объектов и т.п.). Есть же json/yml или хотя-бы ini.
xml
<appSettings>
      <add key="KeyA" value="Msey" />
      <add key="KeyB" value="Love" />
      <add key="KeyC" value="Goosey" />
</appSettings>
json
{
  "appSettings": {
    "KeyA": "Msey",
    "KeyB": "Love",
    "KeyC": "Goosey",
  }
}
yml
appSettings:
  KeyA: Msey
  KeyB: Love
  KeyC: Goosey
ini
[appSettings]
KeyA=Msey
KeyB=Love
KeyC=Goosey
Эргалон #15 - 1 год назад 0
ScorpioT1000, JSON для конфига не лучший вариант. В том плане, что xml в этом плане гораздо лучше читаемый и регулируемый.
ScorpioT1000 #16 - 1 год назад (отредактировано ) 0
Ох уж этот xml) там на жсон ещё не торопятся в геймдеве переходить?