Advertisement
Guest User

Untitled

a guest
Oct 23rd, 2019
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.53 KB | None | 0 0
  1. В c# существуют примитивные типы(такие как Int32,Double...), поскольку примитивные типы - самые частоиспользуемые в языке, то для них существуют псевдонимы (int,double). Это Value типы которые хранятся в стеке
  2. В C# существуют проблемы связанные с тем, что есть возможность переполнения типа, например:
  3. ```csharp
  4. int s = int.MaxValue - 1;
  5. int ss = 2;
  6. var res = s + ss; // (-int.MaxValue)
  7. ```
  8.  
  9. Т.е переполнение не генерирует ошибку, а просто складывает при этом закольцовывая результат
  10. Для того чтобы при переполнении генерировалась ошибка можно глобально поставить это используя флаг компиляции /checked+
  11. Либо используя checked:
  12. Вот так будет сгенерирован OverflowException
  13. ```csharp
  14. int s = int.MaxValue - 1;
  15. int ss = 2;
  16. checked
  17. {
  18. _res = s + ss;
  19. }
  20. ```
  21. Размещение кода в блоке checked говорит компилятору, генерировать IL код с другими инструкциями, например если при сложении двух чисел раньше генерировалась инструкция add, то, теперь будет генерироваться инструкция add.ovf
  22. Кстати, вот так ошибка генерироваться не будет, инструкция не работает для вложенных методов, только для инлайн кода:
  23. ```csharp
  24. int s = int.MaxValue - 1;
  25. int ss = 2;
  26. checked
  27. {
  28. AddMethod(s, ss);
  29. }
  30. ```
  31. Также существует ключевое слово unchecked, используется если стоит флажок /checked+ при компиляции, чтобы отключить ошибку при переполнении
  32.  
  33. Особо примечательно, что тип Decimal игнорирует все правила и всегда при переполнии генерирует System.OverflowException: Value was either too large or too small for a Decimal:
  34. Использование флага checked немного замедляет работу программы
  35. ```csharp
  36. decimal s = decimal.MaxValue - 1;
  37. decimal ss = 2;
  38. decimal res = s + ss;
  39. Console.WriteLine(_res);
  40. ```
  41.  
  42. # Ссылочные и значимые типы
  43. Все типы в CLR разделяются на значимые и ссылочные, ссылоные типы - классы хранятся в куче, а указатель на них - в стеке.
  44. Таким образом память если нужно сослаться на один и тот же ссылочный объект из нескольких мест в программе, то будет создан указатель на этот участок кучи, это очень похоже на классы entity у Мартина Фаулера, их идентичность - адрес в куче.
  45.  
  46. Структуры размещаются в стеке, и если экземпляр структуры возвращается их метода, то в стеке создается новая структура, т.е выделяется память для хранения того же объекта, который уже был создан в методе и происходит копирование полей в область памяти выделенную вызывающим методом, таким образом возвращение структуры из метода - оверхед, также если приходится создавать массив одинаковых объектов-структур это также сказывается на памяти. Замечу, что речь идет именно о неупакованных структурах
  47.  
  48. Все структуры наследуются от System.ValueType, который в свою очередь наследуется от System.Object переопределяя Equals и GetHashCode, Equals переопределяется так, что при сравнении двух структур сравниваются значения их полей,а не ссылки, в случае GetHashCode - вычисляется хеш по всем полям структуры, в отличии от хеша адреса в куче(у ссылочных типов)
  49.  
  50. Иногда стоит предпочитать структуры классам, например, когда нужно структурное сравнение объектов, но необходимо помнить, что в таком случае в стеке будут храниться все созданные экземпляры.Мартин Фаулер называет подобные объекты - record'ами
  51.  
  52. Также сразу при объявлении структуры происходит ее инициализация(хотя компилятор и не дает обращаться к полям не проинициализированной ключевым словом new структуры), поэтому не может возникнуть NRE
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement