KnigkinDom.org» » »📕 Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Книгу Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен читаем онлайн бесплатно полную версию! Чтобы начать читать не надо регистрации. Напомним, что читать онлайн вы можете не только на компьютере, но и на андроид (Android), iPhone и iPad. Приятного чтения!

1 ... 148 149 150 151 152 153 154 155 156 ... 407
Перейти на страницу:

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
значение myInt

  Console.WriteLine("Address of myInt {0:X}", (int)&ptrToMyInt);

                  // адрес myInt

}

В результате запуска этого метода из блока unsafe вы получите такой вывод:

**** Print Value And Address ****

Value of myInt 123

Address of myInt 90F7E698

Небезопасная (и безопасная) функция обмена

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

unsafe static void UnsafeSwap(int* i, int* j)

{

  int temp = *i;

  *i = *j;

  *j = temp;

}

Очень похоже на язык С, не так ли? Тем не менее, учитывая предшествующую работу, вы должны знать, что можно было бы написать безопасную версию алгоритма обмена с применением ключевого слова ref языка С#:

static void SafeSwap(ref int i, ref int j)

{

  int temp = i;

  i = j;

  j = temp;

}

Функциональность обеих версий метода идентична, доказывая тем самым, что прямые манипуляции указателями в C# не являются обязательными. Ниже показана логика вызова, использующая безопасные операторы верхнего уровня, но с небезопасным контекстом:

Console.WriteLine("***** Calling method with unsafe code *****");

// Значения, подлежащие обмену.

int i = 10, j = 20;

// "Безопасный" обмен значений местами.

Console.WriteLine("n***** Safe swap *****");

Console.WriteLine("Values before safe swap: i = {0}, j = {1}", i, j);

SafeSwap(ref i, ref j);

Console.WriteLine("Values after safe swap: i = {0}, j = {1}", i, j);

// "Небезопасный" обмен значений местами.

Console.WriteLine("n***** Unsafe swap *****");

Console.WriteLine("Values before unsafe swap: i = {0}, j = {1}", i, j);

unsafe { UnsafeSwap(&i, &j); }

Console.WriteLine("Values after unsafe swap: i = {0}, j = {1}", i, j);

Console.ReadLine();

Доступ к полям через указатели (операция ->)

Теперь предположим, что определена простая безопасная структура Point:

struct Point

{

  public int x;

  public int y;

  public override string ToString() => $"({x}, {y})";

}

В случае объявления указателя на тип Point для доступа к открытым членам структуры понадобится применять операцию доступа к полям (имеющую вид ->). Как упоминалось в табл. 11.2, она представляет собой небезопасную версию стандартной (безопасной) операции точки (.). В сущности, используя операцию обращения к указателю (*), можно разыменовывать указатель для применения операции точки. Взгляните на следующий небезопасный метод:

static unsafe void UsePointerToPoint()

{

  // Доступ к членам через указатель.

  Point;

  Point* p = &point;

  p->x = 100;

  p->y = 200;

  Console.WriteLine(p->ToString());

  // Доступ к членам через разыменованный указатель.

  Point point2;

  Point* p2 = &point2;

  (*p2).x = 100;

  (*p2).y = 200;

  Console.WriteLine((*p2).ToString());

}

Ключевое слово stackalloc

В небезопасном контексте может возникнуть необходимость в объявлении локальной переменной, для которой память выделяется непосредственно в стеке вызовов (и потому она не обрабатывается сборщиком мусора .NET Core). Для этого в языке C# предусмотрено ключевое слово stackalloc, которое является эквивалентом функции _аllоса библиотеки времени выполнения С. Вот простой пример:

static unsafe string UnsafeStackAlloc()

{

  char* p = stackalloc char[52];

  for (int k = 0; k < 52; k++)

  {

    p[k] = (char)(k + 65)k;

  }

  return new string(p);

Закрепление типа посредством ключевого слова fixed

В предыдущем примере вы видели, что выделение фрагмента памяти внутри небезопасного контекста может делаться с помощью ключевого слова stackalloc. Из-за природы операции stackalloc выделенная память очищается, как только выделяющий ее метод возвращает управление (т.к. память распределена в стеке). Однако рассмотрим более сложный пример. Во время исследования операции -> создавался тип значения по имени Point. Как и все типы значений, выделяемая его экземплярам память исчезает из стека по окончании выполнения. Предположим, что тип Point взамен определен как ссылочный:

class PointRef // <= Renamed and retyped.

{

  public int x;

  public int y;

  public override string ToString() => $"({x}, {y})";

}

Как вам известно, если в вызывающем коде объявляется переменная типа Point, то память для нее выделяется в куче, поддерживающей сборку мусора. И тут возникает животрепещущий вопрос: а что если небезопасный контекст пожелает взаимодействовать с этим объектом (или любым другим объектом из кучи)? Учитывая, что сборка мусора может произойти в любое время, вы только вообразите, какие проблемы возникнут при обращении к членам Point именно в тот момент, когда происходит реорганизация кучи! Теоретически может случиться так, что небезопасный контекст попытается взаимодействовать с членом, который больше не доступен или был перемещен в другое место кучи после ее очистки с учетом поколений (что является очевидной проблемой).

Для фиксации переменной ссылочного типа в памяти из небезопасного контекста язык C# предлагает ключевое слово fixed. Оператор fixed устанавливает указатель на управляемый тип и "закрепляет" такую переменную на время выполнения кода. Без fixed от указателей на управляемые переменные было бы мало толку, поскольку сборщик мусора может перемещать переменные в памяти непредсказуемым образом. (На самом деле компилятор C# даже не позволит установить указатель на управляемую переменную, если оператор fixed отсутствует.)

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

unsafe static void UseAndPinPoint()

{

  PointRef pt = new PointRef

  {

    x = 5,

    y = 6

  };

  // Закрепить указатель pt на месте, чтобы он не мог

1 ... 148 149 150 151 152 153 154 155 156 ... 407
Перейти на страницу:
Отзывы - 0

Прочитали книгу? Предлагаем вам поделится своим отзывом от прочитанного(прослушанного)! Ваш отзыв будет полезен читателям, которые еще только собираются познакомиться с произведением.


Уважаемые читатели, слушатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор knigkindom.ru.


Партнер

Новые отзывы

  1. Гость Татьяна Гость Татьяна24 сентябрь 22:20 Как то не очень... Невеста по ошибке. Я не дам тебе развод - Майя Линн
  2. Римма Римма24 сентябрь 21:52 Почему главные героинитпкие идиотки? И сюжет не плохой, и написано хорошо. Но как героиня - так дура дурой.... Хозяйка маленького дома, или Любимая для дракона - Кира Рамис
  3. Римма Римма20 сентябрь 12:27 Много ненужных пояснений и отступлений. Весь сюжет теряет свою привлекательность. Героиня иногда так тупит, что читать не... Хозяйка приюта для перевертышей и полукровок - Елена Кутукова
Все комметарии
Новое в блоге