Показаны сообщения с ярлыком c#. Показать все сообщения
Показаны сообщения с ярлыком c#. Показать все сообщения

среда, 21 января 2015 г.

Статические поля в generic-классах

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/static-field-in-generic-type/.


Сегодня мы кратко поговорим о статических полях в generic-классах. Тема простая, но у некоторых разработчиков она вызывает трудности. Итак, задачка: что выведет следующий код?

class Foo<T>
{
  public static int Bar;
}
void Main()
{
  Foo<int>.Bar++;
  Console.WriteLine(Foo<double>.Bar);
}

пятница, 21 ноября 2014 г.

Ещё раз об экранировании URI в .NET

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/uri-escaping/.


Сегодня на StackOverflow мне попался интересный вопрос: «Unit test ReSharper and NUnit give different results». Суть заключалась в том, что ReSharper и NUnit дают разные результаты при экранировании URI. Я решил немножко углубиться в эту проблему. Сегодняшний пост продолжает недавно начатую мной тему «Об экранировании слеша в .NET».

среда, 19 ноября 2014 г.

Сайд-эффект внутренней реализации List

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/list-version-side-effect/.


Если вы делаете foreach по некоторому List-у, то менять итерируемый лист внутри цикла крайне не рекомендуется, ведь это верный способ получить InvalidOperationException. А теперь загадка: как думаете, что случится со следующим кодом:

var list = new List<int> { 0, 1, 2 };
foreach(var x in list)
{
  if (x == 0)
  {
    for (int i = int.MinValue; i < int.MaxValue; i++)
      list[0] = 0;
    list.Add(3);
  }
  Console.WriteLine(x);
}

Правильный ответ: этот код замечательно отработает.

четверг, 13 ноября 2014 г.

Об экранировании слеша в .NET

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/uri-escaping/.


Загадка на сегодня: что выведет код?

var uri = new Uri("http://localhost/%2F1");
Console.WriteLine(uri.OriginalString);
Console.WriteLine(uri.AbsoluteUri);

Правильный ответ: зависит. Давайте немножко поразбираемся.

вторник, 11 ноября 2014 г.

Nullable-арифметика

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/cheatsheet-nullable/.


Что будет, если null поделить на ноль? А сколько будет null | true? А null & true? А ((string)null + null)?

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

среда, 29 октября 2014 г.

Endianness в .NET

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/endianness/.


Рассмотрим простую задачку: что выведет следующий код?

[StructLayout(LayoutKind.Explicit)]
struct UInt16Wrapper
{
  [FieldOffset(0)]
  public UInt16 Value;
  [FieldOffset(0)]
  public Byte Byte1;
  [FieldOffset(1)]
  public Byte Byte2;
}
void Main()
{
  var uint16 = new UInt16Wrapper();
  uint16.Value = 1 + 2 * 256;
  Console.WriteLine(uint16.Byte1);
  Console.WriteLine(uint16.Byte2);
}

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

четверг, 2 октября 2014 г.

Задачник.NET

Этот пост предназначается всем любителям платформы .NET и языка C#. Думаю, многие встречали на просторах сети разнообразные задачки на понимание тех или иных особенностей платформы или языка. Я большой любитель подобных задачек и головоломок. Они помогают глубже понять определённые области и повысить собственные программистские навыки. Однажды я решил сделать подборку подобных задачек, чтобы можно было показывать другим людям и обсуждать нюансы работы с .NET/C#. Когда задачек накопилось достаточное количество, появилась новая мысль — оформить мою подборку в виде книжки. Вашему вниманию предоставляется текущий вариант этого сочинения под названием «Задачник.NET».

Читать online
Скачать PDF-версию
Исходные коды на GitHub

четверг, 24 июля 2014 г.

Получение MCP: личный опыт

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/ms-mcp/.


Не так давно мне на работе перепал ваучер на бесплатную сдачу экзамена от Microsoft. «А почему бы и нет?» — подумал я. План был выполнен успешно, в связи с чем мне хотелось бы поделиться личным опытом. Возможно, эта история пригодится тем, кто только собирается начать получать сертификации от Microsoft.

вторник, 29 апреля 2014 г.

