Pull to refresh

[DotNetBook] Структура экземпляров типов и VMT

Reading time 14 min
Views 12K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *
Tutorial
С этой статьей я продолжаю публиковать целую серию статей, результатом которой будет книга по работе .NET CLR, и .NET в целом.

Вся книга будет доступна на GitHub: CLR Book. Так что Issues и Pull Requests приветствуются :)

Это — выжимка из главы про структуру типов и их VMT.

Структура объектов в памяти


До сих, говоря про разницу между значимыми и ссылочными типами, мы затрагивали эту тему с высоты конечного разработчика. Т.е. мы не смотрели на то как они в реальности устроены на уровне CLR, как сделаны те или иные механики внутри каждого из них. Мы смотрели фактически на конечный результат. Однако, чтобы понимать суть вещей глубже и чтобы отбросить в сторону последние оставшиеся мысли о какой-либо магии, происходящей внутри CLR стоит заглянуть в самые ее потроха.

Примечание


Глава, опубликованная на Хабре не обновляется и возможно, уже несколько устарела. А потому, прошу обратиться за более свежим текстом к оригиналу:




Читать дальше →
Total votes 35: ↑34 and ↓1 +33
Comments 3

[DotNetBook] Stackalloc: забытая команда C#

Reading time 8 min
Views 25K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *
Tutorial
С этой статьей я продолжаю публиковать целую серию статей, результатом которой будет книга по работе .NET CLR, и .NET в целом. Вся книга будет доступна на GitHub (ссылка в конце статьи).

В C# существует достаточно интересное и очень редко используемое ключевое слово stackalloc. Оно настолько редко встречается в коде (тут я даже со словом «редко» преуменьшил. Скорее, «никогда»), что найти подходящий пример его использования достаточно трудно а уж придумать тем более трудно: ведь если что-то редко используется, то и опыт работы с ним слишком мал. А все почему? Потому что для тех, кто наконец решается выяснить, что делает эта команда, stackalloc становится более пугающим чем полезным: темная сторона stackalloc — unsafe код. Тот результат, что он возвращает не является managed указателем: значение — обычный указатель на участок не защищенной памяти. Причем если по этому адресу сделать запись уже после того как метод завершил работу, вы начнете писать либо в локальные переменные некоторого метода или же вообще перетрете адрес возврата из метода, после чего приложение закончит работу с ошибкой. Однако наша задача — проникнуть в самые уголки и разобраться, что в них скрыто. И понять, в частности, что если нам дали этот инструмент, то не просто же так, чтобы мы смогли найти секретные грабли и наступить на них со всего маху. Наоборот: нам дали этот инструмент чтобы мы смогли им воспользоваться и делать поистине быстрый софт. Я, надеюсь, вдохновил вас? Тогда начнем.

Примечание


Глава, опубликованная на Хабре не обновляется и возможно, уже несколько устарела. А потому, прошу обратиться за более свежим текстом к оригиналу:





Читать дальше →
Total votes 55: ↑53 and ↓2 +51
Comments 16

[DotNetBook] Span: новый тип данных .NET

Reading time 14 min
Views 30K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *
Tutorial

С этой статьей я продолжаю публиковать целую серию статей, результатом которой будет книга по работе .NET CLR, и .NET в целом (уже готово около 200 страниц книги, так что добро пожаловать в конец статьи за ссылками).


Как язык, так и платформа существуют уже много лет: и все это время существовало множество средств для работы с неуправляемым кодом. Так почему же сейчас выходит очередной API для работы с неуправляемым кодом если по сути он существовал уже много-много лет? Для того чтобы ответить на этот вопрос достаточно понять чего не хватало нам раньше.


Разработчики платформы и раньше пытались нам помочь скрасить будни разработки с использованием неуправляемых ресурсов: это и автоматические врапперы для импортируемых методов. И маршаллинг, который в большинстве случаев работатет автоматически. Это также инструкция stackallloc, о которой говорится в главе про стек потока. Однако, как по мне если ранние разработчики с использованием языка C# приходили из мира C++ (как сделал это и я), то сейчас они приходят из более высокоуровневых языков (я, например, знаю разработчика, который пришел из JavaScript). А что это означает? Это означает что люди со все большим подозрением начинают относиться к неуправляемым ресурсам и конструкциям, близким по духу к C/C++ и уж тем более — к языку Ассемблера.


