17 и 24.09.2022

История Java. Безопасная работа с памятью. Write once, compile once, run everythere.
Компиляция, байт-код, JVM и JIT.
История .NET и C#.
.NET Framework и .NET Core, теперь .NET.
Версия рантайм и версия языка.
Current и LTS версии.
Среды разработки (IDEA, Visual Studio, Rider).

---
01.10.2022

Первые программы hello world. Первый класс. Пространства имен (packages/namespaces). Naming conventions (camelCasing в Java, PascalCasing в C#). Статические методы и методы экземпляров классов.

Стек и куча. Локальные переменные и параметры, размещение объектов, reference-типы. Как работает вызов метода, как работает рекурсия.

---
08.10.2022

Примитивные типы (Java) и простые типы (C#): bool/boolean и числовые. Тип decimal (только в C#, в Java используется BigDecimal, но это класс и он поддерживает multiple precision) и его примение (проблемы float/double в финансовых приложениях).

Классы: поля, методы, конструкторы. Перегрузка (overload) методов и конструкторов. Свойства (есть в C#, нет в Java - как элемента языка, но концепция такая есть, реализуется просто методами getValue/setValue или isProp/setProp для boolean).

Модификаторы доступа: private/protected/public (не упомянули еще default модификатор в Java и internal/internal protected/internal private).

3 кита ООП: инкапсуляция, наследование, полиморфизм. Что мы под этим понимаем. Наследование, виртуальные методы и переопределение (override) в Java и C#.
Java: по умолчанию все методы виртуальные, ключевых слов virtual и override нет, при переопределении рекомендуется (хотя компилятор это не требует) добавлять аннотацию @Override.
C#: по умолчанию все методы невиртуальные, виртуальный метод надо помечать ключевым словом virtual, при переопределении использовать ключевое слово override.
Java: final на уровне класса запрещает его дальнейшее наследование, final на уровне метода запрещает его дальнейшее переопределение. В C# тоже самое достигается с помощью sealed.
Java: final на уровне полей - static final для объявления констант, final для неизменяемых. В C# для констант есть ключевое слово const, для неизменяемых полей - readonly (не точно совпадает по использованию с final в Java, но близко).

---
15.10.2022

Немного вернулись к теме прошлого занятия. Как происходит вызов виртуального метода: не надо идти по цепочке наследования в поиске последнего override. VMT (virtual method table) позволяет сделать вызов за O(1). Вызов невиртуального метода получается совсем немного быстрее, т.к. не требуется обращение к VMT. Разница не стоит того, чтобы беспокоиться, важно другое: виртуальный метод не может быть inlined, внутри hot path это может очень сильно влиять на производительность.

Обсудили, что такое inlining. Его делает рантайм (JVM/CLR) по своему усмотрению (если метод часто вызывается и при этом он небольшой). В C# можно попытаться подсказать (без гарантий, что это будет выполнено), что надо инлайнить метод с помощью аттрибута
[MethodImpl(MethodImplOptions.AggressiveInlining)]
В Java такого способа нет (не очень-то и хотелось; еще раз: не надо заниматься premature optimization, JIT сделает многие вещи лучше вас).

Обсудили, что такое аттрибуты в C# (аналог аннотаций в Java: прошлый раз мы видели аннотацию @Override). 

Функции с переменным числом параметров (по факту - массив параметров одного типа).
Java: void f(int... a)
C#: void f(params int[] a)
(при этом могут быть и другие фиксированные параметры, но только перед параметром вида .../params).

Все дальнейшее - только в C#, аналогов в Java нет.
1) параметры по умолчанию: int f(int a, int b = 0)
2) вызов функций с использованием именованных параметров (удобно при большом количестве параметров по умолчанию)
3) out/ref параметры: bool get(out int value), void change(ref int value)
4) индексные свойства (indexers) - возможность сделать класс с обращением по индексу произвольного типа: a[5], a["abc"].
5) ref свойства, зачем это надо: пример типа Span<>, появившегося относительно недавно.
