This repository has been archived on 2024-08-23. You can view files and clone it, but cannot push or open issues or pull requests.
lessons/C#/C#.md
2023-10-15 08:54:36 +00:00

592 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# C\#
## Project file
Project file - файл для конфигурации проекта в формате xml
Поля:
* OutputType (Exe | Dll) - во что компилировать
* TargetFramework (net7.0) - версия .NET
## Переменные
```C#
string name = "Tom";
string name2;
name2 = "Bob";
```
## Константы
```C#
const string NAME = "Tom";
```
## Типы данных
* bool
* sbyte (signed byte)
* byte
* short - 16 байт
* ushort (unsigned)
* int - 32 байта
* uint
* long - 64 байта
* ulong
* char - 16 байт. Знак unicode
* float 32 байт
* double - 64 байта
* decimal - 128 бит
* string
* object - аля Python Object
Числа в формате 3.14 по умолчанию double. Если нужен float или decimal, то используются суффиксы
```C#
float a = 3.14f;
decimal b = 3.14m;
```
Для целочисленных по умолчанию int
```C#
int a = 5;
uint b = 5u;
long c = 5l;
ulong d = 5ul;
```
## Неявная типизация
```C#
var hello = "Hello world";
```
Для var объявление и инициализация должны идти вместе
```C#
// Так низя: ошибка
var c;
c = 5;
```
## Вывод в терминал
```C#
Console.WriteLine("Привет");
Console.Write("Привет ");
Console.Write("Мир");
```
Выведет:
```text
Привет
Привет мир
```
## Форматированный вывод
```C#
string name = "John";
string age = 34;
Console.WriteLine($"{name} is {age} years old")
```
## Ввод данных
```C#
string? name = Console.ReadLine();
int foo = Convert.ToInt32(Console.ReadLine());
```
## Простые операторы
* \+
* \-
* \*
* /
* %
## Преобразование базовых типов данных
Операция сложения и вычитания возвращает int, если типы, на которые применяется операция, <= int (byte, short, int)
### Неявное преобразование
Работает только на расширение
```C#
byte a = 4;
ushort = a;
```
### Явное преобразовывание
Работает на расширение и на сужение
```C#
byte a = 5;
byte b = 4;
byte c = (byte) (a+b);
```
## Ветвление
```C#
int a = 5;
if (a == 5) {
Console.WriteLine("It works");
} else {
Console.WriteLine("Cosmic ray!");
}
```
### Тернарный оператор
Краткая возвращающая форма if
```C#
int x = 3;
int y = 5;
string z = x < y ? "Works" : "Cosmic ray";
```
### Switch
```C#
int number = 1;
switch (number) {
case 1:
Console.WriteLine("case 1");
goto case 5;
case 3:
Console.WriteLine("case 3");
break;
case 5:
Console.WriteLine("case 5");
break;
default:
Console.WriteLine("case whatever");
break;
}
```
### Циклы
Всё как в С++
* while
* do-while
* for
* foreach
## Массивы
Массивы позволяют хранить заранее известное кол-во элементов вместе
### Инициализация массивов
```C#
int[] a = new int[3] {10, 20, 30};
double[] b = new double[5];
float[] c = {1.5f, 2.3f}; // Поймёт, что нужна длина 2
```
### Длинна массивов
```C#
int[] a = {10, 20};
int len = a.Length;
```
### Методы
```C#
int[] a = {10, 30, 20};
Array.IndexOf(a, 10) // Вернёт 0. -1, если не найдёт.
Array.Sort(a); // Сортирует по возрастанию. Станет {10, 20, 30}
```
### Двумерный массив
```C#
int[,] a = new int[10,10];
```
### Динамический массив
```C#
using System.Collections.Generic;
List<string> words = new List<string> ();
words.Add("Foo");
words.Add("Bar");
words.RemoveAt(1);
```
## Random
```C#
Random r = new Random();
int a = r.Next(); // От 0 до 2 миллиардов
int b = r.Next(5); // От 0 до 5 (не включительно)
int c = r.Next(3, 5); // От 3 до 5
```
## Функции
```C#
void Foo() {
Console.WriteLine("Hello");
}
// Краткая форма
void Bar() => Console.WriteLine("Hi");
```
### Параметры функции
```C#
int Sum(int x, int y) => x + y; // Тут x и y - параметры
Sum(5, 6); // Тут 5 и 6 - аргументы
```
#### Необязательные параметры
```C#
void PrintPerson(string name, int age = 1) {
Console.WriteLine($"{name} - {age}");
}
PrintPerson("John", 5);
PrintPerson(age: 5, name: "Bob"); // Именованные параметры
```
#### Передача по ссылке
При передаче по ссылке и зменения внутри функции меняют оригинальное значение
```C#
void Inc(ref int a) {
a++;
}
void BadInc(int a) {
a++;
}
int b = 5;
Inc(ref b); // b == 6
BadInc(b); // b осталась 6
Inc(b); // Так низя
Inc(5); // И так низя
Inc(ref 5); // И так тоже низя
```
#### Выходной параметр
Функция может иметь несколько выходных параметров, а так лучше return
```C#
void Sum(int a, int b, out int result) {
result = a + b;
}
int result;
Sum(5, 6, out result);
```
#### Входные параментры
Передача по неизменяемой ссылке. Судя по всему полезно только для массивов
```C#
int Sum(in int a, in int b) {
return a + b;
}
int a = 5;
int b = 6;
Sum(a, b);
```
#### params
*params* позволяет передать не определённое кол-во параметров. После него не может быть больше параметров
```C#
int Sum(params int[] nums) {
int sum = 0;
foreach (int i in nums) {
sum += i;
}
return sum;
}
int[] nums = {1, 2, 3, 4};
Sum(nums);
Sum(1, 2, 3);
Sum(20);
Sum();
```
### Возвращение значений
```C#
int Sum1(int a, int b) {
return a + b;
}
int Sum2(int a, int b) => a + b;
```
### Рекурсия
```C#
int Factorial(int n) {
if (n == 0) return 1;
return n * Factorial(n - 1);
}
```
### Функции внути функций
```C#
int Sum2Arr(int[] arr1, int[] arr2) {
int Sum(int[] arr) {
int result = 0;
foreach (int i in arr) {
result += i;
}
return result;
}
return Sum(arr1) + Sum(arr2);
}
```
## Enum
Enum используется для хранения состояния
```C#
enum Operation {
Add,
Sub
}
Operation foo = Operation.Add;
```
### Тип констант перечисления
```C#
enum Time: byte {
Morning,
Afternoon,
Evening,
Night
}
```
Тип обязательно должен быть целочисленным. По умолчанию int
### Задание значения для Enum
```C#
enum DayTime {
Morning = 3,
Afternoon // 4
}
```
## OOP
OOP - зло, C# - OOP -> C# - зло
```C#
namespace Foo {
internal class Enemy {
public int hp;
public int armor;
public int damage;
public Enemy(int hp, int armor, int damage) {
this.hp = hp;
this.armor = armor;
this.damage = damage;
}
public void Move() {
Console.WriteLine("I am moving");
}
public void Attack() {
Console.WriteLine("I am attacking");
}
}
}
```
Конструкторов может быть несколько
### Инициализаторы
```C#
Person tom = new Person {name = "Tom", company = { title = "Microsoft" }};
class Person {
public string name = "Undefined";
public Company company;
public Person() {
company = new Company();
}
}
class Company {
public string title = "Unknown";
}
```
### Деконструкторы
Деконструкторы - методы, чтобы "разобрать" объект на составные части
```C#
class Person {
public string name;
public string age;
public void Deconstruct(out string personName, out int PersonAge) {
personName = name;
personAge = age;
}
}
```
### Структуры
Структуру - аналог классов с особенностями:
* Храняться на стеке
* Нет наследования: нельзя использовать *abstract*, *virtual*, *protected*
* При присваивании создаются копия
* Имеется ключевое слово with
```C#
Person tom;
tom.name = "Tom";
tom.age = 1;
Person bob = tom with { name = "Bob" };
Person Alice = new Person { name = "Alice", age = 5 };
Person Jan = new Person("Jan", 10);
struct Person
{
public string name;
public int age;
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
}
```
### Типы значений и ссылочные типы
Типы значений (значимые типы) хранятся на стеке. При присваивании значимых типов создаётся копия. К таким типам относятся:
* Целочисленные значения
* Числа с плавающей точкой
* *decimal*
* *bool*
* *char*
* Перечисления
* Структуры
Ссылочные типы в куче, а ссылка на них в стеке. При присваивании ссылочных типов копируется только ссылка. К ним относятся:
* *string*
* *object*
* Классы
* Интерфейсы
* Делегаты
## Пространства имён
Пространства имён позволяют организовыывать код программы в логические блоки
```C#
namespace Foo {
namespace Bar {
class Baz {}
}
}
```
Пространство имён подключается с помощью *using*
```C#
using Foo;
using Foo.Bar; // Для этого снача using Foo писать не надо
global using Foo.Bar; // Подключает этот namespace везде. Зачастую такое в файле GlobalUsings.cs
```
## Модификаторы доступа
* *private* - только в рамках класса/структуры (по умолчанию для полей)
* *private protected* - в рамках класса и наследников внутри сборки
* *file* - только в текущем файле
* *protected* - внутри класса и наследниках, которые могут находиться в других сборках
* *internal* - доступен только внутри сборки (по умолчанию для классов)
* *protected internal* - доступен из любого места в сборке и классах наследниках, которые могут быть в других сборках
* *public* - достпупен везде
## Свойства
```C#
class Person {
string name = "Undefined";
public string Name {
get {
return name;
}
set {
name = value;
}
}
}
```
Можно и так
```C#
class Person
{
public string Name { get; set; }
public int Age { get; set; } = 69;
public Person(string name) {
this.Name = name;
}
}
```