Примечание


Глава, опубликованная на Хабре не обновляется и возможно, уже несколько устарела. А потому, прошу обратиться за более свежим текстом к оригиналу:


Читать дальше →
Total votes 38: ↑38 and ↓0 +38
Comments 24

[DotNetBook] Исключения: архитектура системы типов

Reading time 14 min
Views 7.1K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *
Tutorial

С этой статьей я продолжаю публиковать целую серию статей, результатом которой будет книга по работе .NET CLR, и .NET в целом. За ссылками — добро пожаловать под кат.


Архитектура исключительной ситуации


Наверное, один из самых важных вопросов, который касается темы исключений — это вопрос построения архитектуры исключений в вашем приложении. Этот вопрос интересен по многим причинам. Как по мне так основная — это видимая простота, с которой не всегда очевидно, что делать. Это свойство присуще всем базовым конструкциям, которые используются повсеместно: это и IEnumerable, и IDisposable и IObservable и прочие-прочие. С одной стороны, своей простотой они манят, вовлекают в использование себя в самых разных ситуациях. А с другой стороны, они полны омутов и бродов, из которых, не зная, как иной раз и не выбраться вовсе. И, возможно, глядя на будущий объем у вас созрел вопрос: так что же такого в исключительных ситуациях?


Примечание


Глава, опубликованная на Хабре не обновляется и возможно, уже несколько устарела. А потому, прошу обратиться за более свежим текстом к оригиналу:


Читать дальше →
Total votes 34: ↑34 and ↓0 +34
Comments 0

[DotNetBook] События об исключительных ситуациях и как на пустом месте получить StackOverflow и ExecutionEngineException

Reading time 8 min
Views 5.1K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *
Tutorial

События об исключительных ситуациях


В общем случае мы не всегда знаем о тех исключениях, которые произойдут в наших программах потому что практически всегда мы используем что-то, что написано другими людьми и что находится в других подсистемах и библиотеках. Мало того что возможны самые разные ситуации в вашем собственном коде, в коде других библиотек, так еще и существует множество проблем, связанных с исполнением кода в изолированных доменах. И как раз в этом случае было бы крайне полезно уметь получать данные о работе изолированного кода. Ведь вполне реальной может быть ситуация, когда сторонний код перехватывает все без исключения ошибки, заглушив их fault блоком:


try {
    // ...
} catch {
    // do nothing, just to make code call more safe
}

В такой ситуации может оказаться что выполнение кода уже не так безопасно как выглядит, но сообщений о том что произошли какие-то проблемы мы не имеем. Второй вариант — когда приложение глушит некоторое, пусть даже легальное, исключение. А результат — следующее исключение в случайном месте вызовет падение приложения в некотором будущем от случайной казалось бы ошибки. Тут хотелось бы иметь представление, какая была предыстория этой ошибки. Каков ход событий привел к такой ситуации. И один из способов сделать это возможным — использовать дополнительные события, которые относятся к исключительным ситуациям: AppDomain.FirstChanceException и AppDomain.UnhandledException.


Примечание


Глава, опубликованная на Хабре не обновляется и возможно, уже несколько устарела. А потому, прошу обратиться за более свежим текстом к оригиналу:


Читать дальше →
Total votes 30: ↑30 and ↓0 +30
Comments 3

[DotNetBook] Время занимательных историй: исключительно исключительные ситуации

Reading time 1 min
Views 5.1K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *
Tutorial

Существует ряд исключительных ситуаций, которые скажем так… Несколько более исключительны чем другие. Причем если попытаться их классифицировать, то как и было сказано в самом начале главы, есть исключения родом из самого .NET приложения, а есть исключения родом из unsafe мира. Их в свою очередь можно разделить на две подкатегории: иcключительные ситуации ядра CLR (которое по своей сути — unsafe) и любой unsafe код внешних библиотек.


Давайте поговорим про эти особые исключительные ситуации.


ThreadAbortException


Вообще, это может показаться не очевидным, но существует четыре типа Thread Abort.


