readonly vs const

Модификатор readonly защищает элементы класса от модификации после построения. Поле с readonly может быть модифицировано только при создании объекта класса или внутри конструктора.

3 отличия:

  1. Константа должна быть инициализирована при объявлении
  2. Readonly может быть модифицировано в конструкторе
  3. Readonly может быть присвоено значение, являющееся результатом вычислений

Static

Если переменная в классе статическая, то к ней из вне можно обратиться через имя класса:

ClassName.variable

Чтобы всегда можно было обратиться из вне, функция Main всегда статична. Константы тоже всегда статичны, там можно даже не указывать static.

Классы: деструкторы

Когда программа запускается, то сначала создается объект, выполняется конструктор. В конце программы конструктор удаляется, а деструктор вызывается.

class Dog {
  public Dog() {
    Console.WriteLine("Konstructor");
  }
  ~Dog() {
    Console.WriteLine("Destructor");
  }
}

static void Main(string[] args) {
  Dog d = new Dog();
}

/* Outputs:
Constructor
Destructor
*/

Работа со строками в C#

string a = "Some text";
ConsoleWriteLine(a.Lenght);
//9

ConsoleWriteLine(a.IndexOf('t'));
//5

a = a.Insert(0, "This is ");
ConsoleWriteLine(a);
//This is Some text

a = a.Replace("This is", "I am");
ConsoleWriteLine(a);
//I am Some text

if(a.Contains("some"))
  ConsoleWriteLine("found");
//found

a = a.Remove(4);
ConsoleWriteLine(a);
//I am

a = a.Substring(2);
ConsoleWriteLine(a);
//am

Подсчет популярности слов в тексте

#Взять из github-репозитория все файлы с новостями в формате txt: newsfr.txt, newsit.txt, newsafr.txt, newscy.txt.
#Написать программу, которая будет выводить топ 10 самых часто встречающихся в новостях слов длиннее 6 символов для каждого файла.
#Не забываем про декомпозицию и организацию кода в функции. В решении домашнего задания вам могут помочь: split(), sort() или sorted().

# фукнция чтения файлов (ГОТОВО)
def read_files(name):
    import chardet
    with open(name, 'rb') as f:
        data = f.read()
        result = chardet.detect(data)
        original_text = data.decode(result['encoding'])
        return original_text

# функция подсчета слов длиннее 6 символов (ГОТОВО)
def count_word(original_text):
    to_list = original_text.split(' ')
    to_set = set()
    for i in to_list: # заполняем множество с уникальными словами длиной больше 6 символов
        if len(i) > 6:
            to_set.add(i)
    word_value = {} # ищем слова из множества в списке, считаем количество, формируем словарь типа слово:количество
    for i in to_set:
        count = 0
        for j in to_list:
            if i == j:
                count += 1
        word_value[i] = count
    return word_value # возвращаем словарь {слово:количество}

# функция сортировки и вывода ТОП-10 
def sort_top(word_value):
    register = list()
    l_dict = str(len(word_value))
    for i in word_value.items():
        l_word = str(i[1])
        register.append((len(l_dict)-len(l_word))*'0' + str(i[1]) + ' ' + i[0]) # разворачиваем и добавляем нули перед количеством для сортировка, делаем слияние элементов = '00012 слово'
    register.sort(reverse = True)
    top_10_list = list()
    top_10 = {}
    count = 1
    for j in register:
        top_10[count] = j.split(' ') # получаем словарь типа {1: (количество, слово)}          
        top_10[count][0] = int(top_10[count][0])   
        if count == 10:
            break
        count += 1
    return top_10 # возвращаем отсортированный словарь ТОП-10 {номер: (количеств, слово)}

# главная функция: запрашивает имя файла, запускает другие функции (ГОТОВО)
def main():
        while True:
            name = input('Введите имя файла: newsfr.txt, newsit.txt, newsafr.txt, newscy.txt. Выход - exit: ')
            if name == 'newsfr.txt' or name == 'newsit.txt' or name == 'newsafr.txt' or name == 'newscy.txt':
                print('Идет обработка файла ...')
                top_10 = sort_top(count_word(read_files(name)))
                for k in top_10.values():
                    print (k[0], ': ', k[1])
            elif name == 'exit':
                break
            else:
                print('Некорректный ввод, повторите.')
        
main()
  • сортировка через list.sort() — по умолчанию так, если нужна обратная сортировка, то list.sort(reverse=True), если по какому-то ключу, то list.sort(key=[ключ]). Если нужно, чтобы функция возвращала значение, то используем sorted вместо sort;
  • функция chardet для автоматического определения кодировки и перевода в UTF-8.

Аналог с JSON с доработками предыдущего кода (сортировка словаря по значениям через лямбда-функцию):