Странное поведение FindElementsInHostCoordinates в WinRT

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/findelementsinhostcoordinates/.


Есть в Silverlight отличный метод: VisualTreeHelper.FindElementsInHostCoordinates — позволяет выполнять HitTest, т.е. для некоторой точки или прямоугольника искать все объекты визуального поддерева, которые с этими точкой или прямоугольником пересекаются. Внешне точно такой же метод VisualTreeHelper.FindElementsInHostCoordinates можно встретить в WinRT. И вроде выглядит-то он точно также, но есть нюанс: работает этот чудо-метод в разных версиях платформы по-разному. Давайте разберёмся.

пятница, 21 февраля 2014 г.

Про System.Drawing.Color и оператор ==

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/system-drawing-color-equals/.


Для многих стандартных структур в .NET-е переопределён оператор ==, который позволяет легко сравнивать ваши объекты. К сожалению, далеко не все задумываются о том, что на самом деле сравнивается при работе с этим замечательным оператором. В этой короткой заметке мы посмотрим логику сравнения объектов на примере System.Drawing.Color. Как вы думаете, что выведет следующий код:

var redName = Color.Red;
var redArgb = Color.FromArgb(255, 255, 0, 0);    
Console.WriteLine(redName == redArgb);    

среда, 20 ноября 2013 г.

Cache-Conscious Binary Search

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/cache-conscious-binary-search/.


Рассмотрим простую задачу: есть некоторый достаточно большой неизменный набор чисел, к нему осуществляется множество запросов на наличие некоторого числа в этом наборе, необходимо максимально быстро эти запросы обрабатывать. Одно из классических решений заключается в формировании отсортированного массива и обработке запросов через бинарный поиск. Но можно ли добиться более высокой производительности, чем в классической реализации? В этой статье мне хотелось бы рассказать про Cache-Conscious Binary Search. В данном алгоритме предлагается переупорядочить элементы массива таким образом, чтобы использование кэша процессора происходило максимально эффективно.

воскресенье, 3 ноября 2013 г.

Jon Skeet's Quiz

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/jon-skeet-quiz/.


Однажды Джона Скита попросили сформулировать три интересных вопроса на знание C#. Он спросил следующее (оригинал вопросника, перевод статьи):

Q1. Вызов какого конструктора можно использовать, чтобы следующий код вывел True (хотя бы в реализации Microsoft.NET)?

object x = new /* fill in code here */;
object y = new /* fill in code here */;
Console.WriteLine(x == y);

Учтите, что это просто вызов конструктора, вы не можете поменять тип переменных.

Q2. Как сделать так, чтобы следующий код вызывал три различных перегрузки метода?

void Foo()
{
    EvilMethod<string>();
    EvilMethod<int>();
    EvilMethod<int?>();
}

Q3. Как заставить следующий код выбросить исключение во второй строчке с помощью локальной переменной (без хитрого изменения её значения)?

string text = x.ToString(); // No exception
Type type = x.GetType(); // Bang!

Вопросы показались мне интересными, поэтому я решил обсудить их решения.

пятница, 11 октября 2013 г.

Внутреннее устройство массивов в .NET

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/arrays-internal-structure/.


Иногда бывает полезно понимать, как выглядит внутреннее представление объектов, с которыми мы работаем. В этой статье я хотел бы поговорить о массивах: как именно они хранятся в памяти, какие IL-команды используются для работы с ними, как выглядит ассемблерный код при обращении к их элементам. Я рассмотрю три вида массивов: single (T[]), rectangular (T[,]), jagged (T[][]). Также будет затронута тема массивов с ненулевой нижней границей (T[*]) и нюансов работы с ними.

среда, 18 сентября 2013 г.

Учимся округлять в C#

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/cheatsheet-rounding/.


А знаете ли вы, что Math.Round(1.5) == Math.Round(2.5) == 2? Можете ли сходу сказать, сколько будет -7%3 и 7%-3? Помните ли, чем отличаются Math.Round, Math.Floor, Math.Ceiling, Math.Truncate? А как происходит округление при использовании string.Format? Давайте немного погрузимся в мир округлений и разберёмся с нюансами, которые не для всех могут быть очевидными.