Примечание


Глава, опубликованная на Хабре не обновляется и возможно, уже несколько устарела. А потому, прошу обратиться за более свежим текстом к оригиналу:


Читать дальше →
Total votes 37: ↑35 and ↓2 +33
Comments 10

[DotNetBook] Span, Memory и ReadOnlyMemory

Reading time 6 min
Views 12K
Seminars by Stanislav Sidristy corporate blog .NET *C# *
Tutorial

Этой статьей я продолжаю публиковать целую серию статей, результатом которой будет книга по работе .NET CLR, и .NET в целом. За ссылками — добро пожаловать под кат.


Memory<T> и ReadOnlyMemory<T>


Визуальных отличий Memory<T> от Span<T> два. Первое — тип Memory<T> не содержит ограничения ref в заголовке типа. Т.е., другими словами, тип Memory<T> имеет право находиться не только на стеке, являясь либо локальной переменной либо параметром метода либо его возвращаемым значением, но и находиться в куче, ссылаясь оттуда на некоторые данные в памяти. Однако эта маленькая разница создает огромную разницу в поведении и возможностях Memory<T> в сравнении с Span<T>. В отличии от Span<T>, который представляет собой средство пользования неким буфером данных для некоторых методов, тип Memory<T> предназначен для хранения информации о буфере, а не для работы с ним.


Примечание


Глава, опубликованная на Хабре не обновляется и возможно, уже несколько устарела. А потому, прошу обратиться за более свежим текстом к оригиналу:


Читать дальше →
Total votes 40: ↑39 and ↓1 +38
Comments 2

.NET Reference Types vs Value Types. Part 1

Reading time 16 min
Views 6.3K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *

First, let’s talk about Reference Types and Value Types. I think people don’t really understand the differences and benefits of both. They usually say reference types store content on the heap and value types store content on the stack, which is wrong.


Let’s discuss the real differences:


  • A value type: its value is an entire structure. The value of a reference type is a reference to an object. – A structure in memory: value types contain only the data you indicated. Reference types also contain two system fields. The first one stores 'SyncBlockIndex', the second one stores the information about a type, including the information about a Virtual Methods Table (VMT).
  • Reference types can have methods that are overridden when inherited. Value types cannot be inherited.
  • You should allocate space on the heap for an instance of a reference type. A value type can be allocated on the stack, or it becomes the part of a reference type. This sufficiently increases the performance of some algorithms.

However, there are common features:


  • Both subclasses can inherit the object type and become its representatives.

Let’s look closer at each feature.


This chapter was translated from Russian jointly by author and by professional translators. You can help us with translation from Russian or English into any other language, primarily into Chinese or German.

Also, if you want thank us, the best way you can do that is to give us a star on github or to fork repository github/sidristij/dotnetbook.

Read more →
Total votes 33: ↑32 and ↓1 +31
Comments 1

.NET Reference Types vs Value Types. Part 2

Reading time 10 min
Views 2.9K
Seminars by Stanislav Sidristy corporate blog .NET *C# *Development for Windows *


The Object base type and implementation of interfaces. Boxing


It seems we came through hell and high water and can nail any interview, even the one for .NET CLR team. However, let's not rush to microsoft.com and search for vacancies. Now, we need to understand how value types inherit an object if they contain neither a reference to SyncBlockIndex, not a pointer to a virtual methods table. This will completely explain our system of types and all pieces of a puzzle will find their places. However, we will need more than one sentence.


Now, let's remember again how value types are allocated in memory. They get the place in memory right where they are. Reference types get allocation on the heap of small and large objects. They always give a reference to the place on the heap where the object is. Each value type has such methods as ToString, Equals and GetHashCode. They are virtual and overridable, but don’t allow to inherit a value type by overriding methods. If value types used overridable methods, they would need a virtual methods table to route calls. This would lead to the problems of passing structures to unmanaged world: extra fields would go there. As a result, there are descriptions of value type methods somewhere, but you cannot access them directly via a virtual methods table.


This may bring the idea that the lack of inheritance is artificial


This chapter was translated from Russian jointly by author and by professional translators. You can help us with translation from Russian or English into any other language, primarily into Chinese or German.