#Взять из github-репозитория все файлы с новостями в формате json: newsfr.json, newsit.json, newsafr.json, newscy.json.
#Написать программу, которая будет выводить топ 10 самых часто встречающихся в новостях слов длиннее 6 символов для каждого файла.
#Не забываем про декомпозицию и организацию кода в функции. В решении домашнего задания вам могут помочь: split(), sort() или sorted().

#{'rss': {'_version': '2.0',
#         '_xmlns:votpusk': 'https://www.votpusk.ru/news.asp',
#         'channel': {'category': 'ВгаШЧЬ - єШЯа',
#                     'description': 'єШЯа - »ХЭвР вгаШбвШзХбЪШе ЭЮТЮбвХЩ '
#                                    'ЯЮавРЫР І ѕВїГБє.АГ ',
#                     'items': [{'_id': '545166',
#                                'description': 'ІЫРбвШ єШЯаР аРббзШвлТРов '

def read_files(name):
    'Функция чтения файлов'
    import json
    import chardet

    with open(name, 'rb') as f:
        data = f.read()
        result = chardet.detect(data)
        data = data.decode(result['encoding'])
        data = json.loads(data) # внимание! load читает файл, loads читает строку
        original_text = ''
        for items in data['rss']['channel']['items']:
           original_text += ' ' + items['description']
        return original_text

def count_word(original_text):
    'функция подсчета слов длиннее 6 символов'
    to_list = original_text.split(' ')
    word_value = {}
    for word in to_list: 
        if len(word) > 6:
            if word in word_value:
                word_value[word] += 1
            else:
                word_value[word] = 1
    return word_value # возвращаем словарь {слово:количество}

def sort_top(word_value):
    'функция сортировки и вывода ТОП-10' 
    l = lambda word_value: word_value[1]
    sort_list = sorted(word_value.items(), key = l, reverse = True)
    count = 1
    top_10 = {}
    for word in sort_list:
        top_10[count] = word        
        count += 1        
        if count == 10:
            break
    return top_10

def main():
    'главная функция: запрашивает имя файла, запускает другие функции'
    while True:
        name = input('Введите имя файла: newsfr.json, newsit.json, newsafr.json, newscy.json. Выход - exit: ')
        if name == 'newsfr.json' or name == 'newsit.json' or name == 'newsafr.json' or name == 'newscy.json':
            print('Идет обработка файла ...')
            top_10 = sort_top(count_word(read_files(name)))
            for i in top_10.values():
                print (i[1], ': ', i[0])
        elif name == 'exit':
            break
        else:
            print('Некорректный ввод, повторите.')
        
main()

Классы: свойства

Инкапсуляция дает доступ только через публичные методы, а свойства дают возможность реализации гибкого механизма чтения, записи и вычисления приватного поля. Свойства используют элементы доступа get, set.

class Person {
  private string name;
  public string Name {
    get { return name; }
    set { name = value; } // тут можно прописать условия, а не просто присваивание
    }
  }

// Закомментированный код ниже заменяет весь код внутри класса Person
// public string Name { get; set; }

static void Main(string[] args) {
  Person p = new Person();
  p.Name = "Bobik";
  Console.WriteLine(p.Name);
  }

Свойства могут называться как угодно, но принято для понимания кода называть их по имени переменной, но только с большой буквы: name => Name.

Также есть автоматически реализуемые свойства (краткая запись, если нет необходимости реализовать логику в set).

public string Name { get; set; }

Классы: конструктор

Если при создании нового объекта класса нужно что-то автоматически сделать (например, вывести текст, отправить смс) используются конструкторы класса.

class Person {
  private int age;
  public Person() {
    Console.WriteLine("Привет!");
    }
  }

Конструктор имеет такое же имя, что и класс, является публичным и не имеет никакого возвращаемого типа.

При создании объекта класса, реализованного выше Person p = new Person(), будет выведено сообщение «Привет!».

ООП: инкапсуляция

Инкапсуляция — это управление окружением объекта, возможность дать доступ или ограничить его. Реализуется через модификаторы доступа private, public, protected, internal, protected internal.

Методы: перегрузка

Если для разных типов данных или при разном количестве передаваемых аргументов нужно запускать разные методы, то имеется возможность перегрузки методов.

static void Print(int a) {
  Console.WriteLine("Value: " + a);
  }
static void Print(double a) {
  Console.WriteLine("Value: " + a);
  }
static void Print(string label, int a) {
  Console.WriteLine(label + a);
  }

static void Main(string[] args) {
  Print(11);
  Print(4.13);
  Print("Ответ: ", 14);
  }

Перегрузка работает только при разных типах аргументов. Следующий код выведет ошибку:

int Print(int a) {}
float Print(int a) {}
double Print(int a) {}