суббота, 31 августа 2013 г.

Сравнение производительности массивов в .NET, часть 2

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/arrays-access-performance/.


В первой части статьи я задался задачей сравнить производительность многомерных массивов. Рассматривались данные в виде двумерного массива N*M, тестировалась скорость доступа к элементу [i,j] при итерировании по всему массиву двумя циклами. Для сравнения было выбрано три варианта: одномерный массив single[i * N + j] и двумерные массивы jagged[i][j], rectangular[i, j]. Изначально у меня получилось, что jagged-версия работает быстрее single версии, но более детальное изучение проблемы показало, что дело может измениться в зависимости от используемых JIT-оптимизаций. Разберёмся с проблемой более подробно.

Рассмотрим методы из бенчмарка с наборами параметров «100»(N=M=100, IterationCount=100000) и «101»(N=M=101, IterationCount=100001) под x86 и x64. На моей машине (Intel Core i7-3632QM CPU 2.20GHz) получились следующие результаты:

  100-x86
Single      : 1012ms
Jagged      :  772ms
Rectangular : 1460ms

  101-x86
Single      : 1036ms
Jagged      :  785ms
Rectangular : 1485ms  

  100-x64
Single      : 544ms
Jagged      : 346ms
Rectangular : 741ms

  101-x64
Single      :  785ms
Jagged      :  793ms
Rectangular : 1050ms

четверг, 29 августа 2013 г.

Об итерировании статичных массивов в .NET, часть 2

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/static-array-iteration/.


В первой части я встретился с весьма интересной ситуацией. Были измерены скорости работы двух методов, в первом из которых считалась сумма элементов массива, ссылка на который хранилась в обычном поле объекта, а во втором — массива, ссылка на который хранилась в статичном поле. Результаты меня удивили: массивы были одинаковые, но второй метод работал ощутимо дольше. Сперва я подумал, что дело в организации скорости доступа к статичным полям, но более детальный анализ ситуации и разговоры с коллегами помогли мне понять, что истинная причина такого поведения намного интересней: для массивов, длина которых кратна 4, JIT использует различные оптимизации в случае обычных и статичных массивов. Давайте разберёмся с ситуацией более детально.

понедельник, 26 августа 2013 г.

Недокументированные ключевые слова C# или превращаем объект в тыкву

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/undocumented-keywords-in-cs/.


Стандартный компилятор C# поддерживает 4 недокументированных ключевых слова: __makeref, __reftype, __refvalue, __arglist. Эти слова даже успешно распознаются в Visual Studio (хотя, ReSharper на них ругается). Они не даром исключены из стандарта — их использование может повлечь серьёзные проблемы с безопасностью. Поэтому не нужно их использовать везде подряд, но в отдельных исключительных случаях они могут пригодится. В этом посте я обсужу предназначение недокументированных команд, рассмотрю вопросы их производительности и научусь превращать объект в тыкву.

воскресенье, 18 августа 2013 г.

Об итерировании статичных массивов в .NET, часть 1

Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/static-array-iteration/.


Содержание поста было обновлено: результаты были уточнены, появилась вторая часть с подробным объяснением сложившейся ситуации.

Управляемый подход платформы .NET делает жизнь разработчиков достаточно простой, беря на себя многие рутинные операции. Большую часть времени программист может вообще не вспоминать о технической реализации платформы, сосредоточившись исключительно на логике своего приложения. Но иногда попадаются задачи, критичные по производительности. Существует множество различных подходов к оптимизации кода в таких ситуациях вплоть до переписывания наиболее важных частей кода через неуправляемый код. Однако, зачастую для увеличения скорости приложения достаточно понимать, сколько времени тратится на ту или иную операцию. Знание подобных вещей позволит оптимизировать некоторые методы с помощью достаточно простых модификаций исходного кода.

В этой статье мне хотелось бы поговорить о скорости доступа к массивам, ссылки на которые хранятся в статичных переменных. Дело в том, что в скорость итерирования по ним в зависимости от условий запуска может быть ниже, чем для массива, ссылка на который хранится в обычном поле экземпляра класса или локальной переменной. Рассмотрим пример.