Also, if you want thank us, the best way you can do that is to give us a star on github or to fork repository github/sidristij/dotnetbook.
Read more →
Total votes 34: ↑34 and ↓0 +34
Comments 0

Disposable pattern (Disposable Design Principle) pt.1

Reading time 9 min
Views 3.2K
Programming *.NET *C# *


Disposable pattern (Disposable Design Principle)


I guess almost any programmer who uses .NET will now say this pattern is a piece of cake. That it is the best-known pattern used on the platform. However, even the simplest and well-known problem domain will have secret areas which you have never looked at. So, let’s describe the whole thing from the beginning for the first-timers and all the rest (so that each of you could remember the basics). Don’t skip these paragraphs — I am watching you!


If I ask what is IDisposable, you will surely say that it is


public interface IDisposable
{
    void Dispose();
}

What is the purpose of the interface? I mean, why do we need to clear up memory at all if we have a smart Garbage Collector that clears the memory instead of us, so we even don’t have to think about it. However, there are some small details.


This chapter was translated from Russian jointly by author and by professional translators. You can help us with translation from Russian or English into any other language, primarily into Chinese or German.

Also, if you want thank us, the best way you can do that is to give us a star on github or to fork repository github/sidristij/dotnetbook.
Read more →
Total votes 18: ↑17 and ↓1 +16
Comments 0

Disposable pattern (Disposable Design Principle) pt.2

Reading time 8 min
Views 2.8K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *


SafeHandle / CriticalHandle / SafeBuffer / derived types


I feel I’m going to open the Pandora’s box for you. Let’s talk about special types: SafeHandle, CriticalHandle and their derived types.


This is the last thing about the pattern of a type that gives access to an unmanaged resource. But first, let’s list everything we usually get from unmanaged world:


The first and obvious thing is handles. This may be an meaningless word for a .NET developer, but it is a very important component of the operating system world. A handle is a 32- or 64-bit number by nature. It designates an opened session of interaction with an operating system. For example, when you open a file you get a handle from the WinApi function. Then you can work with it and do Seek, Read or Write operations. Or, you may open a socket for network access. Again an operating system will pass you a handle. In .NET handles are stored as IntPtr type;


This chapter was translated from Russian jointly by author and by professional translators. You can help us with translation from Russian or English into any other language, primarily into Chinese or German.

Also, if you want thank us, the best way you can do that is to give us a star on github or to fork repository github/sidristij/dotnetbook.
Read more →
Total votes 24: ↑23 and ↓1 +22
Comments 0

Disposable pattern (Disposable Design Principle) pt.3

Reading time 15 min
Views 3.5K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *


Multithreading


Now let’s talk about thin ice. In the previous sections about IDisposable we touched one very important concept that underlies not only the design principles of Disposable types but any type in general. This is the object’s integrity concept. It means that at any given moment of time an object is in a strictly determined state and any action with this object turns its state into one of the variants that were pre-determined while designing a type of this object. In other words, no action with the object should turn it into an undefined state. This results in a problem with the types designed in the above examples. They are not thread-safe. There is a chance the public methods of these types will be called when the destruction of an object is in progress. Let’s solve this problem and decide whether we should solve it at all.


This chapter was translated from Russian jointly by author and by professional translators. You can help us with translation from Russian or English into any other language, primarily into Chinese or German.

Also, if you want thank us, the best way you can do that is to give us a star on github or to fork repository github/sidristij/dotnetbook.
Read more →
Total votes 12: ↑11 and ↓1 +10
Comments 0

Memory and Span pt.1

Reading time 7 min
Views 3.4K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *

Starting from .NET Core 2.0 and .NET Framework 4.5 we can use new data types: Span and Memory. To use them, you just need to install the System.Memory nuget package:


PM> Install-Package System.Memory

These data types are notable because the CLR team has done a great job to implement their special support inside the code of .NET Core 2.1+ JIT compiler by embedding these data types right into the core. What kind of data types are these and why are they worth a whole chapter?


If we talk about problems that made these types appear, I should name three of them. The first one is unmanaged code.


Both the language and the platform have existed for many years along with means to work with unmanaged code. So, why release another API to work with unmanaged code if the former basically existed for many years? To answer this question, we should understand what we lacked before.


This chapter was translated from Russian jointly by author and by professional translators. You can help us with translation from Russian or English into any other language, primarily into Chinese or German.

Also, if you want thank us, the best way you can do that is to give us a star on github or to fork repository github/sidristij/dotnetbook.
Read more →
Total votes 22: ↑21 and ↓1 +20
Comments 2

Memory and Span pt.2

Reading time 9 min
Views 3K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *


Span<T> usage examples


A human by nature cannot fully understand the purpose of a certain instrument until he or she gets some experience. So, let’s turn to some examples.


ValueStringBuilder


One of the most interesting examples in respect to algorithms is the ValueStringBuilder type. However, it is buried deep inside mscorlib and marked with the internal modifier as many other very interesting data types. This means we would not find this remarkable instrument for optimization if we haven’t researched the mscorlib source code.


What is the main disadvantage of the StringBuilder system type? Its main drawback is the type and its basis — it is a reference type and is based on char[], i.e. a character array. At least, this means two things: we use the heap (though not much) anyway and increase the chances to miss the CPU cash.


Another issue with StringBuilder that I faced is the construction of small strings, that is when the resulting string must be short e.g. less than 100 characters. Short formatting raises issues on performance.


This chapter was translated from Russian jointly by author and by professional translators. You can help us with translation from Russian or English into any other language, primarily into Chinese or German.

Also, if you want thank us, the best way you can do that is to give us a star on github or to fork repository github/sidristij/dotnetbook.
Read more →
Total votes 12: ↑11 and ↓1 +10
Comments 0

Memory and Span pt.3

Reading time 10 min
Views 2.3K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *


Memory<T> and ReadOnlyMemory<T>


There are two visual differences between Memory<T> and Span<T>. The first one is that Memory<T> type doesn’t contain ref modifier in the header of the type. In other words, the Memory<T> type can be allocated both on the stack while being either a local variable, or a method parameter, or its returned value and on the heap, referencing some data in memory from there. However, this small difference creates a huge distinction in the behavior and capabilities of Memory<T> compared to Span<T>. Unlike Span<T> that is an instrument for some methods to use some data buffer, the Memory<T> type is designed to store information about the buffer, but not to handle it. Thus, there is the difference in API.


  • Memory<T> doesn’t have methods to access the data that it is responsible for. Instead, it has the Span property and the Slice method that return an instance of the Span type.
  • Additionally, Memory<T> contains the Pin() method used for scenarios when a stored buffer data should be passed to unsafe code. If this method is called when memory is allocated in .NET, the buffer will be pinned and will not move when GC is active. This method will return an instance of the MemoryHandle structure, which encapsulates GCHandle to indicate a segment of a lifetime and to pin array buffer in memory.

This chapter was translated from Russian jointly by author and by professional translators. You can help us with translation from Russian or English into any other language, primarily into Chinese or German.

Also, if you want thank us, the best way you can do that is to give us a star on github or to fork repository github/sidristij/dotnetbook.
Read more →
Total votes 9: ↑9 and ↓0 +9
Comments 0

The architecture of an exceptional situation: pt.2 of 4

Reading time 13 min
Views 1.2K
Seminars by Stanislav Sidristy corporate blog Programming *.NET *C# *

I guess one of the most important issues in this topic is building an exception handling architecture in your application. This is interesting for many reasons. And the main reason, I think, is an apparent simplicity, which you don’t always know what to do with. All the basic constructs such as IEnumerable, IDisposable, IObservable, etc. have this property and use it everywhere. On the one hand, their simplicity tempts to use these constructs in different situations. On the other hand, they are full of traps which you might not get out. It is possible that looking at the amount of information we will cover you’ve got a question: what is so special about exceptional situations?


However, to make conclusions about building the architecture of exception classes we should learn some details about their classification. Because before building a system of types that would be clear for the user of code, a programmer should determine when to choose the type of error and when to catch or skip exceptions. So, let’s classify the exceptional situations (not the types of exceptions) based on various features.

Read more →
Total votes 10: ↑9 and ↓1 +8
Comments 0