Учебники

C # — Краткое руководство

C # — Обзор

C # — это современный универсальный объектно-ориентированный язык программирования, разработанный Microsoft и одобренный Европейской ассоциацией производителей компьютеров (ECMA) и Международной организацией по стандартизации (ISO).

C # был разработан Андерсом Хейлсбергом и его командой во время разработки .Net Framework.

C # разработан для Common Language Infrastructure (CLI), которая состоит из исполняемого кода и среды выполнения, которая позволяет использовать различные языки высокого уровня на разных компьютерных платформах и архитектурах.

Следующие причины делают C # широко используемым профессиональным языком —

  • Это современный язык программирования общего назначения.
  • Это объектно-ориентированный.
  • Это компонентно-ориентированный.
  • Это легко учиться.
  • Это структурированный язык.
  • Он производит эффективные программы.
  • Он может быть скомпилирован на различных компьютерных платформах.
  • Это часть .Net Framework.

Сильные возможности программирования на C #

Хотя конструкции C # тесно связаны с традиционными языками высокого уровня, C и C ++ и являются объектно-ориентированным языком программирования. Он очень похож на Java, имеет множество сильных функций программирования, которые делают его привлекательным для многих программистов по всему миру.

Ниже приведен список нескольких важных функций C # —

  • Булевы условия
  • Автоматическая сборка мусора
  • Стандартная библиотека
  • Версии сборки
  • Свойства и События
  • Управление делегатами и мероприятиями
  • Простота в использовании Generics
  • индексаторы
  • Условная компиляция
  • Простая многопоточность
  • LINQ и лямбда-выражения
  • Интеграция с Windows

C # — Окружающая среда

Попробуйте вариант онлайн

Мы настроили среду программирования на C # онлайн, чтобы вы могли скомпилировать и выполнить все доступные примеры онлайн. Это дает вам уверенность в том, что вы читаете, и позволяет вам проверять программы с различными вариантами. Не стесняйтесь изменять любой пример и выполнять его онлайн.

Попробуйте следующий пример, используя наш онлайн-компилятор, доступный на CodingGround.

using System;

namespace HelloWorldApplication {
   
   class HelloWorld {

      static void Main(string[] args) {
         /* my first program in C# */
         Console.WriteLine("Hello World");
         Console.ReadKey();
      }
   }
}

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

Мы настроили среду программирования на C # онлайн, чтобы вы могли скомпилировать и выполнить все доступные примеры онлайн. Это дает вам уверенность в том, что вы читаете, и позволяет вам проверять программы с различными вариантами. Не стесняйтесь изменять любой пример и выполнять его онлайн.

Попробуйте следующий пример, используя наш онлайн-компилятор, доступный на CodingGround.

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

В этой главе мы обсудим инструменты, необходимые для создания программирования на C #. Мы уже упоминали, что C # является частью .Net Framework и используется для написания .Net приложений. Поэтому, прежде чем обсуждать доступные инструменты для запуска программы на C #, давайте разберемся, как C # относится к платформе .Net.

.Net Framework

.Net Framework — это революционная платформа, которая помогает вам писать приложения следующих типов:

  • Приложения для Windows
  • Веб-приложения
  • Веб-сервисы

Приложения .Net Framework являются мультиплатформенными приложениями. Фреймворк спроектирован таким образом, что его можно использовать на любом из следующих языков: C #, C ++, Visual Basic, Jscript, COBOL и т. Д. Все эти языки могут обращаться к фреймворку, а также общаться друг с другом.

.Net Framework состоит из огромной библиотеки кодов, используемых клиентскими языками, такими как C #. Ниже приведены некоторые компоненты .Net Framework —

  • Common Language Runtime (CLR)
  • Библиотека классов .Net Framework
  • Спецификация общего языка
  • Система общего типа
  • Метаданные и сборки
  • Windows Forms
  • ASP.Net и ASP.Net AJAX
  • ADO.Net
  • Windows Workflow Foundation (WF)
  • Windows Presentation Foundation
  • Windows Communication Foundation (WCF)
  • LINQ

Работы, выполняемые каждым из этих компонентов, см. В разделе ASP.Net — Введение , а сведения о каждом компоненте см. В документации Microsoft.

Интегрированная среда разработки (IDE) для C #

Microsoft предоставляет следующие инструменты разработки для программирования на C # —

  • Visual Studio 2010 (VS)
  • Visual C # 2010 Express (VCE)
  • Visual Web Developer

Последние два свободно доступны с официального сайта Microsoft. Используя эти инструменты, вы можете писать все виды программ на C # от простых приложений командной строки до более сложных приложений. Вы также можете писать файлы исходного кода C # с помощью обычного текстового редактора, такого как Блокнот, и компилировать код в сборки, используя компилятор командной строки, который снова является частью .NET Framework.

Выпуски Visual C # Express и Visual Web Developer Express являются урезанными версиями Visual Studio и имеют одинаковый внешний вид. Они сохраняют большинство функций Visual Studio. В этом уроке мы использовали Visual C # 2010 Express.

Вы можете скачать его из Microsoft Visual Studio . Он устанавливается автоматически на вашем компьютере.

Примечание. Для установки экспресс-издания необходимо активное подключение к Интернету.

Написание программ на C # в Linux или Mac OS

Хотя .NET Framework работает в операционной системе Windows, есть несколько альтернативных версий, которые работают в других операционных системах. Mono — это версия .NET Framework с открытым исходным кодом, которая включает в себя компилятор C # и работает в нескольких операционных системах, включая различные версии Linux и Mac OS. Пожалуйста, проверьте Go Mono .

Заявленная цель Mono состоит не только в том, чтобы иметь возможность запускать кросс-платформенные приложения Microsoft .NET, но также и в том, чтобы предлагать лучшие инструменты разработки для разработчиков Linux. Mono может работать на многих операционных системах, включая Android, BSD, iOS, Linux, OS X, Windows, Solaris и UNIX.

C # — Структура программы

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

Создание программы Hello World

Программа AC # состоит из следующих частей —

  • Объявление пространства имен
  • Класс
  • Методы класса
  • Атрибуты класса
  • Основной метод
  • Заявления и выражения
  • Комментарии

Давайте посмотрим на простой код, который печатает слова «Hello World» —

using System;

namespace HelloWorldApplication {
   
   class HelloWorld {
      
      static void Main(string[] args) {
         /* my first program in C# */
         Console.WriteLine("Hello World");
         Console.ReadKey();
      }
   }
}

Когда этот код компилируется и выполняется, он дает следующий результат —

Hello World

Давайте посмотрим на различные части данной программы —

  • Первая строка программы с использованием System; — ключевое слово using используется для включения в программу пространства имен System . Программа обычно имеет несколько операторов использования .

  • Следующая строка имеет объявление пространства имен . Пространство имен — это коллекция классов. Пространство имен HelloWorldApplication содержит класс HelloWorld .

  • Следующая строка имеет объявление класса , класс HelloWorld содержит определения данных и методов, которые использует ваша программа. Классы обычно содержат несколько методов. Методы определяют поведение класса. Однако класс HelloWorld имеет только один метод Main .

  • Следующая строка определяет метод Main , который является точкой входа для всех программ на C #. Метод Main указывает, что делает класс при выполнении.

  • Следующая строка /*…*/ игнорируется компилятором и ставится для добавления комментариев в программу.

  • Метод Main определяет свое поведение с помощью оператора Console.WriteLine («Hello World»);

    WriteLine — это метод класса Console, определенный в пространстве имен System . Это утверждение вызывает сообщение «Hello, World!» быть отображенным на экране.

  • Последняя строка Console.ReadKey (); для пользователей VS.NET. Это заставляет программу ждать нажатия клавиши и предотвращает быстрый запуск и закрытие экрана при запуске программы из Visual Studio .NET.

Первая строка программы с использованием System; — ключевое слово using используется для включения в программу пространства имен System . Программа обычно имеет несколько операторов использования .

Следующая строка имеет объявление пространства имен . Пространство имен — это коллекция классов. Пространство имен HelloWorldApplication содержит класс HelloWorld .

Следующая строка имеет объявление класса , класс HelloWorld содержит определения данных и методов, которые использует ваша программа. Классы обычно содержат несколько методов. Методы определяют поведение класса. Однако класс HelloWorld имеет только один метод Main .

Следующая строка определяет метод Main , который является точкой входа для всех программ на C #. Метод Main указывает, что делает класс при выполнении.

Следующая строка /*…*/ игнорируется компилятором и ставится для добавления комментариев в программу.

Метод Main определяет свое поведение с помощью оператора Console.WriteLine («Hello World»);

WriteLine — это метод класса Console, определенный в пространстве имен System . Это утверждение вызывает сообщение «Hello, World!» быть отображенным на экране.

Последняя строка Console.ReadKey (); для пользователей VS.NET. Это заставляет программу ждать нажатия клавиши и предотвращает быстрый запуск и закрытие экрана при запуске программы из Visual Studio .NET.

Стоит отметить следующие моменты —

  • C # чувствителен к регистру.
  • Все выражения и выражения должны заканчиваться точкой с запятой (;).
  • Выполнение программы начинается с метода Main.
  • В отличие от Java, имя файла программы может отличаться от имени класса.

Компиляция и выполнение программы

Если вы используете Visual Studio.Net для компиляции и выполнения программ на C #, сделайте следующее:

  • Запустите Visual Studio.

  • В строке меню выберите Файл -> Создать -> Проект.

  • Выберите Visual C # из шаблонов, а затем выберите Windows.

  • Выберите Консольное приложение.

  • Укажите имя для вашего проекта и нажмите кнопку ОК.

  • Это создает новый проект в обозревателе решений.

  • Напишите код в редакторе кода.

  • Нажмите кнопку «Выполнить» или нажмите клавишу F5, чтобы выполнить проект. Появится окно командной строки, содержащее строку Hello World.

Запустите Visual Studio.

В строке меню выберите Файл -> Создать -> Проект.

Выберите Visual C # из шаблонов, а затем выберите Windows.

Выберите Консольное приложение.

Укажите имя для вашего проекта и нажмите кнопку ОК.

Это создает новый проект в обозревателе решений.

Напишите код в редакторе кода.

Нажмите кнопку «Выполнить» или нажмите клавишу F5, чтобы выполнить проект. Появится окно командной строки, содержащее строку Hello World.

Вы можете скомпилировать программу на C #, используя командную строку вместо Visual Studio IDE —

  • Откройте текстовый редактор и добавьте вышеупомянутый код.

  • Сохраните файл как helloworld.cs

  • Откройте инструмент командной строки и перейдите в каталог, где вы сохранили файл.

  • Введите csc helloworld.cs и нажмите Enter, чтобы скомпилировать ваш код.

  • Если в вашем коде нет ошибок, командная строка переместит вас на следующую строку и сгенерирует исполняемый файл helloworld.exe .

  • Введите helloworld, чтобы выполнить вашу программу.

  • Вы можете увидеть вывод Hello World, напечатанный на экране.

Откройте текстовый редактор и добавьте вышеупомянутый код.

Сохраните файл как helloworld.cs

Откройте инструмент командной строки и перейдите в каталог, где вы сохранили файл.

Введите csc helloworld.cs и нажмите Enter, чтобы скомпилировать ваш код.

Если в вашем коде нет ошибок, командная строка переместит вас на следующую строку и сгенерирует исполняемый файл helloworld.exe .

Введите helloworld, чтобы выполнить вашу программу.

Вы можете увидеть вывод Hello World, напечатанный на экране.

C # — основной синтаксис

C # — объектно-ориентированный язык программирования. В методологии объектно-ориентированного программирования программа состоит из различных объектов, которые взаимодействуют друг с другом посредством действий. Действия, которые может выполнять объект, называются методами. Говорят, что объекты одного и того же типа имеют одинаковый тип или, как говорят, находятся в одном классе.

Например, давайте рассмотрим объект Rectangle. У него есть такие атрибуты, как длина и ширина. В зависимости от дизайна могут потребоваться способы принятия значений этих атрибутов, расчета площади и отображения деталей.

Давайте посмотрим на реализацию класса Rectangle и обсудим основной синтаксис C # —

using System;

namespace RectangleApplication {
   
   class Rectangle {
      // member variables
      double length;
      double width;
      
      public void Acceptdetails() {
         length = 4.5;    
         width = 3.5;
      }
      
      public double GetArea() {
         return length * width; 
      }
      
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }
   
   class ExecuteRectangle {
   
      static void Main(string[] args) {
         Rectangle r = new Rectangle();
         r.Acceptdetails();
         r.Display();
         Console.ReadLine(); 
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Length: 4.5
Width: 3.5
Area: 15.75

Использование ключевого слова

Первое утверждение в любой программе на C #

using System;

Ключевое слово using используется для включения пространств имен в программу. Программа может включать несколько операторов использования.

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

Ключевое слово class используется для объявления класса.

Комментарии в C #

Комментарии используются для объяснения кода. Компиляторы игнорируют записи комментариев. Многострочные комментарии в программах на C # начинаются с / * и заканчиваются символами * /, как показано ниже —

/* This program demonstrates
The basic syntax of C# programming 
Language */

Однострочные комментарии обозначаются символом «//». Например,

}//end class Rectangle    

Переменные-члены

Переменные — это атрибуты или члены-данные класса, используемые для хранения данных. В предыдущей программе класс Rectangle имеет две переменные-члены с именами length и width .

Функции члена

Функции — это набор операторов, которые выполняют определенную задачу. Функции-члены класса объявлены внутри класса. Наш пример класса Rectangle содержит три функции-члена: AcceptDetails , GetArea и Display .

Создание класса

В предыдущей программе класс ExecuteRectangle содержит метод Main () и создает экземпляр класса Rectangle .

Идентификаторы

Идентификатор — это имя, используемое для идентификации класса, переменной, функции или любого другого пользовательского элемента. Основные правила именования классов в C # следующие:

  • Имя должно начинаться с буквы, за которой может следовать последовательность букв, цифр (0 — 9) или подчеркивания. Первый символ в идентификаторе не может быть цифрой.

  • Он не должен содержать пробелов или символов, таких как? — +! @ #% ^ & * () [] {}. ; : «‘/ and \. Однако можно использовать подчеркивание (_).

  • Это не должно быть ключевое слово C #.

Имя должно начинаться с буквы, за которой может следовать последовательность букв, цифр (0 — 9) или подчеркивания. Первый символ в идентификаторе не может быть цифрой.

Он не должен содержать пробелов или символов, таких как? — +! @ #% ^ & * () [] {}. ; : «‘/ and \. Однако можно использовать подчеркивание (_).

Это не должно быть ключевое слово C #.

C # Ключевые слова

Ключевые слова — это зарезервированные слова, предопределенные для компилятора C #. Эти ключевые слова не могут быть использованы в качестве идентификаторов. Однако, если вы хотите использовать эти ключевые слова в качестве идентификаторов, вы можете поставить перед ключевым словом символ @.

В C # некоторые идентификаторы имеют особое значение в контексте кода, например, get и set называются контекстными ключевыми словами.

В следующей таблице перечислены зарезервированные ключевые слова и контекстные ключевые слова в C # —

Зарезервированные ключевые слова
Аннотация как база BOOL перерыв байт дело
ловить голец проверено учебный класс Const Продолжить десятичный
дефолт делегат делать двойной еще перечисление событие
явный внешний ложный в конце концов фиксированный поплавок за
для каждого идти к если неявный в в (универсальный модификатор) ИНТ
интерфейс внутренний является замок долго Пространство имен новый
ноль объект оператор из out (универсальный модификатор) переопределение Титулы
частный защищенный общественности только для чтения ссылка вернуть SByte
запечатанный короткая размер stackalloc статический строка структура
переключатель этот бросать правда пытаться тип UINT
ULONG непроверенный небезопасный USHORT с помощью виртуальный недействительным
летучий в то время как
Контекстные ключевые слова
добавлять псевдоним по возрастанию нисходящий динамический от получить
Глобальный группа в присоединиться позволять Сортировать по частичный (тип)
частичный
(Метод)
Удалить Выбрать задавать

C # — Типы данных

Переменные в C # подразделяются на следующие типы:

  • Типы значений
  • Типы ссылок
  • Типы указателей

Тип ценности

Переменным типа значения можно присвоить значение напрямую. Они являются производными от класса System.ValueType .

Типы значений напрямую содержат данные. Некоторыми примерами являются int, char и float , в которых хранятся числа, алфавиты и числа с плавающей запятой соответственно. Когда вы объявляете тип int , система выделяет память для хранения значения.

В следующей таблице перечислены доступные типы значений в C # 2010.

Тип Представляет собой Спектр Значение по умолчанию
BOOL Логическое значение Правда или ложь Ложь
байт 8-битное целое число без знака От 0 до 255 0
голец 16-битный символ Юникода U +0000 до U + FFFF ‘\ 0’
десятичный 128-битные точные десятичные значения с 28-29 значащими цифрами (От -7,9 х 10 28 до 7,9 х 10 28 ) / от 10 до 28 0.0 млн
двойной 64-битный тип с плавающей запятой двойной точности (+/-) 5,0 x 10 -324 до (+/-) 1,7 x 10 308 0.0d
поплавок 32-битный тип с плавающей запятой одинарной точности От -3,4 х 10 38 до + 3,4 х 10 38 0.0f
ИНТ 32-разрядное целое число со знаком От -2 147 483 648 до 2 147 483 647 0
долго 64-разрядное целое число со знаком От -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807 0L
SByte 8-разрядное целое число со знаком От -128 до 127 0
короткая 16-разрядное целое число со знаком От -32 768 до 32 767 0
UINT 32-разрядное целое число без знака От 0 до 4 294 967 295 0
ULONG 64-разрядное целое число без знака От 0 до 18 446 744 073 709 551 615 0
USHORT 16-разрядное целое число без знака От 0 до 65 535 0

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

using System;

namespace DataTypeApplication {
   
   class Program {

      static void Main(string[] args) {
         Console.WriteLine("Size of int: {0}", sizeof(int));
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Size of int: 4

Тип ссылки

Типы ссылок не содержат фактических данных, хранящихся в переменной, но содержат ссылку на переменные.

Другими словами, они относятся к области памяти. Используя несколько переменных, ссылочные типы могут ссылаться на ячейку памяти. Если данные в ячейке памяти изменяются одной из переменных, другая переменная автоматически отражает это изменение в значении. Примеры встроенных ссылочных типов: object , dynamic и string .

Тип объекта

Тип объекта является основным базовым классом для всех типов данных в C # Common Type System (CTS). Объект является псевдонимом для класса System.Object. Типам объектов могут быть назначены значения любых других типов, типов значений, ссылочных типов, предопределенных или пользовательских типов. Однако перед присвоением значений необходимо преобразование типов.

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

object obj;
obj = 100; // this is boxing

Динамический тип

Вы можете сохранить любой тип значения в переменной динамического типа данных. Проверка типов для этих типов переменных происходит во время выполнения.

Синтаксис объявления динамического типа —

dynamic <variable_name> = value;

Например,

dynamic d = 20;

Динамические типы аналогичны типам объектов, за исключением того, что проверка типов для переменных типа объекта выполняется во время компиляции, тогда как проверка для переменных динамического типа выполняется во время выполнения.

Тип строки

Тип String позволяет назначать любые строковые значения переменной. Тип string является псевдонимом для класса System.String. Это происходит от типа объекта. Значение для строкового типа может быть назначено с использованием строковых литералов в двух формах: в кавычках и @quoted.

Например,

String str = "Tutorials Point";

Строковый литерал @ в кавычках выглядит следующим образом —

@"Tutorials Point";

Определяемые пользователем типы ссылок: класс, интерфейс или делегат. Мы обсудим эти типы в следующей главе.

Тип указателя

Переменные типа указателя хранят адрес памяти другого типа. Указатели в C # имеют те же возможности, что и указатели в C или C ++.

Синтаксис для объявления типа указателя —

type* identifier;

Например,

char* cptr;
int* iptr;

Мы обсудим типы указателей в главе «Небезопасные коды».

C # — преобразование типов

Преобразование типов — это преобразование данных одного типа в другой тип. Это также известно как Кастинг Типа. В C # приведение типов имеет две формы:

  • Неявное преобразование типов — эти преобразования выполняются в C # безопасным для типов образом. Например, это преобразования из меньших целых типов в большие и преобразования из производных классов в базовые классы.

  • Явное преобразование типов — эти преобразования выполняются явно пользователями, использующими предопределенные функции. Явные преобразования требуют оператора приведения.

Неявное преобразование типов — эти преобразования выполняются в C # безопасным для типов образом. Например, это преобразования из меньших целых типов в большие и преобразования из производных классов в базовые классы.

Явное преобразование типов — эти преобразования выполняются явно пользователями, использующими предопределенные функции. Явные преобразования требуют оператора приведения.

В следующем примере показано явное преобразование типов —

using System;

namespace TypeConversionApplication {

   class ExplicitConversion {
   
      static void Main(string[] args) {
         double d = 5673.74; 
         int i;
         
         // cast double to int.
         i = (int)d;
         Console.WriteLine(i);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

5673

Методы преобразования типов в C #

C # предоставляет следующие встроенные методы преобразования типов —

Sr.No. Методы и описание
1

ToBoolean

Преобразует тип в логическое значение, где это возможно.

2

ToByte

Преобразует тип в байт.

3

TOCHAR

Преобразует тип в один символ Unicode, где это возможно.

4

ToDateTime

Преобразует тип (целочисленный или строковый тип) в структуры даты и времени.

5

ToDecimal

Преобразует тип с плавающей запятой или целочисленный в десятичный тип.

6

Удвоить

Преобразует тип в двойной тип.

7

ToInt16

Преобразует тип в 16-разрядное целое число.

8

ToInt32

Преобразует тип в 32-разрядное целое число.

9

ToInt64

Преобразует тип в 64-разрядное целое число.

10

ToSbyte

Преобразует тип в тип байта со знаком.

11

ToSingle

Преобразует тип в небольшое число с плавающей запятой.

12

Нанизывать

Преобразует тип в строку.

13

Печатать

Преобразует тип в указанный тип.

14

ToUint16

Преобразует тип в тип unsigned int.

15

ToUint32

Преобразует тип в длинный тип без знака.

16

ToUInt64

Преобразует тип в целое число без знака.

ToBoolean

Преобразует тип в логическое значение, где это возможно.

ToByte

Преобразует тип в байт.

TOCHAR

Преобразует тип в один символ Unicode, где это возможно.

ToDateTime

Преобразует тип (целочисленный или строковый тип) в структуры даты и времени.

ToDecimal

Преобразует тип с плавающей запятой или целочисленный в десятичный тип.

Удвоить

Преобразует тип в двойной тип.

ToInt16

Преобразует тип в 16-разрядное целое число.

ToInt32

Преобразует тип в 32-разрядное целое число.

ToInt64

Преобразует тип в 64-разрядное целое число.

ToSbyte

Преобразует тип в тип байта со знаком.

ToSingle

Преобразует тип в небольшое число с плавающей запятой.

Нанизывать

Преобразует тип в строку.

Печатать

Преобразует тип в указанный тип.

ToUint16

Преобразует тип в тип unsigned int.

ToUint32

Преобразует тип в длинный тип без знака.

ToUInt64

Преобразует тип в целое число без знака.

В следующем примере различные типы значений преобразуются в строковый тип —

using System;

namespace TypeConversionApplication {
   
   class StringConversion {
      
      static void Main(string[] args) {
         int i = 75;
         float f = 53.005f;
         double d = 2345.7652;
         bool b = true;

         Console.WriteLine(i.ToString());
         Console.WriteLine(f.ToString());
         Console.WriteLine(d.ToString());
         Console.WriteLine(b.ToString());
         Console.ReadKey();
            
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

75
53.005
2345.7652
True

C # — переменные

Переменная — это не что иное, как имя, данное области памяти, которой могут манипулировать наши программы. Каждая переменная в C # имеет определенный тип, который определяет размер и расположение памяти переменной, диапазон значений, которые могут быть сохранены в этой памяти, и набор операций, которые могут быть применены к переменной.

Основные типы значений, представленные в C #, могут быть классифицированы как —

Тип пример
Интегральные типы sbyte, byte, short, ushort, int, uint, long, ulong и char
Типы с плавающей точкой плавать и двойной
Десятичные типы десятичный
Булевы типы истинные или ложные значения, как назначено
Обнуляемые типы Обнуляемые типы данных

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

Определение переменных

Синтаксис для определения переменной в C # —

<data_type> <variable_list>;

Здесь data_type должен быть допустимым типом данных C #, включая char, int, float, double или любой определенный пользователем тип данных, а variable_list может состоять из одного или нескольких имен идентификаторов, разделенных запятыми.

Некоторые действительные определения переменных показаны здесь —

int i, j, k;
char c, ch;
float f, salary;
double d;

Вы можете инициализировать переменную во время определения как —

int i = 100;

Инициализация переменных

Переменные инициализируются (присваиваются значения) со знаком равенства, за которым следует постоянное выражение. Общая форма инициализации —

variable_name = value;

Переменные могут быть инициализированы в их объявлении. Инициализатор состоит из знака равенства, за которым следует постоянное выражение в виде —

<data_type> <variable_name> = value;

Вот некоторые примеры:

int d = 3, f = 5;    /* initializing d and f. */
byte z = 22;         /* initializes z. */
double pi = 3.14159; /* declares an approximation of pi. */
char x = 'x';        /* the variable x has the value 'x'. */

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

В следующем примере используются различные типы переменных —

using System;

namespace VariableDefinition {

   class Program {
   
      static void Main(string[] args) {
         short a;
         int b ;
         double c;

         /* actual initialization */
         a = 10;
         b = 20;
         c = a + b;
         Console.WriteLine("a = {0}, b = {1}, c = {2}", a, b, c);
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

a = 10, b = 20, c = 30

Принятие значений от пользователя

Класс Console в пространстве имен System предоставляет функцию ReadLine () для приема ввода от пользователя и сохранения его в переменной.

Например,

int num;
num = Convert.ToInt32(Console.ReadLine());

Функция Convert.ToInt32 () преобразует введенные пользователем данные в тип данных int, поскольку Console.ReadLine () принимает данные в строковом формате.

Выражения Lvalue и Rvalue в C #

Есть два вида выражений в C # —

  • lvalue — выражение, являющееся lvalue, может отображаться как слева или справа от присваивания.

  • rvalue — выражение, являющееся rvalue, может появляться справа, но не слева от присваивания.

lvalue — выражение, являющееся lvalue, может отображаться как слева или справа от присваивания.

rvalue — выражение, являющееся rvalue, может появляться справа, но не слева от присваивания.

Переменные являются lvalue и, следовательно, они могут появляться в левой части назначения. Числовые литералы являются значениями и, следовательно, они не могут быть назначены и не могут отображаться в левой части. Ниже приведен действительный оператор C # —

int g = 20;

Но следующее не является допустимым утверждением и может привести к ошибке во время компиляции —

10 = 20;

C # — Константы и литералы

Константы относятся к фиксированным значениям, которые программа не может изменить во время своего выполнения. Эти фиксированные значения также называются литералами. Константы могут быть любого из основных типов данных, таких как целочисленная константа, плавающая константа, символьная константа или строковый литерал. Есть также константы перечисления.

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

Целочисленные литералы

Целочисленный литерал может быть десятичной или шестнадцатеричной константой. Префикс указывает основание или основание: 0x или 0X для шестнадцатеричного числа, и для префикса не существует идентификатора префикса.

Целочисленный литерал также может иметь суффикс, который представляет собой комбинацию U и L для беззнакового и длинного соответственно. Суффикс может быть в верхнем или нижнем регистре и может быть в любом порядке.

Вот несколько примеров целочисленных литералов —

212         /* Legal */
215u        /* Legal */
0xFeeL      /* Legal */

Ниже приведены другие примеры различных типов литералов Integer:

85         /* decimal */
0x4b       /* hexadecimal */
30         /* int */
30u        /* unsigned int */
30l        /* long */
30ul       /* unsigned long */

Литералы с плавающей точкой

Литерал с плавающей точкой имеет целочисленную часть, десятичную точку, дробную часть и экспоненту. Вы можете представлять литералы с плавающей запятой в десятичной или экспоненциальной форме.

Вот несколько примеров литералов с плавающей точкой —

3.14159       /* Legal */
314159E-5F    /* Legal */
510E          /* Illegal: incomplete exponent */
210f          /* Illegal: no decimal or exponent */
.e55          /* Illegal: missing integer or fraction */

Представляя в десятичной форме, вы должны включить десятичную точку, показатель степени или оба; и при представлении с использованием экспоненциальной формы вы должны включать целую часть, дробную часть или оба. Подписанный показатель вводится через e или E.

Константы персонажа

Символьные литералы заключены в одинарные кавычки. Например, ‘x’ и может храниться в простой переменной типа char. Символьный литерал может быть простым символом (таким как ‘x’), escape-последовательностью (такой как ‘\ t’) или универсальным символом (таким как ‘\ u02C0’).

В C # есть определенные символы, когда им предшествует обратная косая черта. Они имеют особое значение и используются для представления, например, новой строки (\ n) или табуляции (\ t). Вот список некоторых из таких кодов escape-последовательностей —

Последовательность побега Имея в виду
\\ \ персонаж
‘ персонаж
» персонаж
\? ? персонаж
\ а Оповещение или звонок
\ б возврат на одну позицию
\ е Форма подачи
\ п Новая линия
Возврат каретки
\ т Горизонтальная вкладка
\ v Вертикальная вкладка
ххх , , Шестнадцатеричное число из одной или нескольких цифр

Ниже приведен пример, показывающий несколько символов escape-последовательности:

using System;

namespace EscapeChar {

   class Program {
   
      static void Main(string[] args) {
         Console.WriteLine("Hello\tWorld\n\n");
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Hello   World

Строковые литералы

Строковые литералы или константы заключаются в двойные кавычки «» или с @ «». Строка содержит символы, похожие на символьные литералы: простые символы, escape-последовательности и универсальные символы.

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

Вот несколько примеров строковых литералов. Все три формы являются одинаковыми строками.

"hello, dear"
"hello, \
dear"
"hello, " "d" "ear"
@"hello dear"

Определение констант

Константы определяются с помощью ключевого слова const . Синтаксис для определения константы —

const <data_type> <constant_name> = value;

Следующая программа демонстрирует определение и использование константы в вашей программе —

using System;

namespace DeclaringConstants {

    class Program {
    
        static void Main(string[] args) {
            const double pi = 3.14159;   
            
            // constant declaration 
            double r;
            Console.WriteLine("Enter Radius: ");
            r = Convert.ToDouble(Console.ReadLine());
            double areaCircle = pi * r * r;
            Console.WriteLine("Radius: {0}, Area: {1}", r, areaCircle);
            Console.ReadLine();
        }
    }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Enter Radius: 
3
Radius: 3, Area: 28.27431

C # — Операторы

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

  • Арифметические Операторы
  • Операторы отношений
  • Логические Операторы
  • Битовые операторы
  • Операторы присваивания
  • Разные Операторы

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

Арифметические Операторы

В следующей таблице показаны все арифметические операторы, поддерживаемые C #. Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда —

Показать примеры

оператор Описание пример
+ Добавляет два операнда А + В = 30
Вычитает второй операнд из первого A — B = -10
* Умножает оба операнда A * B = 200
/ Делит числитель на числитель B / A = 2
% Оператор модуля и остаток от целочисленного деления B% A = 0
++ Оператор приращения увеличивает целое значение на единицу А ++ = 11
Оператор декремента уменьшает целочисленное значение на единицу A— = 9

Операторы отношений

Следующая таблица показывает все реляционные операторы, поддерживаемые C #. Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда —

Показать примеры

оператор Описание пример
== Проверяет, равны ли значения двух операндов или нет, если да, тогда условие становится истинным. (A == B) не соответствует действительности.
знак равно Проверяет, равны ли значения двух операндов или нет, если значения не равны, тогда условие становится истинным. (A! = B) верно.
> Проверяет, больше ли значение левого операнда, чем значение правого операнда, если да, тогда условие становится истинным. (A> B) не соответствует действительности.
< Проверяет, меньше ли значение левого операнда, чем значение правого операнда, если да, тогда условие становится истинным. (A <B) верно.
> = Проверяет, больше ли значение левого операнда или равно значению правого операнда, если да, тогда условие становится истинным. (A> = B) не соответствует действительности.
<= Проверяет, меньше ли значение левого операнда или равно значению правого операнда, если да, тогда условие становится истинным. (A <= B) верно.

Логические Операторы

В следующей таблице приведены все логические операторы, поддерживаемые C #. Предположим, что переменная A содержит логическое значение true, а переменная B содержит логическое значение false, тогда —

Показать примеры

оператор Описание пример
&& Называется логический оператор И. Если оба операнда отличны от нуля, условие становится истинным. (A && B) неверно.
|| Вызывается логическим оператором ИЛИ. Если любой из двух операндов отличен от нуля, условие становится истинным. (A || B) верно.
! Вызывается логическим оператором НЕ. Используйте для изменения логического состояния своего операнда. Если условие истинно, то оператор Логический НЕ будет делать ложь. ! (A && B) верно.

Битовые операторы

Побитовый оператор работает с битами и выполняет побитовую операцию. Таблицы истинности для &, | и ^ следующие:

п Q P & Q р | Q р ^ д
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

Предположим, если А = 60; и B = 13; тогда в двоичном формате они выглядят следующим образом:

A = 0011 1100

B = 0000 1101

——————-

A & B = 0000 1100

A | B = 0011 1101

A ^ B = 0011 0001

~ A = 1100 0011

Побитовые операторы, поддерживаемые C #, перечислены в следующей таблице. Предположим, что переменная A содержит 60, а переменная B содержит 13, тогда —

Показать примеры

оператор Описание пример
& Двоичный оператор AND немного копирует результат, если он существует в обоих операндах. (A & B) = 12, что составляет 0000 1100
| Оператор двоичного ИЛИ копирует немного, если он существует в любом из операндов. (A | B) = 61, что составляет 0011 1101
^ Двоичный оператор XOR копирует бит, если он установлен в одном операнде, но не в обоих. (A ^ B) = 49, что составляет 0011 0001
~ Оператор дополнения двоичных единиц является унарным и имеет эффект «переворачивания» битов. (~ A) = -61, что составляет 1100 0011 в дополнении 2 из-за двоичного числа со знаком.
<< Двоичный оператор левого сдвига. Значение левого операнда перемещается влево на количество битов, указанное правым операндом. A << 2 = 240, что составляет 1111 0000
>> Оператор двоичного правого сдвига. Значение левого операнда перемещается вправо на количество битов, указанное правым операндом. A >> 2 = 15, что составляет 0000 1111

Операторы присваивания

В C # поддерживаются следующие операторы присваивания

Показать примеры

оператор Описание пример
знак равно Простой оператор присваивания, присваивает значения от правых операндов к левому операнду C = A + B присваивает значение A + B в C
+ = Добавить оператор присваивания И, он добавляет правый операнд к левому операнду и присваивает результат левому операнду C + = A эквивалентно C = C + A
знак равно Вычитание И оператор присваивания, вычитает правый операнд из левого операнда и присваивает результат левому операнду C — = A эквивалентно C = C — A
знак равно Оператор присваивания умножения И, умножает правый операнд на левый операнд и присваивает результат левому операнду C * = A эквивалентно C = C * A
знак равно Оператор деления И присваивания, делит левый операнд на правый операнд и присваивает результат левому операнду C / = A эквивалентно C = C / A
знак равно Модуль и оператор присваивания, принимает модуль с использованием двух операндов и присваивает результат левому операнду C% = A эквивалентно C = C% A
<< = Левый сдвиг И оператор присваивания C << = 2 совпадает с C = C << 2
>> = Оператор правого сдвига И присваивания C >> = 2 — это то же самое, что C = C >> 2
знак равно Побитовое И оператор присваивания C & = 2 совпадает с C = C & 2
^ = побитовое исключающее ИЛИ и оператор присваивания C ^ = 2 совпадает с C = C ^ 2
| = побитовое ИЛИ и оператор присваивания C | = 2 — это то же самое, что C = C | 2

Разные операторы

Есть несколько других важных операторов, включая sizeof, typeof и ? : поддерживается C #.

Показать примеры

оператор Описание пример
размер() Возвращает размер типа данных. sizeof (int), возвращает 4.
тип() Возвращает тип класса. TypeOf (StreamReader);
& Возвращает адрес переменной. & А; возвращает фактический адрес переменной.
* Указатель на переменную. * А; создает указатель с именем «a» на переменную.
? : Условное выражение Если условие верно? Тогда значение X: в противном случае значение Y
является Определяет, относится ли объект к определенному типу. If (Ford is Car) // проверяет, является ли Ford объектом класса Car.
как Разыгрывание без поднятия исключения, если произойдет сбой. Object obj = new StringReader («Hello»);

StringReader r = obj as StringReader;

StringReader r = obj as StringReader;

Приоритет оператора в C #

Приоритет оператора определяет группировку терминов в выражении. Это влияет на оценку выражения. Некоторые операторы имеют более высокий приоритет, чем другие; например, оператор умножения имеет более высокий приоритет, чем оператор сложения.

Например, х = 7 + 3 * 2; здесь x назначено 13, а не 20, потому что оператор * имеет более высокий приоритет, чем +, поэтому первая оценка выполняется для 3 * 2, а затем в нее добавляется 7.

Здесь операторы с самым высоким приоритетом отображаются вверху таблицы, а операторы с самым низким — внизу. Внутри выражения операторы с более высоким приоритетом вычисляются первыми.

Показать примеры

категория оператор Ассоциативность
постфикс () [] ->. ++ — — Слева направо
Одинарный + -! ~ ++ — — (тип) * & sizeof Справа налево
Multiplicative * /% Слева направо
присадка + — Слева направо
сдвиг << >> Слева направо
реляционный <<=>> = Слева направо
равенство ==! = Слева направо
Побитовое И & Слева направо
Побитовый XOR ^ Слева направо
Побитовое ИЛИ | Слева направо
Логическое И && Слева направо
Логическое ИЛИ || Слева направо
условный ?: Справа налево
присваивание = + = — = * = / =% = >> = << = & = ^ = | = Справа налево
запятая , Слева направо

C # — Принятие решений

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

Ниже приводится общая форма типичной структуры принятия решений, встречающейся в большинстве языков программирования.

Принятие решений в C #

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

Sr.No. Заявление и описание
1 если заявление

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

2 если … еще заявление

За оператором if может следовать необязательный оператор else , который выполняется, когда логическое выражение имеет значение false.

3 вложенные операторы if

Вы можете использовать один оператор if или else if внутри другого оператора if или else if .

4 заявление о переключении

Оператор switch позволяет проверять переменную на соответствие списку значений.

5 вложенные операторы switch

Вы можете использовать один оператор switch внутри другого оператора (ов) switch .

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

За оператором if может следовать необязательный оператор else , который выполняется, когда логическое выражение имеет значение false.

Вы можете использовать один оператор if или else if внутри другого оператора if или else if .

Оператор switch позволяет проверять переменную на соответствие списку значений.

Вы можете использовать один оператор switch внутри другого оператора (ов) switch .

? : Оператор

Мы накрыли условного оператора? : в предыдущей главе, которая может быть использована для замены операторов if … else . Он имеет следующую общую форму —

Exp1 ? Exp2 : Exp3;

Где Exp1, Exp2 и Exp3 являются выражениями. Обратите внимание на использование и размещение толстой кишки.

Значение? Выражение определяется следующим образом: Exp1 оценивается. Если это правда, то Exp2 оценивается и становится значением целого? выражение. Если Exp1 имеет значение false, то Exp3 оценивается, и его значение становится значением выражения.

C # — Петли

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

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

Оператор цикла позволяет нам выполнять оператор или группу операторов несколько раз, и в большинстве языков программирования ниже приводится общая инструкция оператора цикла.

Петлевая архитектура

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

Sr.No. Тип и описание петли
1 в то время как цикл

Он повторяет оператор или группу операторов, пока данное условие выполняется. Он проверяет условие перед выполнением тела цикла.

2 для цикла

Он выполняет последовательность операторов несколько раз и сокращает код, который управляет переменной цикла.

3 делать … пока цикл

Он похож на оператор while, за исключением того, что он проверяет условие в конце тела цикла

4 вложенные циклы

Вы можете использовать один или несколько циклов внутри любого другого цикла while, for или do.. while.

Он повторяет оператор или группу операторов, пока данное условие выполняется. Он проверяет условие перед выполнением тела цикла.

Он выполняет последовательность операторов несколько раз и сокращает код, который управляет переменной цикла.

Он похож на оператор while, за исключением того, что он проверяет условие в конце тела цикла

Вы можете использовать один или несколько циклов внутри любого другого цикла while, for или do.. while.

Заявления о контроле цикла

Операторы управления циклом изменяют выполнение от его нормальной последовательности. Когда выполнение покидает область действия, все автоматические объекты, созданные в этой области, уничтожаются.

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

Sr.No. Контрольное заявление и описание
1 заявление о нарушении

Завершает оператор цикла или переключателя и передает выполнение в оператор, следующий сразу за циклом или переключателем.

2 продолжить заявление

Заставляет петлю пропускать оставшуюся часть своего тела и немедленно проверять свое состояние перед повторением.

Завершает оператор цикла или переключателя и передает выполнение в оператор, следующий сразу за циклом или переключателем.

Заставляет петлю пропускать оставшуюся часть своего тела и немедленно проверять свое состояние перед повторением.

Бесконечный цикл

Цикл становится бесконечным, если условие никогда не становится ложным. Цикл for традиционно используется для этой цели. Поскольку ни одно из трех выражений, образующих цикл for, не требуется, вы можете создать бесконечный цикл, оставив условное выражение пустым.

пример

using System;

namespace Loops {

   class Program {
   
      static void Main(string[] args) {
         for (; ; ) {
            Console.WriteLine("Hey! I am Trapped");
         }
      }
   }
} 

Когда условное выражение отсутствует, оно считается истинным. У вас может быть выражение инициализации и приращения, но программисты чаще используют конструкцию for (;;) для обозначения бесконечного цикла.

C # — Инкапсуляция

Инкапсуляция определяется как «процесс включения одного или нескольких элементов в физический или логический пакет». Инкапсуляция в методологии объектно-ориентированного программирования предотвращает доступ к деталям реализации.

Абстракция и инкапсуляция являются связанными функциями в объектно-ориентированном программировании. Абстракция позволяет сделать релевантную информацию видимой, а инкапсуляция позволяет программисту реализовать желаемый уровень абстракции .

Инкапсуляция осуществляется с помощью спецификаторов доступа . Спецификатор доступа определяет область действия и видимость члена класса. C # поддерживает следующие спецификаторы доступа —

  • общественного
  • Частный
  • защищенный
  • внутренний
  • Защищенный внутренний

Спецификатор публичного доступа

Спецификатор открытого доступа позволяет классу предоставлять свои переменные-члены и функции-члены другим функциям и объектам. Любой общедоступный член может быть доступен извне класса.

Следующий пример иллюстрирует это —

using System;

namespace RectangleApplication {

   class Rectangle {
      //member variables
      public double length;
      public double width;
      
      public double GetArea() {
         return length * width;
      }
      
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle
   
   class ExecuteRectangle {
      static void Main(string[] args) {
         Rectangle r = new Rectangle();
         r.length = 4.5;
         r.width = 3.5;
         r.Display();
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Length: 4.5
Width: 3.5
Area: 15.75

В предыдущем примере переменные-члены длина и ширина объявлены как открытые , поэтому к ним можно получить доступ из функции Main (), используя экземпляр класса Rectangle с именем r .

Функции-члены Display () и GetArea () также могут обращаться к этим переменным напрямую, без использования какого-либо экземпляра класса.

Функции-члены Display () также объявлены открытыми , поэтому к ним также можно получить доступ из Main () с помощью экземпляра класса Rectangle с именем r .

Спецификатор частного доступа

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

Следующий пример иллюстрирует это —

using System;

namespace RectangleApplication {

   class Rectangle {
      //member variables
      private double length;
      private double width;
      
      public void Acceptdetails() {
         Console.WriteLine("Enter Length: ");
         length = Convert.ToDouble(Console.ReadLine());
         Console.WriteLine("Enter Width: ");
         width = Convert.ToDouble(Console.ReadLine());
      }
      
      public double GetArea() {
         return length * width;
      }
      
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle
   
   class ExecuteRectangle {
      static void Main(string[] args) {
         Rectangle r = new Rectangle();
         r.Acceptdetails();
         r.Display();
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Enter Length:
4.4
Enter Width:
3.3
Length: 4.4
Width: 3.3
Area: 14.52

В предыдущем примере переменные-члены длина и ширина объявлены закрытыми , поэтому к ним нельзя получить доступ из функции Main (). Функции-члены AcceptDetails () и Display () могут обращаться к этим переменным. Поскольку функции-члены AcceptDetails () и Display () объявлены открытыми , к ним можно получить доступ из Main () с помощью экземпляра класса Rectangle с именем r .

Спецификатор защищенного доступа

Спецификатор защищенного доступа позволяет дочернему классу обращаться к переменным-членам и функциям-членам своего базового класса. Таким образом, это помогает в реализации наследования. Мы обсудим это более подробно в главе о наследовании.

Спецификатор внутреннего доступа

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

Следующая программа иллюстрирует это —

using System;

namespace RectangleApplication {

   class Rectangle {
      //member variables
      internal double length;
      internal double width;
      
      double GetArea() {
         return length * width;
      }
      
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle
   
   class ExecuteRectangle {
      static void Main(string[] args) {
         Rectangle r = new Rectangle();
         r.length = 4.5;
         r.width = 3.5;
         r.Display();
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Length: 4.5
Width: 3.5
Area: 15.75

В предыдущем примере обратите внимание, что функция-член GetArea () не объявлена ​​с каким-либо спецификатором доступа. Тогда что будет спецификатором доступа по умолчанию для члена класса, если мы не будем упоминать его? Это личное .

Спецификатор защищенного внутреннего доступа

Спецификатор защищенного внутреннего доступа позволяет классу скрывать свои переменные-члены и функции-члены от других объектов и функций класса, кроме дочернего класса в том же приложении. Это также используется при реализации наследования.

C # — Методы

Метод — это группа операторов, которые вместе выполняют задачу. Каждая программа на C # имеет хотя бы один класс с методом Main.

Чтобы использовать метод, вам нужно —

  • Определите метод
  • Вызовите метод

Определение методов в C #

Когда вы определяете метод, вы в основном объявляете элементы его структуры. Синтаксис для определения метода в C # следующий:

<Access Specifier> <Return Type> <Method Name>(Parameter List) {
   Method Body
}

Ниже приведены различные элементы метода —

  • Спецификатор доступа — определяет видимость переменной или метода из другого класса.

  • Тип возврата — метод может возвращать значение. Тип возвращаемого значения — это тип данных значения, которое возвращает метод. Если метод не возвращает никаких значений, тип возвращаемого значения void .

  • Имя методаимя метода является уникальным идентификатором и учитывает регистр. Он не может совпадать с любым другим идентификатором, объявленным в классе.

  • Список параметров — заключенный в скобки, параметры используются для передачи и получения данных из метода. Список параметров относится к типу, порядку и количеству параметров метода. Параметры являются необязательными; то есть метод может не содержать параметров.

  • Тело метода — содержит набор инструкций, необходимых для выполнения требуемого действия.

Спецификатор доступа — определяет видимость переменной или метода из другого класса.

Тип возврата — метод может возвращать значение. Тип возвращаемого значения — это тип данных значения, которое возвращает метод. Если метод не возвращает никаких значений, тип возвращаемого значения void .

Имя методаимя метода является уникальным идентификатором и учитывает регистр. Он не может совпадать с любым другим идентификатором, объявленным в классе.

Список параметров — заключенный в скобки, параметры используются для передачи и получения данных из метода. Список параметров относится к типу, порядку и количеству параметров метода. Параметры являются необязательными; то есть метод может не содержать параметров.

Тело метода — содержит набор инструкций, необходимых для выполнения требуемого действия.

пример

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

class NumberManipulator {

   public int FindMax(int num1, int num2) {
      /* local variable declaration */
      int result;

      if (num1 > num2)
         result = num1;
      else
         result = num2;

      return result;
   }
   ...
}

Вызов методов в C #

Вы можете вызвать метод, используя имя метода. Следующий пример иллюстрирует это —

using System;

namespace CalculatorApplication {

   class NumberManipulator {
   
      public int FindMax(int num1, int num2) {
         /* local variable declaration */
         int result;
         
         if (num1 > num2)
            result = num1;
         else
            result = num2;
         return result;
      }
      
      static void Main(string[] args) {
         /* local variable definition */
         int a = 100;
         int b = 200;
         int ret;
         NumberManipulator n = new NumberManipulator();

         //calling the FindMax method
         ret = n.FindMax(a, b);
         Console.WriteLine("Max value is : {0}", ret );
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Max value is : 200

Вы также можете вызывать открытый метод из других классов, используя экземпляр класса. Например, метод FindMax принадлежит классу NumberManipulator , его можно вызвать из другого класса Test .

using System;

namespace CalculatorApplication {

   class NumberManipulator {
   
      public int FindMax(int num1, int num2) {
         /* local variable declaration */
         int result;
         
         if(num1 > num2)
            result = num1;
         else
            result = num2;
         
         return result;
      }
   }
   
   class Test {
   
      static void Main(string[] args) {
         /* local variable definition */
         int a = 100;
         int b = 200;
         int ret;
         NumberManipulator n = new NumberManipulator();
         
         //calling the FindMax method
         ret = n.FindMax(a, b);
         Console.WriteLine("Max value is : {0}", ret );
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Max value is : 200

Рекурсивный вызов метода

Метод может вызывать сам себя. Это известно как рекурсия . Ниже приведен пример, который вычисляет факториал для данного числа с использованием рекурсивной функции:

using System;

namespace CalculatorApplication {

   class NumberManipulator {
   
      public int factorial(int num) {
         /* local variable declaration */
         int result;
         if (num == 1) {
            return 1;
         }
         else {
            result = factorial(num - 1) * num;
            return result;
         }
      }
      
      static void Main(string[] args) {
         NumberManipulator n = new NumberManipulator();
         //calling the factorial method {0}", n.factorial(6));
         Console.WriteLine("Factorial of 7 is : {0}", n.factorial(7));
         Console.WriteLine("Factorial of 8 is : {0}", n.factorial(8));
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Factorial of 6 is: 720
Factorial of 7 is: 5040
Factorial of 8 is: 40320

Передача параметров в метод

Когда вызывается метод с параметрами, необходимо передать параметры в метод. Существует три способа передачи параметров в метод —

Sr.No. Механизм и описание
1 Значения параметров

Этот метод копирует фактическое значение аргумента в формальный параметр функции. В этом случае изменения, внесенные в параметр внутри функции, не влияют на аргумент.

2 Контрольные параметры

Этот метод копирует ссылку на ячейку памяти аргумента в формальный параметр. Это означает, что изменения, внесенные в параметр, влияют на аргумент.

3 Выходные параметры

Этот метод помогает возвращать более одного значения.

Этот метод копирует фактическое значение аргумента в формальный параметр функции. В этом случае изменения, внесенные в параметр внутри функции, не влияют на аргумент.

Этот метод копирует ссылку на ячейку памяти аргумента в формальный параметр. Это означает, что изменения, внесенные в параметр, влияют на аргумент.

Этот метод помогает возвращать более одного значения.

C # — Nullables

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

Например, вы можете сохранить любое значение от -2 147 483 648 до 2 147 483 647 или ноль в переменной Nullable <Int32>. Точно так же вы можете присвоить true, false или null в переменной Nullable <bool>. Синтаксис для объявления обнуляемого типа следующий:

< data_type> ? <variable_name> = null;

В следующем примере демонстрируется использование обнуляемых типов данных —

using System;

namespace CalculatorApplication {

   class NullablesAtShow {
   
      static void Main(string[] args) {
         int? num1 = null;
         int? num2 = 45;
         double? num3 = new double?();
         double? num4 = 3.14157;
         
         bool? boolval = new bool?();

         // display the values
         Console.WriteLine("Nullables at Show: {0}, {1}, {2}, {3}", num1, num2, num3, num4);
         Console.WriteLine("A Nullable boolean value: {0}", boolval);
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Nullables at Show: , 45,  , 3.14157
A Nullable boolean value:

Нулевой оператор слияния (??)

Нулевой оператор объединения используется с типами значений NULL и ссылочными типами. Он используется для преобразования операнда в тип другого обнуляемого (или нет) операнда типа значения, где возможно неявное преобразование.

Если значение первого операнда равно нулю, то оператор возвращает значение второго операнда, в противном случае он возвращает значение первого операнда. Следующий пример объясняет это —

using System;

namespace CalculatorApplication {

   class NullablesAtShow {
   
      static void Main(string[] args) {
         double? num1 = null;
         double? num2 = 3.14157;
         double num3;
         num3 = num1 ?? 5.34;      
         Console.WriteLine(" Value of num3: {0}", num3);
         num3 = num2 ?? 5.34;
         Console.WriteLine(" Value of num3: {0}", num3);
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Value of num3: 5.34
Value of num3: 3.14157

C # — Массивы

В массиве хранится последовательная коллекция фиксированного размера элементов одного типа. Массив используется для хранения набора данных, но часто более полезно думать о массиве как о коллекции переменных того же типа, хранящихся в смежных местах памяти.

Вместо того, чтобы объявлять отдельные переменные, такие как number0, number1, … и number99, вы объявляете одну переменную массива, такую ​​как числа, и используете числа [0], числа [1] и …, числа [99] для представления отдельные переменные. Определенный элемент в массиве доступен по индексу.

Все массивы состоят из смежных областей памяти. Самый низкий адрес соответствует первому элементу, а самый высокий адрес — последнему.

Массивы в C #

Объявление массивов

Чтобы объявить массив в C #, вы можете использовать следующий синтаксис —

datatype[] arrayName;

где,

  • Тип данных используется для указания типа элементов в массиве.

  • [] определяет ранг массива. Ранг определяет размер массива.

  • arrayName указывает имя массива.

Тип данных используется для указания типа элементов в массиве.

[] определяет ранг массива. Ранг определяет размер массива.

arrayName указывает имя массива.

Например,

double[] balance;

Инициализация массива

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

Массив является ссылочным типом, поэтому вам нужно использовать ключевое слово new для создания экземпляра массива. Например,

double[] balance = new double[10];

Присвоение значений массиву

Вы можете назначить значения отдельным элементам массива, используя номер индекса, например:

double[] balance = new double[10];
balance[0] = 4500.0;

Вы можете присвоить значения массиву во время объявления, как показано на рисунке —

double[] balance = { 2340.0, 4523.69, 3421.0};

Вы также можете создать и инициализировать массив, как показано на рисунке —

int [] marks = new int[5]  { 99,  98, 92, 97, 95};

Вы также можете опустить размер массива, как показано на рисунке —

int [] marks = new int[]  { 99,  98, 92, 97, 95};

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

int [] marks = new int[]  { 99,  98, 92, 97, 95};
int[] score = marks;

При создании массива компилятор C # неявно инициализирует каждый элемент массива значением по умолчанию в зависимости от типа массива. Например, для массива int все элементы инициализируются в 0.

Доступ к элементам массива

Доступ к элементу осуществляется путем индексации имени массива. Это делается путем помещения индекса элемента в квадратные скобки после имени массива. Например,

double salary = balance[9];

В следующем примере демонстрируются декларация вышеупомянутых концепций, присваивание и доступ к массивам —

using System;

namespace ArrayApplication {

   class MyArray {
   
      static void Main(string[] args) {
         int []  n = new int[10]; /* n is an array of 10 integers */
         int i,j;

         /* initialize elements of array n */
         for ( i = 0; i < 10; i++ ) {
            n[ i ] = i + 100;
         }
         
         /* output each array element's value */
         for (j = 0; j < 10; j++ ) {
            Console.WriteLine("Element[{0}] = {1}", j, n[j]);
         }
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109

Использование цикла foreach

В предыдущем примере мы использовали цикл for для доступа к каждому элементу массива. Вы также можете использовать оператор foreach для перебора массива.

using System;

namespace ArrayApplication {

   class MyArray {
   
      static void Main(string[] args) {
         int []  n = new int[10]; /* n is an array of 10 integers */
         
         /* initialize elements of array n */
         for ( int i = 0; i < 10; i++ ) {
            n[i] = i + 100;
         }
         
         /* output each array element's value */
         foreach (int j in n ) {
            int i = j-100;
            Console.WriteLine("Element[{0}] = {1}", i, j);
            
         }
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109

C # массивы

Существует несколько важных концепций, связанных с массивом, которые должны быть понятны программисту C # —

Sr.No. Концепция и описание
1 Многомерные массивы

C # поддерживает многомерные массивы. Простейшей формой многомерного массива является двумерный массив.

2 Зубчатые массивы

C # поддерживает многомерные массивы, которые являются массивами массивов.

3 Передача массивов в функции

Вы можете передать функции указатель на массив, указав имя массива без индекса.

4 Массивы параметров

Это используется для передачи неизвестного количества параметров в функцию.

5 Массив Класс

Определенный в пространстве имен System, он является базовым классом для всех массивов и предоставляет различные свойства и методы для работы с массивами.

C # поддерживает многомерные массивы. Простейшей формой многомерного массива является двумерный массив.

C # поддерживает многомерные массивы, которые являются массивами массивов.

Вы можете передать функции указатель на массив, указав имя массива без индекса.

Это используется для передачи неизвестного количества параметров в функцию.

Определенный в пространстве имен System, он является базовым классом для всех массивов и предоставляет различные свойства и методы для работы с массивами.

C # — Струны

В C # вы можете использовать строки в качестве массива символов. Однако более распространенной практикой является использование ключевого слова string для объявления строковой переменной. Ключевое слово string является псевдонимом для класса System.String .

Создание строкового объекта

Вы можете создать строковый объект, используя один из следующих методов —

  • Присваивая строковый литерал строковой переменной

  • Используя конструктор класса String

  • Используя оператор конкатенации строк (+)

  • Получая свойство или вызывая метод, который возвращает строку

  • Вызывая метод форматирования для преобразования значения или объекта в его строковое представление

Присваивая строковый литерал строковой переменной

Используя конструктор класса String

Используя оператор конкатенации строк (+)

Получая свойство или вызывая метод, который возвращает строку

Вызывая метод форматирования для преобразования значения или объекта в его строковое представление

Следующий пример демонстрирует это —

using System;

namespace StringApplication {

   class Program {
   
      static void Main(string[] args) {
         //from string literal and string concatenation
         string fname, lname;
         fname = "Rowan";
         lname = "Atkinson";
			
         char []letters= { 'H', 'e', 'l', 'l','o' };
         string [] sarray={ "Hello", "From", "Tutorials", "Point" };
			
         string fullname = fname + lname;
         Console.WriteLine("Full Name: {0}", fullname);
         
         //by using string constructor { 'H', 'e', 'l', 'l','o' };
         string greetings = new string(letters);
         Console.WriteLine("Greetings: {0}", greetings);
         
         //methods returning string { "Hello", "From", "Tutorials", "Point" };
         string message = String.Join(" ", sarray);
         Console.WriteLine("Message: {0}", message);
         
         //formatting method to convert a value
         DateTime waiting = new DateTime(2012, 10, 10, 17, 58, 1);
         string chat = String.Format("Message sent at {0:t} on {0:D}", waiting);
         Console.WriteLine("Message: {0}", chat);
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Full Name: RowanAtkinson
Greetings: Hello
Message: Hello From Tutorials Point
Message: Message sent at 5:58 PM on Wednesday, October 10, 2012

Свойства класса String

Класс String имеет следующие два свойства —

Sr.No. Описание недвижимости
1

Символов

Получает объект Char в указанной позиции в текущем объекте String .

2

длина

Получает количество символов в текущем объекте String.

Символов

Получает объект Char в указанной позиции в текущем объекте String .

длина

Получает количество символов в текущем объекте String.

Методы класса String

Класс String имеет множество методов, которые помогут вам в работе со строковыми объектами. В следующей таблице приведены некоторые из наиболее часто используемых методов —

Sr.No. Методы и описание
1

public static int Compare (строка strA, строка strB)

Сравнивает два указанных строковых объекта и возвращает целое число, которое указывает их относительное положение в порядке сортировки.

2

public static int Compare (строка strA, строка strB, bool ignoreCase)

Сравнивает два указанных строковых объекта и возвращает целое число, которое указывает их относительное положение в порядке сортировки. Однако он игнорирует случай, если логический параметр имеет значение true.

3

открытая статическая строка Concat (строка str0, строка str1)

Объединяет два строковых объекта.

4

открытая статическая строка Concat (строка str0, строка str1, строка str2)

Объединяет три строковых объекта.

5

открытая статическая строка Concat (строка str0, строка str1, строка str2, строка str3)

Объединяет четыре строковых объекта.

6

public bool Contains (строковое значение)

Возвращает значение, указывающее, встречается ли указанный объект String в этой строке.

7

публичная статическая строка Copy (строка str)

Создает новый объект String с тем же значением, что и указанная строка.

8

public void CopyTo (int sourceIndex, char [] destination, int destinationIndex, int count)

Копирует указанное количество символов из указанной позиции объекта String в указанную позицию в массиве символов Unicode.

9

public bool EndsWith (строковое значение)

Определяет, соответствует ли конец строкового объекта указанной строке.

10

public bool Equals (строковое значение)

Определяет, имеют ли текущий объект String и указанный объект String одинаковые значения.

11

public static bool Equals (строка a, строка b)

Определяет, имеют ли два указанных объекта String одинаковое значение.

12

открытый статический формат строки (формат строки, объект arg0)

Заменяет один или несколько элементов формата в указанной строке строковым представлением указанного объекта.

13

public int IndexOf (значение char)

Возвращает нулевой индекс первого вхождения указанного символа Unicode в текущей строке.

14

public int IndexOf (строковое значение)

Возвращает нулевой индекс первого вхождения указанной строки в этом экземпляре.

15

public int IndexOf (значение char, int startIndex)

Возвращает нулевой индекс первого вхождения указанного символа Unicode в этой строке, начиная поиск с указанной позиции символа.

16

public int IndexOf (строковое значение, int startIndex)

Возвращает нулевой индекс первого вхождения указанной строки в этом случае, начиная поиск с указанной позиции символа.

17

public int IndexOfAny (char [] anyOf)

Возвращает нулевой индекс первого вхождения в этом экземпляре любого символа в указанном массиве символов Юникода.

18

public int IndexOfAny (char [] anyOf, int startIndex)

Возвращает нулевой индекс первого вхождения в этом экземпляре любого символа в указанном массиве символов Юникода, начиная поиск с указанной позиции символа.

19

публичная строка Insert (int startIndex, строковое значение)

Возвращает новую строку, в которой указанная строка вставлена ​​в указанную позицию индекса в текущем строковом объекте.

20

public static bool IsNullOrEmpty (строковое значение)

Указывает, является ли указанная строка пустой или пустой строкой.

21

открытая статическая строка Join (разделитель строк, params string [] value)

Объединяет все элементы массива строк, используя указанный разделитель между каждым элементом.

22

открытая статическая строка Join (разделитель строк, значение string [], int startIndex, int count)

Объединяет указанные элементы массива строк, используя указанный разделитель между каждым элементом.

23

public int LastIndexOf (значение символа)

Возвращает нулевую позицию индекса последнего вхождения указанного символа Unicode в текущем строковом объекте.

24

public int LastIndexOf (строковое значение)

Возвращает нулевую позицию индекса последнего вхождения указанной строки в текущем строковом объекте.

25

открытая строка Remove (int startIndex)

Удаляет все символы в текущем экземпляре, начиная с указанной позиции и продолжая до последней позиции, и возвращает строку.

26

открытая строка Remove (int startIndex, int count)

Удаляет указанное количество символов в текущей строке, начиная с указанной позиции, и возвращает строку.

27

публичная строка Replace (char oldChar, char newChar)

Заменяет все вхождения указанного символа Unicode в текущем строковом объекте на указанный символ Unicode и возвращает новую строку.

28

публичная строка Replace (строка oldValue, строка newValue)

Заменяет все вхождения указанной строки в текущем строковом объекте на указанную строку и возвращает новую строку.

29

открытая строка [] Split (params char [] разделитель)

Возвращает строковый массив, содержащий подстроки в текущем строковом объекте, разделенные элементами указанного массива символов Unicode.

30

открытая строка [] Split (разделитель char [], int count)

Возвращает строковый массив, содержащий подстроки в текущем строковом объекте, разделенные элементами указанного массива символов Unicode. Параметр int указывает максимальное количество возвращаемых подстрок.

31

public bool StartsWith (строковое значение)

Определяет, соответствует ли начало этого экземпляра строки указанной строке.

32

public char [] ToCharArray ()

Возвращает массив символов Unicode со всеми символами в текущем строковом объекте.

33

public char [] ToCharArray (int startIndex, int length)

Возвращает массив символов Unicode со всеми символами в текущем строковом объекте, начиная с указанного индекса и до указанной длины.

34

открытая строка ToLower ()

Возвращает копию этой строки, преобразованную в нижний регистр.

35

открытая строка ToUpper ()

Возвращает копию этой строки, преобразованную в верхний регистр.

36

открытая строка Trim ()

Удаляет все начальные и конечные пробельные символы из текущего объекта String.

public static int Compare (строка strA, строка strB)

Сравнивает два указанных строковых объекта и возвращает целое число, которое указывает их относительное положение в порядке сортировки.

public static int Compare (строка strA, строка strB, bool ignoreCase)

Сравнивает два указанных строковых объекта и возвращает целое число, которое указывает их относительное положение в порядке сортировки. Однако он игнорирует случай, если логический параметр имеет значение true.

открытая статическая строка Concat (строка str0, строка str1)

Объединяет два строковых объекта.

открытая статическая строка Concat (строка str0, строка str1, строка str2)

Объединяет три строковых объекта.

открытая статическая строка Concat (строка str0, строка str1, строка str2, строка str3)

Объединяет четыре строковых объекта.

public bool Contains (строковое значение)

Возвращает значение, указывающее, встречается ли указанный объект String в этой строке.

публичная статическая строка Copy (строка str)

Создает новый объект String с тем же значением, что и указанная строка.

public void CopyTo (int sourceIndex, char [] destination, int destinationIndex, int count)

Копирует указанное количество символов из указанной позиции объекта String в указанную позицию в массиве символов Unicode.

public bool EndsWith (строковое значение)

Определяет, соответствует ли конец строкового объекта указанной строке.

public bool Equals (строковое значение)

Определяет, имеют ли текущий объект String и указанный объект String одинаковые значения.

public static bool Equals (строка a, строка b)

Определяет, имеют ли два указанных объекта String одинаковое значение.

открытый статический формат строки (формат строки, объект arg0)

Заменяет один или несколько элементов формата в указанной строке строковым представлением указанного объекта.

public int IndexOf (значение char)

Возвращает нулевой индекс первого вхождения указанного символа Unicode в текущей строке.

public int IndexOf (строковое значение)

Возвращает нулевой индекс первого вхождения указанной строки в этом экземпляре.

public int IndexOf (значение char, int startIndex)

Возвращает нулевой индекс первого вхождения указанного символа Unicode в этой строке, начиная поиск с указанной позиции символа.

public int IndexOf (строковое значение, int startIndex)

Возвращает нулевой индекс первого вхождения указанной строки в этом случае, начиная поиск с указанной позиции символа.

public int IndexOfAny (char [] anyOf)

Возвращает нулевой индекс первого вхождения в этом экземпляре любого символа в указанном массиве символов Юникода.

public int IndexOfAny (char [] anyOf, int startIndex)

Возвращает нулевой индекс первого вхождения в этом экземпляре любого символа в указанном массиве символов Юникода, начиная поиск с указанной позиции символа.

публичная строка Insert (int startIndex, строковое значение)

Возвращает новую строку, в которой указанная строка вставлена ​​в указанную позицию индекса в текущем строковом объекте.

public static bool IsNullOrEmpty (строковое значение)

Указывает, является ли указанная строка пустой или пустой строкой.

открытая статическая строка Join (разделитель строк, params string [] value)

Объединяет все элементы массива строк, используя указанный разделитель между каждым элементом.

открытая статическая строка Join (разделитель строк, значение string [], int startIndex, int count)

Объединяет указанные элементы массива строк, используя указанный разделитель между каждым элементом.

public int LastIndexOf (значение символа)

Возвращает нулевую позицию индекса последнего вхождения указанного символа Unicode в текущем строковом объекте.

public int LastIndexOf (строковое значение)

Возвращает нулевую позицию индекса последнего вхождения указанной строки в текущем строковом объекте.

открытая строка Remove (int startIndex)

Удаляет все символы в текущем экземпляре, начиная с указанной позиции и продолжая до последней позиции, и возвращает строку.

открытая строка Remove (int startIndex, int count)

Удаляет указанное количество символов в текущей строке, начиная с указанной позиции, и возвращает строку.

публичная строка Replace (char oldChar, char newChar)

Заменяет все вхождения указанного символа Unicode в текущем строковом объекте на указанный символ Unicode и возвращает новую строку.

публичная строка Replace (строка oldValue, строка newValue)

Заменяет все вхождения указанной строки в текущем строковом объекте на указанную строку и возвращает новую строку.

открытая строка [] Split (params char [] разделитель)

Возвращает строковый массив, содержащий подстроки в текущем строковом объекте, разделенные элементами указанного массива символов Unicode.

открытая строка [] Split (разделитель char [], int count)

Возвращает строковый массив, содержащий подстроки в текущем строковом объекте, разделенные элементами указанного массива символов Unicode. Параметр int указывает максимальное количество возвращаемых подстрок.

public bool StartsWith (строковое значение)

Определяет, соответствует ли начало этого экземпляра строки указанной строке.

public char [] ToCharArray ()

Возвращает массив символов Unicode со всеми символами в текущем строковом объекте.

public char [] ToCharArray (int startIndex, int length)

Возвращает массив символов Unicode со всеми символами в текущем строковом объекте, начиная с указанного индекса и до указанной длины.

открытая строка ToLower ()

Возвращает копию этой строки, преобразованную в нижний регистр.

открытая строка ToUpper ()

Возвращает копию этой строки, преобразованную в верхний регистр.

открытая строка Trim ()

Удаляет все начальные и конечные пробельные символы из текущего объекта String.

Вы можете посетить библиотеку MSDN для получения полного списка методов и конструкторов классов String.

Примеры

Следующий пример демонстрирует некоторые из методов, упомянутых выше —

Сравнение строк

using System;

namespace StringApplication {

   class StringProg {
   
      static void Main(string[] args) {
         string str1 = "This is test";
         string str2 = "This is text";

         if (String.Compare(str1, str2) == 0) {
            Console.WriteLine(str1 + " and " + str2 +  " are equal.");
         } else {
            Console.WriteLine(str1 + " and " + str2 + " are not equal.");
         }
         Console.ReadKey() ;
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

This is test and This is text are not equal.

Строка содержит строку

using System;

namespace StringApplication {

   class StringProg {
   
      static void Main(string[] args) {
         string str = "This is test";
         
         if (str.Contains("test")) {
            Console.WriteLine("The sequence 'test' was found.");
         }
         Console.ReadKey() ;
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

The sequence 'test' was found.

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

using System;

namespace StringApplication {

   class StringProg {
   
      static void Main(string[] args) {
         string str = "Last night I dreamt of San Pedro";
         Console.WriteLine(str);
         string substr = str.Substring(23);
         Console.WriteLine(substr);
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

San Pedro

Строки соединения

using System;

namespace StringApplication {

   class StringProg {
   
      static void Main(string[] args) {
         string[] starray = new string[]{"Down the way nights are dark",
            "And the sun shines daily on the mountain top",
            "I took a trip on a sailing ship",
            "And when I reached Jamaica",
            "I made a stop"};

         string str = String.Join("\n", starray);
         Console.WriteLine(str);
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Down the way nights are dark
And the sun shines daily on the mountain top
I took a trip on a sailing ship
And when I reached Jamaica
I made a stop

C # — Структуры

В C # структура является типом данных типа значения. Это помогает вам сделать одну переменную для хранения связанных данных различных типов данных. Ключевое слово struct используется для создания структуры.

Структуры используются для представления записи. Предположим, вы хотите отслеживать свои книги в библиотеке. Вы можете отслеживать следующие атрибуты о каждой книге —

  • заглавие
  • автор
  • Предмет
  • ID книги

Определение структуры

Чтобы определить структуру, вы должны использовать инструкцию struct. Оператор struct определяет новый тип данных с более чем одним членом для вашей программы.

Например, вот как вы можете объявить структуру Book —

struct Books {
   public string title;
   public string author;
   public string subject;
   public int book_id;
};  

Следующая программа показывает использование структуры —

using System;

struct Books {
   public string title;
   public string author;
   public string subject;
   public int book_id;
};  

public class testStructure {

   public static void Main(string[] args) {
      Books Book1;   /* Declare Book1 of type Book */
      Books Book2;   /* Declare Book2 of type Book */

      /* book 1 specification */
      Book1.title = "C Programming";
      Book1.author = "Nuha Ali"; 
      Book1.subject = "C Programming Tutorial";
      Book1.book_id = 6495407;

      /* book 2 specification */
      Book2.title = "Telecom Billing";
      Book2.author = "Zara Ali";
      Book2.subject =  "Telecom Billing Tutorial";
      Book2.book_id = 6495700;

      /* print Book1 info */
      Console.WriteLine( "Book 1 title : {0}", Book1.title);
      Console.WriteLine("Book 1 author : {0}", Book1.author);
      Console.WriteLine("Book 1 subject : {0}", Book1.subject);
      Console.WriteLine("Book 1 book_id :{0}", Book1.book_id);

      /* print Book2 info */
      Console.WriteLine("Book 2 title : {0}", Book2.title);
      Console.WriteLine("Book 2 author : {0}", Book2.author);
      Console.WriteLine("Book 2 subject : {0}", Book2.subject);
      Console.WriteLine("Book 2 book_id : {0}", Book2.book_id);       

      Console.ReadKey();
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

Особенности структур C #

Вы уже использовали простую структуру с именем Книги. Структуры в C # весьма отличаются от традиционных C или C ++. Структуры C # имеют следующие особенности —

  • Структуры могут иметь методы, поля, индексаторы, свойства, операторные методы и события.

  • Структуры могут иметь определенные конструкторы, но не деструкторы. Однако вы не можете определить конструктор по умолчанию для структуры. Конструктор по умолчанию определяется автоматически и не может быть изменен.

  • В отличие от классов, структуры не могут наследовать другие структуры или классы.

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

  • Структура может реализовывать один или несколько интерфейсов.

  • Члены структуры не могут быть определены как абстрактные, виртуальные или защищенные.

  • Когда вы создаете объект структуры с помощью оператора New , он создается и вызывается соответствующий конструктор. В отличие от классов, структуры могут быть созданы без использования оператора New.

  • Если оператор New не используется, поля остаются неназначенными, и объект нельзя использовать, пока все поля не будут инициализированы.

Структуры могут иметь методы, поля, индексаторы, свойства, операторные методы и события.

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

В отличие от классов, структуры не могут наследовать другие структуры или классы.

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

Структура может реализовывать один или несколько интерфейсов.

Члены структуры не могут быть определены как абстрактные, виртуальные или защищенные.

Когда вы создаете объект структуры с помощью оператора New , он создается и вызывается соответствующий конструктор. В отличие от классов, структуры могут быть созданы без использования оператора New.

Если оператор New не используется, поля остаются неназначенными, и объект нельзя использовать, пока все поля не будут инициализированы.

Класс против структуры

Классы и структуры имеют следующие основные различия —

  • классы являются ссылочными типами, а структуры являются типами значений
  • структуры не поддерживают наследование
  • структуры не могут иметь конструктор по умолчанию

В свете вышесказанного, давайте перепишем предыдущий пример —

using System;

struct Books {
   private string title;
   private string author;
   private string subject;
   private int book_id;
   
   public void getValues(string t, string a, string s, int id) {
      title = t;
      author = a;
      subject = s;
      book_id = id;
   }
   
   public void display() {
      Console.WriteLine("Title : {0}", title);
      Console.WriteLine("Author : {0}", author);
      Console.WriteLine("Subject : {0}", subject);
      Console.WriteLine("Book_id :{0}", book_id);
   }
};  

public class testStructure {

   public static void Main(string[] args) {
      Books Book1 = new Books();   /* Declare Book1 of type Book */
      Books Book2 = new Books();   /* Declare Book2 of type Book */

      /* book 1 specification */
      Book1.getValues("C Programming",
      "Nuha Ali", "C Programming Tutorial",6495407);

      /* book 2 specification */
      Book2.getValues("Telecom Billing",
      "Zara Ali", "Telecom Billing Tutorial", 6495700);

      /* print Book1 info */
      Book1.display();

      /* print Book2 info */
      Book2.display(); 

      Console.ReadKey();
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Title : C Programming
Author : Nuha Ali
Subject : C Programming Tutorial
Book_id : 6495407
Title : Telecom Billing
Author : Zara Ali
Subject : Telecom Billing Tutorial
Book_id : 6495700

C # — Перечисления

Перечисление — это набор именованных целочисленных констант. Перечислимый тип объявляется с использованием ключевого слова enum .

Перечисления C # являются типом данных value. Другими словами, перечисление содержит свои собственные значения и не может наследовать или не может передавать наследование.

Объявление enum Variable

Общий синтаксис объявления перечисления —

enum <enum_name> {
   enumeration list 
};

Куда,

  • Enum_name указывает имя типа перечисления.

  • Список перечисления представляет собой список идентификаторов через запятую.

Enum_name указывает имя типа перечисления.

Список перечисления представляет собой список идентификаторов через запятую.

Каждый из символов в списке перечисления обозначает целочисленное значение, на один больше, чем символ, который предшествует ему. По умолчанию значение первого символа перечисления равно 0. Например, —

enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };

пример

В следующем примере демонстрируется использование переменной enum —

using System;

namespace EnumApplication {

   class EnumProgram {
      enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };

      static void Main(string[] args) {
         int WeekdayStart = (int)Days.Mon;
         int WeekdayEnd = (int)Days.Fri;
         Console.WriteLine("Monday: {0}", WeekdayStart);
         Console.WriteLine("Friday: {0}", WeekdayEnd);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Monday: 1
Friday: 5

C # — Классы

Когда вы определяете класс, вы определяете план для типа данных. На самом деле это не определяет какие-либо данные, но определяет, что означает имя класса. То есть, из чего состоит объект класса и какие операции могут быть выполнены над этим объектом. Объекты являются экземплярами класса. Методы и переменные, которые составляют класс, называются членами класса.

Определение класса

Определение класса начинается с ключевого слова class, за которым следует имя класса; и тело класса, заключенное в пару фигурных скобок. Ниже приводится общая форма определения класса —

<access specifier> class  class_name {
   // member variables
   <access specifier> <data type> variable1;
   <access specifier> <data type> variable2;
   ...
   <access specifier> <data type> variableN;
   // member methods
   <access specifier> <return type> method1(parameter_list) {
      // method body
   }
   <access specifier> <return type> method2(parameter_list) {
      // method body
   }
   ...
   <access specifier> <return type> methodN(parameter_list) {
      // method body
   }
}

Примечание —

  • Спецификаторы доступа определяют правила доступа для членов, а также самого класса. Если не упомянуто, то спецификатор доступа по умолчанию для типа класса является внутренним . Доступ по умолчанию для членов является закрытым .

  • Тип данных указывает тип переменной, а возвращаемый тип указывает тип данных, которые возвращает метод, если таковые имеются.

  • Чтобы получить доступ к членам класса, вы используете оператор точки (.).

  • Точечный оператор связывает имя объекта с именем члена.

Спецификаторы доступа определяют правила доступа для членов, а также самого класса. Если не упомянуто, то спецификатор доступа по умолчанию для типа класса является внутренним . Доступ по умолчанию для членов является закрытым .

Тип данных указывает тип переменной, а возвращаемый тип указывает тип данных, которые возвращает метод, если таковые имеются.

Чтобы получить доступ к членам класса, вы используете оператор точки (.).

Точечный оператор связывает имя объекта с именем члена.

Следующий пример иллюстрирует концепции, которые обсуждались до сих пор —

using System;

namespace BoxApplication {

    class Box {
       public double length;   // Length of a box
       public double breadth;  // Breadth of a box
       public double height;   // Height of a box
    }
    
    class Boxtester {

        static void Main(string[] args) {
            Box Box1 = new Box();   // Declare Box1 of type Box
            Box Box2 = new Box();   // Declare Box2 of type Box
            double volume = 0.0;    // Store the volume of a box here

            // box 1 specification
            Box1.height = 5.0;
            Box1.length = 6.0;
            Box1.breadth = 7.0;

            // box 2 specification
            Box2.height = 10.0;
            Box2.length = 12.0;
            Box2.breadth = 13.0;
           
            // volume of box 1
            volume = Box1.height * Box1.length * Box1.breadth;
            Console.WriteLine("Volume of Box1 : {0}",  volume);

            // volume of box 2
            volume = Box2.height * Box2.length * Box2.breadth;
            Console.WriteLine("Volume of Box2 : {0}", volume);
            Console.ReadKey();
        }
    }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Volume of Box1 : 210
Volume of Box2 : 1560

Функции-члены и инкапсуляция

Функция-член класса — это функция, определение которой или ее прототип в определении класса аналогичны любой другой переменной. Он работает с любым объектом класса, членом которого он является, и имеет доступ ко всем членам класса для этого объекта.

Переменные-члены — это атрибуты объекта (с точки зрения разработки), и они остаются закрытыми для реализации инкапсуляции. Эти переменные могут быть доступны только с помощью открытых функций-членов.

Давайте изложим вышеупомянутые концепции, чтобы установить и получить значение различных членов класса в классе —

using System;

namespace BoxApplication {

   class Box {
      private double length;   // Length of a box
      private double breadth;  // Breadth of a box
      private double height;   // Height of a box
      
      public void setLength( double len ) {
         length = len;
      }
      
      public void setBreadth( double bre ) {
         breadth = bre;
      }
      
      public void setHeight( double hei ) {
         height = hei;
      }
      public double getVolume() {
         return length * breadth * height;
      }
   }
   
   class Boxtester {
   
      static void Main(string[] args) {
         Box Box1 = new Box();   // Declare Box1 of type Box
         Box Box2 = new Box();
         double volume;
         
         // Declare Box2 of type Box
         // box 1 specification
         Box1.setLength(6.0);
         Box1.setBreadth(7.0);
         Box1.setHeight(5.0);
         
         // box 2 specification
         Box2.setLength(12.0);
         Box2.setBreadth(13.0);
         Box2.setHeight(10.0);
         
         // volume of box 1
         volume = Box1.getVolume();
         Console.WriteLine("Volume of Box1 : {0}" ,volume);
         
         // volume of box 2
         volume = Box2.getVolume();
         Console.WriteLine("Volume of Box2 : {0}", volume);
         
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Volume of Box1 : 210
Volume of Box2 : 1560

Конструкторы C #

Конструктор класса — это специальная функция-член класса, которая выполняется всякий раз, когда мы создаем новые объекты этого класса.

Конструктор имеет точно такое же имя, как и у класса, и не имеет никакого возвращаемого типа. Следующий пример объясняет концепцию конструктора —

using System;

namespace LineApplication {

   class Line {
      private double length;   // Length of a line
      
      public Line() {
         Console.WriteLine("Object is being created");
      }

      public void setLength( double len ) {
         length = len;
      }
      
      public double getLength() {
         return length;
      }

      static void Main(string[] args) {
         Line line = new Line();    
         
         // set line length
         line.setLength(6.0);
         Console.WriteLine("Length of line : {0}", line.getLength());
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Object is being created
Length of line : 6

Конструктор по умолчанию не имеет параметров, но если вам нужно, конструктор может иметь параметры. Такие конструкторы называются параметризованными конструкторами . Этот метод помогает вам присвоить начальное значение объекту во время его создания, как показано в следующем примере:

using System;

namespace LineApplication {

   class Line {
      private double length;   // Length of a line
      
      public Line(double len) {  //Parameterized constructor
         Console.WriteLine("Object is being created, length = {0}", len);
         length = len;
      }

      public void setLength( double len ) {
         length = len;
      }
      
      public double getLength() {
         return length;
      }

      static void Main(string[] args) {
         Line line = new Line(10.0);
         Console.WriteLine("Length of line : {0}", line.getLength()); 
         
         // set line length
         line.setLength(6.0);
         Console.WriteLine("Length of line : {0}", line.getLength()); 
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Object is being created, length = 10
Length of line : 10
Length of line : 6

C # Деструкторы

Деструктор — это специальная функция-член класса, которая выполняется всякий раз, когда объект его класса выходит из области видимости. Деструктор имеет точно такое же имя, как и у класса с префиксом тильда (~), и он не может ни возвращать значение, ни принимать какие-либо параметры.

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

Следующий пример объясняет понятие деструктора —

using System;

namespace LineApplication {

   class Line {
      private double length;   // Length of a line
      
      public Line() {   // constructor
         Console.WriteLine("Object is being created");
      }
      
      ~Line() {   //destructor
         Console.WriteLine("Object is being deleted");
      }

      public void setLength( double len ) {
         length = len;
      }

      public double getLength() {
         return length;
      }

      static void Main(string[] args) {
         Line line = new Line();

         // set line length
         line.setLength(6.0);
         Console.WriteLine("Length of line : {0}", line.getLength());           
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Object is being created
Length of line : 6
Object is being deleted

Статические члены класса C #

Мы можем определить членов класса как статические, используя ключевое слово static . Когда мы объявляем член класса статическим, это означает, что независимо от того, сколько объектов класса создано, существует только одна копия статического члена.

Ключевое слово static подразумевает, что для класса существует только один экземпляр члена. Статические переменные используются для определения констант, потому что их значения могут быть получены путем вызова класса без создания его экземпляра. Статические переменные могут быть инициализированы вне функции-члена или определения класса. Вы также можете инициализировать статические переменные внутри определения класса.

В следующем примере демонстрируется использование статических переменных

using System;

namespace StaticVarApplication {

   class StaticVar {
      public static int num;
      
      public void count() {
         num++;
      }
      
      public int getNum() {
         return num;
      }
   }
   
   class StaticTester {
   
      static void Main(string[] args) {
         StaticVar s1 = new StaticVar();
         StaticVar s2 = new StaticVar();
         s1.count();
         s1.count();
         s1.count();
         s2.count();
         s2.count();
         s2.count();
         Console.WriteLine("Variable num for s1: {0}", s1.getNum());
         Console.WriteLine("Variable num for s2: {0}", s2.getNum());
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Variable num for s1: 6
Variable num for s2: 6

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

using System;

namespace StaticVarApplication {

   class StaticVar {
      public static int num;
      
      public void count() {
         num++;
      }
      
      public static int getNum() {
         return num;
      }
   }
   
   class StaticTester {
   
      static void Main(string[] args) {
         StaticVar s = new StaticVar();
         s.count();
         s.count();
         s.count();
         Console.WriteLine("Variable num: {0}", StaticVar.getNum());
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Variable num: 3

C # — Наследование

Одним из наиболее важных понятий в объектно-ориентированном программировании является наследование. Наследование позволяет нам определять класс в терминах другого класса, что облегчает создание и поддержку приложения. Это также дает возможность повторно использовать функциональные возможности кода и ускоряет время реализации.

При создании класса, вместо того, чтобы писать совершенно новые члены-данные и функции-члены, программист может указать, что новый класс должен наследовать члены существующего класса. Этот существующий класс называется базовым классом, а новый класс называется производным классом.

Идея наследования реализует отношения IS-A . Например, млекопитающее — это животное, собака — это млекопитающее, следовательно, собака это тоже животное, и так далее.

Базовые и производные классы

Класс может быть производным от нескольких классов или интерфейсов, что означает, что он может наследовать данные и функции от нескольких базовых классов или интерфейсов.

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

<acess-specifier> class <base_class> {
   ...
}

class <derived_class> : <base_class> {
   ...
}

Рассмотрим базовый класс Shape и его производный класс Rectangle —

using System;

namespace InheritanceApplication {
   
   class Shape {
      
      public void setWidth(int w) {
         width = w;
      }
      
      public void setHeight(int h) {
         height = h;
      }
      protected int width;
      protected int height;
   }

   // Derived class
   class Rectangle: Shape {
      
      public int getArea() { 
         return (width * height); 
      }
   }
   
   class RectangleTester {
   
      static void Main(string[] args) {
         Rectangle Rect = new Rectangle();

         Rect.setWidth(5);
         Rect.setHeight(7);

         // Print the area of the object.
         Console.WriteLine("Total area: {0}",  Rect.getArea());
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Total area: 35

Инициализация базового класса

Производный класс наследует переменные-члены базового класса и методы-члены. Следовательно, объект суперкласса должен быть создан до создания подкласса. Вы можете дать инструкции по инициализации суперкласса в списке инициализации члена.

Следующая программа демонстрирует это —

using System;

namespace RectangleApplication {

   class Rectangle {
      //member variables
      protected double length;
      protected double width;
      
      public Rectangle(double l, double w) {
         length = l;
         width = w;
      }
      
      public double GetArea() {
         return length * width;
      }
      
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle  
   
   class Tabletop : Rectangle {
      private double cost;
      public Tabletop(double l, double w) : base(l, w) { }
      
      public double GetCost() {
         double cost;
         cost = GetArea() * 70;
         return cost;
      }
      
      public void Display() {
         base.Display();
         Console.WriteLine("Cost: {0}", GetCost());
      }
   }
   
   class ExecuteRectangle {
      
      static void Main(string[] args) {
         Tabletop t = new Tabletop(4.5, 7.5);
         t.Display();
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Length: 4.5
Width: 7.5
Area: 33.75
Cost: 2362.5

Множественное наследование в C #

C # не поддерживает множественное наследование . Однако вы можете использовать интерфейсы для реализации множественного наследования. Следующая программа демонстрирует это —

using System;

namespace InheritanceApplication {
   
   class Shape {
      
      public void setWidth(int w) {
         width = w;
      }
      
      public void setHeight(int h) {
         height = h;
      }
      protected int width;
      protected int height;
   }

   // Base class PaintCost
   public interface PaintCost {
      int getCost(int area);
   }
   
   // Derived class
   class Rectangle : Shape, PaintCost {
      
      public int getArea() {
         return (width * height);
      }
      
      public int getCost(int area) {
         return area * 70;
      }
   }
   
   class RectangleTester {
      
      static void Main(string[] args) {
         Rectangle Rect = new Rectangle();
         int area;
         Rect.setWidth(5);
         Rect.setHeight(7);
         area = Rect.getArea();
         
         // Print the area of the object.
         Console.WriteLine("Total area: {0}",  Rect.getArea());
         Console.WriteLine("Total paint cost: ${0}" , Rect.getCost(area));
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Total area: 35
Total paint cost: $2450

C # — Полиморфизм

Слово полиморфизм означает наличие многих форм. В парадигме объектно-ориентированного программирования полиморфизм часто выражается как «один интерфейс, несколько функций».

Полиморфизм может быть статическим или динамическим. В статическом полиморфизме ответ на функцию определяется во время компиляции. В динамическом полиморфизме это решается во время выполнения.

Статический Полиморфизм

Механизм связывания функции с объектом во время компиляции называется ранним связыванием. Это также называется статическим связыванием. C # предоставляет два метода для реализации статического полиморфизма. Они —

  • Перегрузка функций
  • Перегрузка оператора

Мы обсудим перегрузку операторов в следующей главе.

Перегрузка функций

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

В следующем примере показано использование функции print () для печати различных типов данных —

using System;

namespace PolymorphismApplication {

   class Printdata {
   
      void print(int i) {
         Console.WriteLine("Printing int: {0}", i );
      }

      void print(double f) {
         Console.WriteLine("Printing float: {0}" , f);
      }

      void print(string s) {
         Console.WriteLine("Printing string: {0}", s);
      }
      
      static void Main(string[] args) {
         Printdata p = new Printdata();
         
         // Call print to print integer
         p.print(5);
         
         // Call print to print float
         p.print(500.263);
         
         // Call print to print string
         p.print("Hello C++");
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Printing int: 5
Printing float: 500.263
Printing string: Hello C++

Динамический Полиморфизм

C # позволяет создавать абстрактные классы, которые используются для обеспечения частичной реализации класса интерфейса. Реализация завершается, когда производный класс наследует от него. Абстрактные классы содержат абстрактные методы, которые реализуются производным классом. Производные классы имеют более специализированную функциональность.

Вот правила об абстрактных классах —

  • Вы не можете создать экземпляр абстрактного класса

  • Вы не можете объявить абстрактный метод вне абстрактного класса

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

Вы не можете создать экземпляр абстрактного класса

Вы не можете объявить абстрактный метод вне абстрактного класса

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

Следующая программа демонстрирует абстрактный класс —

using System;

namespace PolymorphismApplication {

   abstract class Shape {
      public abstract int area();
   }
   
   class Rectangle:  Shape {
      private int length;
      private int width;
      
      public Rectangle( int a = 0, int b = 0) {
         length = a;
         width = b;
      }
      
      public override int area () { 
         Console.WriteLine("Rectangle class area :");
         return (width * length); 
      }
   }

   class RectangleTester {
      
      static void Main(string[] args) {
         Rectangle r = new Rectangle(10, 7);
         double a = r.area();
         Console.WriteLine("Area: {0}",a);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Rectangle class area :
Area: 70

Когда у вас есть функция, определенная в классе, которую вы хотите реализовать в унаследованном классе (ах), вы используете виртуальные функции. Виртуальные функции могут быть реализованы по-разному в разных унаследованных классах, и вызов этих функций будет решаться во время выполнения.

Динамический полиморфизм реализуется абстрактными классами и виртуальными функциями .

Следующая программа демонстрирует это —

using System;

namespace PolymorphismApplication {

   class Shape {
      protected int width, height;
      
      public Shape( int a = 0, int b = 0) {
         width = a;
         height = b;
      }
      
      public virtual int area() {
         Console.WriteLine("Parent class area :");
         return 0;
      }
   }
   
   class Rectangle: Shape {
      public Rectangle( int a = 0, int b = 0): base(a, b) {

      }
      
      public override int area () {
         Console.WriteLine("Rectangle class area :");
         return (width * height); 
      }
   }
   
   class Triangle: Shape {
      public Triangle(int a = 0, int b = 0): base(a, b) {
      
      }
      
      public override int area() {
         Console.WriteLine("Triangle class area :");
         return (width * height / 2); 
      }
   }
   
   class Caller {
      public void CallArea(Shape sh) {
         int a;
         a = sh.area();
         Console.WriteLine("Area: {0}", a);
      }
   }  
   
   class Tester {

      static void Main(string[] args) {
         Caller c = new Caller();
         Rectangle r = new Rectangle(10, 7);
         Triangle t = new Triangle(10, 5);
         c.CallArea(r);
         c.CallArea(t);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Rectangle class area:
Area: 70
Triangle class area:
Area: 25

C # — Перегрузка оператора

Вы можете переопределить или перегрузить большинство встроенных операторов, доступных в C #. Таким образом, программист может использовать операторы с пользовательскими типами. Перегруженные операторы — это функции со специальными именами ключевое слово operator, за которым следует символ определяемого оператора. Как и любая другая функция, перегруженный оператор имеет тип возвращаемого значения и список параметров.

Например, выполните следующую функцию —

public static Box operator+ (Box b, Box c) {
   Box box = new Box();
   box.length = b.length + c.length;
   box.breadth = b.breadth + c.breadth;
   box.height = b.height + c.height;
   return box;
}

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

Реализация перегрузки оператора

Следующая программа показывает полную реализацию —

using System;

namespace OperatorOvlApplication {

   class Box {
      private double length;   // Length of a box
      private double breadth;  // Breadth of a box
      private double height;   // Height of a box

      public double getVolume() {
         return length * breadth * height;
      }
      
      public void setLength( double len ) {
         length = len;
      }

      public void setBreadth( double bre ) {
         breadth = bre;
      }

      public void setHeight( double hei ) {
         height = hei;
      }
      
      // Overload + operator to add two Box objects.
      public static Box operator+ (Box b, Box c) {
         Box box = new Box();
         box.length = b.length + c.length;
         box.breadth = b.breadth + c.breadth;
         box.height = b.height + c.height;
         return box;
      }
   }

   class Tester {
   
      static void Main(string[] args) {
         Box Box1 = new Box();   // Declare Box1 of type Box
         Box Box2 = new Box();   // Declare Box2 of type Box
         Box Box3 = new Box();   // Declare Box3 of type Box
         double volume = 0.0;    // Store the volume of a box here

         // box 1 specification
         Box1.setLength(6.0);
         Box1.setBreadth(7.0);
         Box1.setHeight(5.0);

         // box 2 specification
         Box2.setLength(12.0);
         Box2.setBreadth(13.0);
         Box2.setHeight(10.0);

         // volume of box 1
         volume = Box1.getVolume();
         Console.WriteLine("Volume of Box1 : {0}", volume);

         // volume of box 2
         volume = Box2.getVolume();
         Console.WriteLine("Volume of Box2 : {0}", volume);

         // Add two object as follows:
         Box3 = Box1 + Box2;

         // volume of box 3
         volume = Box3.getVolume();
         Console.WriteLine("Volume of Box3 : {0}", volume);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400

Перегружаемые и не перегружаемые операторы

В следующей таблице описана перегрузочная способность операторов в C # —

Sr.No. Операторы и описание
1

+, -,!, ~, ++, —

Эти унарные операторы принимают один операнд и могут быть перегружены.

2

+, -, *, /,%

Эти двоичные операторы принимают один операнд и могут быть перегружены.

3

==,! =, <,>, <=,> =

Операторы сравнения могут быть перегружены.

4

&&, ||

Условные логические операторы не могут быть перегружены напрямую.

5

+ =, — =, * =, / =,% =

Операторы присваивания не могут быть перегружены.

6

=,.,?:, ->, new, is, sizeof, typeof

Эти операторы не могут быть перегружены.

+, -,!, ~, ++, —

Эти унарные операторы принимают один операнд и могут быть перегружены.

+, -, *, /,%

Эти двоичные операторы принимают один операнд и могут быть перегружены.

==,! =, <,>, <=,> =

Операторы сравнения могут быть перегружены.

&&, ||

Условные логические операторы не могут быть перегружены напрямую.

+ =, — =, * =, / =,% =

Операторы присваивания не могут быть перегружены.

=,.,?:, ->, new, is, sizeof, typeof

Эти операторы не могут быть перегружены.

пример

В свете вышеприведенных обсуждений давайте расширим предыдущий пример и перегрузим еще несколько операторов —

using System;

namespace OperatorOvlApplication {

   class Box {
      private double length;    // Length of a box
      private double breadth;   // Breadth of a box
      private double height;    // Height of a box
      
      public double getVolume() {
         return length * breadth * height;
      }
      
      public void setLength( double len ) {
         length = len;
      }
      
      public void setBreadth( double bre ) {
         breadth = bre;
      }
      
      public void setHeight( double hei ) {
         height = hei;
      }
      
      // Overload + operator to add two Box objects.
      public static Box operator+ (Box b, Box c) {
         Box box = new Box();
         box.length = b.length + c.length;
         box.breadth = b.breadth + c.breadth;
         box.height = b.height + c.height;
         return box;
      }

      public static bool operator == (Box lhs, Box rhs) {
         bool status = false;
         if (lhs.length == rhs.length && lhs.height == rhs.height && lhs.breadth == rhs.breadth) {
            status = true;
         }
         return status;
      }
      
      public static bool operator !=(Box lhs, Box rhs) {
         bool status = false;
         
         if (lhs.length != rhs.length || lhs.height != rhs.height || lhs.breadth != rhs.breadth) {
            status = true;
         }
         return status;
      }
      
      public static bool operator <(Box lhs, Box rhs) {
         bool status = false;
         
         if (lhs.length < rhs.length && lhs.height < rhs.height && lhs.breadth < rhs.breadth) {
            status = true;
         }
         return status;
      }
      
      public static bool operator >(Box lhs, Box rhs) {
         bool status = false;
         
         if (lhs.length > rhs.length && lhs.height > rhs.height && lhs.breadth > rhs.breadth) {
            status = true;
         }
         return status;
      }
      
      public static bool operator <=(Box lhs, Box rhs) {
         bool status = false;
         
         if (lhs.length <= rhs.length && lhs.height <= rhs.height && lhs.breadth <= rhs.breadth) {
            status = true;
         }
         return status;
      }
      
      public static bool operator >=(Box lhs, Box rhs) {
         bool status = false;
         
         if (lhs.length >= rhs.length && lhs.height >= rhs.height && lhs.breadth >= rhs.breadth) {
            status = true;
         }
         return status;
      }
      
      public override string ToString() {
         return String.Format("({0}, {1}, {2})", length, breadth, height);
      }
   }
   
   class Tester {
   
      static void Main(string[] args) {
         Box Box1 = new Box();   // Declare Box1 of type Box
         Box Box2 = new Box();   // Declare Box2 of type Box
         Box Box3 = new Box();   // Declare Box3 of type Box
         Box Box4 = new Box();
         double volume = 0.0;    // Store the volume of a box here
         
         // box 1 specification
         Box1.setLength(6.0);
         Box1.setBreadth(7.0);
         Box1.setHeight(5.0);
         
         // box 2 specification
         Box2.setLength(12.0);
         Box2.setBreadth(13.0);
         Box2.setHeight(10.0);
         
         //displaying the Boxes using the overloaded ToString():
         Console.WriteLine("Box 1: {0}", Box1.ToString());
         Console.WriteLine("Box 2: {0}", Box2.ToString());
         
         // volume of box 1
         volume = Box1.getVolume();
         Console.WriteLine("Volume of Box1 : {0}", volume);
         
         // volume of box 2
         volume = Box2.getVolume();
         Console.WriteLine("Volume of Box2 : {0}", volume);
         
         // Add two object as follows:
         Box3 = Box1 + Box2;
         Console.WriteLine("Box 3: {0}", Box3.ToString());
         
         // volume of box 3
         volume = Box3.getVolume();
         Console.WriteLine("Volume of Box3 : {0}", volume);
         
         //comparing the boxes
         if (Box1 > Box2)
            Console.WriteLine("Box1 is greater than Box2");
         else
            Console.WriteLine("Box1 is  greater than Box2");
         
         if (Box1 < Box2)
            Console.WriteLine("Box1 is less than Box2");
         else
            Console.WriteLine("Box1 is not less than Box2");
         
         if (Box1 >= Box2)
            Console.WriteLine("Box1 is greater or equal to Box2");
         else
            Console.WriteLine("Box1 is not greater or equal to Box2");
         
         if (Box1 <= Box2)
            Console.WriteLine("Box1 is less or equal to Box2");
         else
            Console.WriteLine("Box1 is not less or equal to Box2");
         
         if (Box1 != Box2)
            Console.WriteLine("Box1 is not equal to Box2");
         else
            Console.WriteLine("Box1 is not greater or equal to Box2");
         Box4 = Box3;
         
         if (Box3 == Box4)
            Console.WriteLine("Box3 is equal to Box4");
         else
            Console.WriteLine("Box3 is not equal to Box4");

         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Box 1: (6, 7, 5)
Box 2: (12, 13, 10)
Volume of Box1 : 210
Volume of Box2 : 1560
Box 3: (18, 20, 15)
Volume of Box3 : 5400
Box1 is not greater than Box2
Box1 is less than Box2
Box1 is not greater or equal to Box2
Box1 is less or equal to Box2
Box1 is not equal to Box2
Box3 is equal to Box4

C # — Интерфейсы

Интерфейс определяется как синтаксический контракт, которому должны следовать все классы, наследующие интерфейс. Интерфейс определяет часть «что» в синтаксическом контракте, а производные классы определяют часть «как» в синтаксическом контракте.

Интерфейсы определяют свойства, методы и события, которые являются членами интерфейса. Интерфейсы содержат только декларации членов. Ответственность за определение членов лежит на производном классе. Это часто помогает в обеспечении стандартной структуры, которой будут следовать производные классы.

Абстрактные классы в некоторой степени служат той же цели, однако они в основном используются, когда базовый класс должен объявлять лишь несколько методов, а производный класс реализует функциональные возможности.

Объявление интерфейсов

Интерфейсы объявляются с использованием ключевого слова interface. Это похоже на объявление класса. Интерфейсные операторы общедоступны по умолчанию. Ниже приведен пример объявления интерфейса:

public interface ITransactions {
   // interface members
   void showTransaction();
   double getAmount();
}

пример

Следующий пример демонстрирует реализацию вышеуказанного интерфейса —

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;

namespace InterfaceApplication {
   
   public interface ITransactions {
      // interface members
      void showTransaction();
      double getAmount();
   }
   
   public class Transaction : ITransactions {
      private string tCode;
      private string date;
      private double amount;
      
      public Transaction() {
         tCode = " ";
         date = " ";
         amount = 0.0;
      }
      
      public Transaction(string c, string d, double a) {
         tCode = c;
         date = d;
         amount = a;
      }
      
      public double getAmount() {
         return amount;
      }
      
      public void showTransaction() {
         Console.WriteLine("Transaction: {0}", tCode);
         Console.WriteLine("Date: {0}", date);
         Console.WriteLine("Amount: {0}", getAmount());
      }
   }
   
   class Tester {
     
      static void Main(string[] args) {
         Transaction t1 = new Transaction("001", "8/10/2012", 78900.00);
         Transaction t2 = new Transaction("002", "9/10/2012", 451900.00);
         t1.showTransaction();
         t2.showTransaction();
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Transaction: 001
Date: 8/10/2012
Amount: 78900
Transaction: 002
Date: 9/10/2012
Amount: 451900

C # — Пространства имен

Пространство имен предназначено для обеспечения способа отделить один набор имен от другого. Имена классов, объявленные в одном пространстве имен, не конфликтуют с теми же именами классов, объявленными в другом.

Определение пространства имен

Определение пространства имен начинается с ключевого слова namespace, за которым следует имя пространства имен следующим образом:

namespace namespace_name {
   // code declarations
}

Чтобы вызвать версию функции или переменной с пространством имен, добавьте имя пространства имен следующим образом:

namespace_name.item_name;

Следующая программа демонстрирует использование пространств имен —

using System;

namespace first_space {

   class namespace_cl {
   
      public void func() {
         Console.WriteLine("Inside first_space");
      }
   }
}

namespace second_space {

   class namespace_cl {
   
      public void func() {
         Console.WriteLine("Inside second_space");
      }
   }
}

class TestClass {

   static void Main(string[] args) {
      first_space.namespace_cl fc = new first_space.namespace_cl();
      second_space.namespace_cl sc = new second_space.namespace_cl();
      fc.func();
      sc.func();
      Console.ReadKey();
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Inside first_space
Inside second_space

Использование ключевого слова

Ключевое слово using указывает, что программа использует имена в заданном пространстве имен. Например, мы используем пространство имен System в наших программах. Класс Console определен там. Мы просто пишем —

Console.WriteLine ("Hello there");

Мы могли бы написать полное имя как —

System.Console.WriteLine("Hello there");

Вы также можете избежать добавления пространств имен с помощью директивы using namespace. Эта директива сообщает компилятору, что последующий код использует имена в указанном пространстве имен. Таким образом, пространство имен подразумевается для следующего кода:

Давайте перепишем наш предыдущий пример с использованием директивы —

using System;
using first_space;
using second_space;

namespace first_space {

   class abc {
   
      public void func() {
         Console.WriteLine("Inside first_space");
      }
   }
}

namespace second_space {

   class efg {
   
      public void func() {
         Console.WriteLine("Inside second_space");
      }
   }
}   

class TestClass {

   static void Main(string[] args) {
      abc fc = new abc();
      efg sc = new efg();
      fc.func();
      sc.func();
      Console.ReadKey();
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Inside first_space
Inside second_space

Вложенные пространства имен

Вы можете определить одно пространство имен внутри другого пространства имен следующим образом:

namespace namespace_name1 {
   
   // code declarations
   namespace namespace_name2 {
      // code declarations
   }
}

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

using System;
using first_space;
using first_space.second_space;

namespace first_space {

   class abc {
   
      public void func() {
         Console.WriteLine("Inside first_space");
      }
   }
   
   namespace second_space {
   
      class efg {
      
         public void func() {
            Console.WriteLine("Inside second_space");
         }
      }
   }   
}
 
class TestClass {

   static void Main(string[] args) {
      abc fc = new abc();
      efg sc = new efg();
      fc.func();
      sc.func();
      Console.ReadKey();
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Inside first_space
Inside second_space

C # — Директивы препроцессора

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

Все директивы препроцессора начинаются с #, и перед директивой препроцессора в строке могут появляться только символы пробела. Директивы препроцессора не являются операторами, поэтому они не заканчиваются точкой с запятой (;).

Компилятор C # не имеет отдельного препроцессора; однако директивы обрабатываются так, как если бы они были. В C # директивы препроцессора используются для помощи в условной компиляции. В отличие от директив C и C ++, они не используются для создания макросов. Директива препроцессора должна быть единственной инструкцией в строке.

Директивы препроцессора в C #

В следующей таблице перечислены директивы препроцессора, доступные в C # —

Sr.No. Директива препроцессора и описание
1

#define

Он определяет последовательность символов, называемых символом.

2

#undef

Это позволяет вам определить символ.

3

#если

Это позволяет протестировать символ или символы, чтобы увидеть, оценивают ли они значение true.

4

#else

Это позволяет создать составную условную директиву вместе с #if.

5

#elif

Это позволяет создать составную условную директиву.

6

#endif

Определяет конец условной директивы.

7

#линия

Это позволяет вам изменить номер строки компилятора и (опционально) вывод имени файла для ошибок и предупреждений.

8

#ошибка

Это позволяет генерировать ошибку из определенного места в вашем коде.

9

#предупреждение

Это позволяет генерировать предупреждение первого уровня из определенного места в вашем коде.

10

#область, край

Он позволяет указать блок кода, который можно развернуть или свернуть при использовании функции выделения в редакторе кода Visual Studio.

11

#endregion

Это отмечает конец блока #region.

#define

Он определяет последовательность символов, называемых символом.

#undef

Это позволяет вам определить символ.

#если

Это позволяет протестировать символ или символы, чтобы увидеть, оценивают ли они значение true.

#else

Это позволяет создать составную условную директиву вместе с #if.

#elif

Это позволяет создать составную условную директиву.

#endif

Определяет конец условной директивы.

#линия

Это позволяет вам изменить номер строки компилятора и (опционально) вывод имени файла для ошибок и предупреждений.

#ошибка

Это позволяет генерировать ошибку из определенного места в вашем коде.

#предупреждение

Это позволяет генерировать предупреждение первого уровня из определенного места в вашем коде.

#область, край

Он позволяет указать блок кода, который можно развернуть или свернуть при использовании функции выделения в редакторе кода Visual Studio.

#endregion

Это отмечает конец блока #region.

Препроцессор #define

Директива препроцессора #define создает символические константы.

#define позволяет вам определить символ так, чтобы, используя символ в качестве выражения, переданного директиве #if, выражение оценивалось как true. Его синтаксис выглядит следующим образом —

#define symbol

Следующая программа иллюстрирует это —

#define PI 
using System;

namespace PreprocessorDAppl {

   class Program {
   
      static void Main(string[] args) {
         #if (PI)
            Console.WriteLine("PI is defined");
         #else
            Console.WriteLine("PI is not defined");
         #endif
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

PI is defined

Условные Директивы

Вы можете использовать директиву #if для создания условной директивы. Условные директивы полезны для проверки символа или символов, чтобы проверить, имеют ли они значение true. Если они действительно оцениваются как true, компилятор оценивает весь код между #if и следующей директивой.

Синтаксис для условной директивы —

#if symbol [operator symbol]...

Где символ — это имя символа, который вы хотите проверить. Вы также можете использовать true и false или добавить символ перед оператором отрицания.

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

  • == (равенство)
  • ! = (неравенство)
  • && (а также)
  • || (или же)

Вы также можете группировать символы и операторы в скобках. Условные директивы используются для компиляции кода для отладочной сборки или при компиляции для конкретной конфигурации. Условная директива, начинающаяся с директивы #if, должна явно заканчиваться директивой #endif .

Следующая программа демонстрирует использование условных директив —

#define DEBUG
#define VC_V10
using System;

public class TestClass {

   public static void Main() {
      #if (DEBUG && !VC_V10)
         Console.WriteLine("DEBUG is defined");
      #elif (!DEBUG && VC_V10)
         Console.WriteLine("VC_V10 is defined");
      #elif (DEBUG && VC_V10)
         Console.WriteLine("DEBUG and VC_V10 are defined");
      #else
         Console.WriteLine("DEBUG and VC_V10 are not defined");
      #endif
      Console.ReadKey();
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

DEBUG and VC_V10 are defined

C # — Регулярные выражения

Регулярное выражение — это шаблон, который можно сопоставить с входным текстом. .Net Framework предоставляет механизм регулярных выражений, который позволяет такое сопоставление. Шаблон состоит из одного или нескольких литералов символов, операторов или конструкций.

Конструкции для определения регулярных выражений

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

Персонаж убегает

Классы персонажей

Якоря

Группировка конструкций

Кванторы

Обратные ссылки

Чередование конструкций

Замены

Разные конструкции

Класс Regex

Класс Regex используется для представления регулярного выражения. Он имеет следующие обычно используемые методы —

Sr.No. Методы и описание
1

public bool IsMatch (ввод строки)

Указывает, находит ли регулярное выражение, указанное в конструкторе Regex, совпадение в указанной входной строке.

2

public bool IsMatch (ввод строки, int startat)

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

3

public static bool IsMatch (ввод строки, шаблон строки)

Указывает, находит ли указанное регулярное выражение совпадение в указанной входной строке.

4

public MatchCollection Matches (строковый ввод)

Выполняет поиск в указанной входной строке всех вхождений регулярного выражения.

5

публичная строка Replace (ввод строки, замена строки)

В указанной входной строке заменяет все строки, которые соответствуют шаблону регулярного выражения, указанной строкой замены.

6

public string [] Split (ввод строки)

Разбивает входную строку на массив подстрок в позициях, определенных шаблоном регулярного выражения, указанным в конструкторе Regex.

public bool IsMatch (ввод строки)

Указывает, находит ли регулярное выражение, указанное в конструкторе Regex, совпадение в указанной входной строке.

public bool IsMatch (ввод строки, int startat)

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

public static bool IsMatch (ввод строки, шаблон строки)

Указывает, находит ли указанное регулярное выражение совпадение в указанной входной строке.

public MatchCollection Matches (строковый ввод)

Выполняет поиск в указанной входной строке всех вхождений регулярного выражения.

публичная строка Replace (ввод строки, замена строки)

В указанной входной строке заменяет все строки, которые соответствуют шаблону регулярного выражения, указанной строкой замены.

public string [] Split (ввод строки)

Разбивает входную строку на массив подстрок в позициях, определенных шаблоном регулярного выражения, указанным в конструкторе Regex.

Для полного списка методов и свойств, пожалуйста, прочитайте документацию Microsoft на C #.

Пример 1

В следующем примере сопоставляются слова, начинающиеся с ‘S’ —

using System;
using System.Text.RegularExpressions;

namespace RegExApplication {

   class Program {
   
      private static void showMatch(string text, string expr) {
         Console.WriteLine("The Expression: " + expr);
         MatchCollection mc = Regex.Matches(text, expr);
         foreach (Match m in mc) {
            Console.WriteLine(m);
         }
      }
      
      static void Main(string[] args) {
         string str = "A Thousand Splendid Suns";
         
         Console.WriteLine("Matching words that start with 'S': ");
         showMatch(str, @"\bS\S*");
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Matching words that start with 'S':
The Expression: \bS\S*
Splendid
Suns

Пример 2

В следующем примере сопоставляются слова, которые начинаются с «m» и заканчиваются «e» —

using System;
using System.Text.RegularExpressions;

namespace RegExApplication {

   class Program {
      private static void showMatch(string text, string expr) {
         Console.WriteLine("The Expression: " + expr);
         MatchCollection mc = Regex.Matches(text, expr);
         foreach (Match m in mc) {
            Console.WriteLine(m);
         }
      }
      static void Main(string[] args) {
         string str = "make maze and manage to measure it";

         Console.WriteLine("Matching words start with 'm' and ends with 'e':");
         showMatch(str, @"\bm\S*e\b");
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Matching words start with 'm' and ends with 'e':
The Expression: \bm\S*e\b
make
maze
manage
measure

Пример 3

Этот пример заменяет дополнительный пробел —

using System;
using System.Text.RegularExpressions;

namespace RegExApplication {

   class Program {
   
      static void Main(string[] args) {
         string input = "Hello   World   ";
         string pattern = "\\s+";
         string replacement = " ";
         Regex rgx = new Regex(pattern);
         string result = rgx.Replace(input, replacement);

         Console.WriteLine("Original String: {0}", input);
         Console.WriteLine("Replacement String: {0}", result);    
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Original String: Hello World   
Replacement String: Hello World   

C # — Обработка исключений

Исключением является проблема, возникающая при выполнении программы. Исключение AC # — это ответ на исключительное обстоятельство, которое возникает во время работы программы, например, попытка деления на ноль.

Исключения предоставляют способ передачи управления из одной части программы в другую. Обработка исключений в C # построена на четырех ключевых словах: try , catch , finally и throw .

  • try — блок try идентифицирует блок кода, для которого активируются определенные исключения. За ним следует один или несколько блоков улова.

  • catch — программа ловит исключение с помощью обработчика исключений в том месте программы, где вы хотите решить проблему. Ключевое слово catch указывает на перехват исключения.

  • finally — блок finally используется для выполнения заданного набора операторов независимо от того, было ли выброшено исключение или нет. Например, если вы открываете файл, он должен быть закрыт независимо от того, возбуждено ли исключение или нет.

  • throw — программа выдает исключение при обнаружении проблемы. Это делается с помощью ключевого слова throw.

try — блок try идентифицирует блок кода, для которого активируются определенные исключения. За ним следует один или несколько блоков улова.

catch — программа ловит исключение с помощью обработчика исключений в том месте программы, где вы хотите решить проблему. Ключевое слово catch указывает на перехват исключения.

finally — блок finally используется для выполнения заданного набора операторов независимо от того, было ли выброшено исключение или нет. Например, если вы открываете файл, он должен быть закрыт независимо от того, возбуждено ли исключение или нет.

throw — программа выдает исключение при обнаружении проблемы. Это делается с помощью ключевого слова throw.

Синтаксис

Предполагая, что блок вызывает исключение, метод перехватывает исключение, используя комбинацию ключевых слов try и catch. Вокруг кода помещается блок try / catch, который может генерировать исключение. Код в блоке try / catch называется защищенным кодом, и синтаксис использования try / catch выглядит следующим образом:

try {
   // statements causing exception
} catch( ExceptionName e1 ) {
   // error handling code
} catch( ExceptionName e2 ) {
   // error handling code
} catch( ExceptionName eN ) {
   // error handling code
} finally {
   // statements to be executed
}

Вы можете перечислить несколько операторов catch для перехвата различных типов исключений в случае, если ваш блок try вызывает более одного исключения в разных ситуациях.

Классы исключений в C #

Исключения в C # представлены классами. Классы исключений в C # в основном прямо или косвенно получены из класса System.Exception . Некоторыми из классов исключений, полученных из класса System.Exception, являются классы System.ApplicationException и System.SystemException .

Класс System.ApplicationException поддерживает исключения, генерируемые прикладными программами. Следовательно, исключения, определенные программистами, должны быть производными от этого класса.

Класс System.SystemException является базовым классом для всех предопределенных системных исключений.

В следующей таблице представлены некоторые предопределенные классы исключений, полученные из класса Sytem.SystemException.

Sr.No. Исключительный класс и описание
1

System.IO.IOException

Обрабатывает ошибки ввода / вывода.

2

System.IndexOutOfRangeException

Обрабатывает ошибки, сгенерированные, когда метод ссылается на индекс массива вне диапазона.

3

System.ArrayTypeMismatchException

Обрабатывает ошибки, возникающие, когда тип не соответствует типу массива.

4

System.NullReferenceException

Обрабатывает ошибки, возникающие при обращении к нулевому объекту.

5

System.DivideByZeroException

Обрабатывает ошибки, возникающие при делении дивиденда на ноль.

6

System.InvalidCastException

Обрабатывает ошибки, сгенерированные во время приведения типов.

7

System.OutOfMemoryException

Обрабатывает ошибки, возникающие из-за недостатка свободной памяти.

8

System.StackOverflowException

Обрабатывает ошибки, вызванные переполнением стека.

System.IO.IOException

Обрабатывает ошибки ввода / вывода.

System.IndexOutOfRangeException

Обрабатывает ошибки, сгенерированные, когда метод ссылается на индекс массива вне диапазона.

System.ArrayTypeMismatchException

Обрабатывает ошибки, возникающие, когда тип не соответствует типу массива.

System.NullReferenceException

Обрабатывает ошибки, возникающие при обращении к нулевому объекту.

System.DivideByZeroException

Обрабатывает ошибки, возникающие при делении дивиденда на ноль.

System.InvalidCastException

Обрабатывает ошибки, сгенерированные во время приведения типов.

System.OutOfMemoryException

Обрабатывает ошибки, возникающие из-за недостатка свободной памяти.

System.StackOverflowException

Обрабатывает ошибки, вызванные переполнением стека.

Обработка исключений

C # предоставляет структурированное решение для обработки исключений в форме блоков try и catch. Используя эти блоки, основные программные операторы отделены от операторов обработки ошибок.

Эти блоки обработки ошибок реализованы с использованием ключевых слов try , catch и finally . Ниже приведен пример создания исключения при делении на ноль:

using System;

namespace ErrorHandlingApplication {

   class DivNumbers {
      int result;
      
      DivNumbers() {
         result = 0;
      }
      
      public void division(int num1, int num2) {
         try {
            result = num1 / num2;
         } catch (DivideByZeroException e) {
            Console.WriteLine("Exception caught: {0}", e);
         } finally {
            Console.WriteLine("Result: {0}", result);
         }
      }
      
      static void Main(string[] args) {
         DivNumbers d = new DivNumbers();
         d.division(25, 0);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Exception caught: System.DivideByZeroException: Attempted to divide by zero. 
at ...
Result: 0

Создание пользовательских исключений

Вы также можете определить свое собственное исключение. Определяемые пользователем классы исключений являются производными от класса Exception . Следующий пример демонстрирует это —

using System;

namespace UserDefinedException {

   class TestTemperature {
   
      static void Main(string[] args) {
         Temperature temp = new Temperature();
         try {
            temp.showTemp();
         } catch(TempIsZeroException e) {
            Console.WriteLine("TempIsZeroException: {0}", e.Message);
         }
         Console.ReadKey();
      }
   }
}

public class TempIsZeroException: Exception {

   public TempIsZeroException(string message): base(message) {
   
   }
}

public class Temperature {
   int temperature = 0;
   
   public void showTemp() {
      
      if(temperature == 0) {
         throw (new TempIsZeroException("Zero Temperature found"));
      } else {
         Console.WriteLine("Temperature: {0}", temperature);
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

TempIsZeroException: Zero Temperature found

Бросать предметы

Вы можете выбросить объект, если он прямо или косвенно является производным от класса System.Exception . Вы можете использовать оператор throw в блоке catch, чтобы выбросить текущий объект как —

Catch(Exception e) {
   ...
   Throw e
}

C # — File I / O

Файл — это набор данных, хранящихся на диске с определенным именем и путем к каталогу. Когда файл открывается для чтения или записи, он становится потоком .

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

C # I / O Classes

Пространство имен System.IO имеет различные классы, которые используются для выполнения многочисленных операций с файлами, таких как создание и удаление файлов, чтение или запись в файл, закрытие файла и т. Д.

В следующей таблице показаны некоторые часто используемые неабстрактные классы в пространстве имен System.IO.

Sr.No. Класс ввода / вывода и описание
1

BinaryReader

Читает примитивные данные из двоичного потока.

2

BinaryWriter

Записывает примитивные данные в двоичном формате.

3

BufferedStream

Временное хранилище для потока байтов.

4

каталог

Помогает в управлении структурой каталогов.

5

DirectoryInfo

Используется для выполнения операций над каталогами.

6

DriveInfo

Предоставляет информацию для дисков.

7

файл

Помогает в манипулировании файлами.

8

FileInfo

Используется для выполнения операций над файлами.

9

FileStream

Используется для чтения и записи в любом месте файла.

10

MemoryStream

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

11

Дорожка

Выполняет операции с информацией о пути.

12

StreamReader

Используется для чтения символов из потока байтов.

13

StreamWriter

Используется для записи символов в поток.

14

StringReader

Используется для чтения из строкового буфера.

15

StringWriter

Используется для записи в строковый буфер.

BinaryReader

Читает примитивные данные из двоичного потока.

BinaryWriter

Записывает примитивные данные в двоичном формате.

BufferedStream

Временное хранилище для потока байтов.

каталог

Помогает в управлении структурой каталогов.

DirectoryInfo

Используется для выполнения операций над каталогами.

DriveInfo

Предоставляет информацию для дисков.

файл

Помогает в манипулировании файлами.

FileInfo

Используется для выполнения операций над файлами.

FileStream

Используется для чтения и записи в любом месте файла.

MemoryStream

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

Дорожка

Выполняет операции с информацией о пути.

StreamReader

Используется для чтения символов из потока байтов.

StreamWriter

Используется для записи символов в поток.

StringReader

Используется для чтения из строкового буфера.

StringWriter

Используется для записи в строковый буфер.

Класс FileStream

Класс FileStream в пространстве имен System.IO помогает в чтении, записи и закрытии файлов. Этот класс является производным от абстрактного класса Stream.

Вам необходимо создать объект FileStream, чтобы создать новый файл или открыть существующий файл. Синтаксис для создания объекта FileStream следующий:

FileStream <object_name> = new FileStream( <file_name>, <FileMode Enumerator>,
   <FileAccess Enumerator>, <FileShare Enumerator>);

Например, мы создаем объект FileStream F для чтения файла с именем sample.txt, как показано ниже:

FileStream F = new FileStream("sample.txt", FileMode.Open, FileAccess.Read,
   FileShare.Read);
Sr.No. Параметр и описание
1

FileMode

Перечислитель FileMode определяет различные способы открытия файлов. Членами перечислителя FileMode являются:

  • Добавить — открывает существующий файл и помещает курсор в конец файла, либо создает файл, если файл не существует.

  • Создать — создает новый файл.

  • CreateNew — указывает операционной системе, что он должен создать новый файл.

  • Открыть — открывает существующий файл.

  • OpenOrCreate — Он указывает операционной системе, что он должен открыть файл, если он существует, в противном случае он должен создать новый файл.

  • Обрезать — открывает существующий файл и усекает его размер до нуля байтов.

2

FileAccess

Перечислители FileAccess имеют следующие члены: Read , ReadWrite и Write .

3

Обменник

Перечислители FileShare имеют следующих членов —

  • Inheritable — позволяет дескриптору файла передавать наследование дочерним процессам.

  • Нет — отказывается от обмена текущим файлом

  • Чтение — позволяет открыть файл для чтения.

  • ReadWrite — позволяет открыть файл для чтения и записи.

  • Запись — позволяет открыть файл для записи

FileMode

Перечислитель FileMode определяет различные способы открытия файлов. Членами перечислителя FileMode являются:

Добавить — открывает существующий файл и помещает курсор в конец файла, либо создает файл, если файл не существует.

Создать — создает новый файл.

CreateNew — указывает операционной системе, что он должен создать новый файл.

Открыть — открывает существующий файл.

OpenOrCreate — Он указывает операционной системе, что он должен открыть файл, если он существует, в противном случае он должен создать новый файл.

Обрезать — открывает существующий файл и усекает его размер до нуля байтов.

FileAccess

Перечислители FileAccess имеют следующие члены: Read , ReadWrite и Write .

Обменник

Перечислители FileShare имеют следующих членов —

Inheritable — позволяет дескриптору файла передавать наследование дочерним процессам.

Нет — отказывается от обмена текущим файлом

Чтение — позволяет открыть файл для чтения.

ReadWrite — позволяет открыть файл для чтения и записи.

Запись — позволяет открыть файл для записи

пример

Следующая программа демонстрирует использование класса FileStream

using System;
using System.IO;

namespace FileIOApplication {
   
   class Program {
      
      static void Main(string[] args) {
         FileStream F = new FileStream("test.dat", FileMode.OpenOrCreate, 
            FileAccess.ReadWrite);
         
         for (int i = 1; i <= 20; i++) {
            F.WriteByte((byte)i);
         }
         
         F.Position = 0;
         for (int i = 0; i <= 20; i++) {
            Console.Write(F.ReadByte() + " ");
         }
         F.Close();
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 -1

Расширенные операции с файлами в C #

В предыдущем примере представлены простые файловые операции в C #. Однако, чтобы использовать огромные возможности классов C # System.IO, вам необходимо знать обычно используемые свойства и методы этих классов.

Sr.No. Тема и описание
1 Чтение и запись в текстовые файлы

Это включает чтение и запись в текстовые файлы. Класс StreamReader и StreamWriter помогают достичь этого.

2 Чтение и запись в двоичные файлы

Это включает чтение и запись в двоичные файлы. Класс BinaryReader и BinaryWriter помогает достичь этого.

3 Управление файловой системой Windows

Это дает программисту C # возможность просматривать и находить файлы и каталоги Windows.

Это включает чтение и запись в текстовые файлы. Класс StreamReader и StreamWriter помогают достичь этого.

Это включает чтение и запись в двоичные файлы. Класс BinaryReader и BinaryWriter помогает достичь этого.

Это дает программисту C # возможность просматривать и находить файлы и каталоги Windows.

C # — Атрибуты

Атрибут — это декларативный тег, который используется для передачи во время выполнения информации о поведении различных элементов, таких как классы, методы, структуры, перечислители, сборки и т. Д. В вашей программе. Вы можете добавить декларативную информацию в программу, используя атрибут. Декларативный тег обозначается квадратными ([]) скобками, помещенными над элементом, для которого он используется.

Атрибуты используются для добавления метаданных, таких как инструкции компилятора, и другой информации, такой как комментарии, описание, методы и классы, в программу. .Net Framework предоставляет два типа атрибутов: предопределенные атрибуты и настраиваемые атрибуты.

Указание атрибута

Синтаксис для указания атрибута следующий:

[attribute(positional_parameters, name_parameter = value, ...)]
element

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

Предопределенные атрибуты

.Net Framework предоставляет три предопределенных атрибута —

  • AttributeUsage
  • условный
  • устарелый

AttributeUsage

Предопределенный атрибут AttributeUsage описывает, как можно использовать пользовательский класс атрибута. Он указывает типы элементов, к которым может быть применен атрибут.

Синтаксис для указания этого атрибута следующий:

[AttributeUsage (
   validon,
   AllowMultiple = allowmultiple,
   Inherited = inherited
)]

Куда,

  • Параметр validon указывает элементы языка, на которых можно разместить атрибут. Это комбинация значения перечислителя AttributeTargets . Значением по умолчанию является AttributeTargets.All .

  • Параметр allowmultiple (необязательный) предоставляет значение для свойства AllowMultiple этого атрибута, логическое значение. Если это правда, атрибут является multiuse. По умолчанию используется значение false (одноразовое использование).

  • Унаследованный параметр (необязательный) предоставляет значение для свойства Inherited этого атрибута, логическое значение. Если это правда, атрибут наследуется производными классами. Значением по умолчанию является false (не наследуется).

Параметр validon указывает элементы языка, на которых можно разместить атрибут. Это комбинация значения перечислителя AttributeTargets . Значением по умолчанию является AttributeTargets.All .

Параметр allowmultiple (необязательный) предоставляет значение для свойства AllowMultiple этого атрибута, логическое значение. Если это правда, атрибут является multiuse. По умолчанию используется значение false (одноразовое использование).

Унаследованный параметр (необязательный) предоставляет значение для свойства Inherited этого атрибута, логическое значение. Если это правда, атрибут наследуется производными классами. Значением по умолчанию является false (не наследуется).

Например,

[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property, 
AllowMultiple = true)]

условный

Этот предопределенный атрибут отмечает условный метод, выполнение которого зависит от указанного идентификатора предварительной обработки.

Это вызывает условную компиляцию вызовов методов, в зависимости от указанного значения, такого как Debug или Trace . Например, он отображает значения переменных при отладке кода.

Синтаксис для указания этого атрибута следующий:

[Conditional(
   conditionalSymbol
)]

Например,

[Conditional("DEBUG")]

В следующем примере демонстрируется атрибут —

#define DEBUG
using System;
using System.Diagnostics;

public class Myclass {
   [Conditional("DEBUG")]
   
   public static void Message(string msg) {
      Console.WriteLine(msg);
   }
}

class Test {
   static void function1() {
      Myclass.Message("In Function 1.");
      function2();
   }
   
   static void function2() {
      Myclass.Message("In Function 2.");
   }
   
   public static void Main() {
      Myclass.Message("In Main function.");
      function1();
      Console.ReadKey();
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

In Main function
In Function 1
In Function 2

устарелый

Этот предопределенный атрибут отмечает программный объект, который не должен использоваться. Это позволяет вам сообщить компилятору об отмене определенного целевого элемента. Например, когда в классе используется новый метод, и если вы все еще хотите сохранить старый метод в классе, вы можете пометить его как устаревший, отобразив сообщение, что следует использовать новый метод вместо старого.

Синтаксис для указания этого атрибута следующий:

[Obsolete (
   message
)]

[Obsolete (
   message,
   iserror
)]

Куда,

  • Сообщение параметра — это строка, описывающая причину, по которой элемент устарел, и что вместо этого использовать.

  • Параметр iserror , является логическим значением. Если его значение равно true, компилятор должен рассматривать использование элемента как ошибку. Значением по умолчанию является false (компилятор выдает предупреждение).

Сообщение параметра — это строка, описывающая причину, по которой элемент устарел, и что вместо этого использовать.

Параметр iserror , является логическим значением. Если его значение равно true, компилятор должен рассматривать использование элемента как ошибку. Значением по умолчанию является false (компилятор выдает предупреждение).

Следующая программа демонстрирует это —

using System;

public class MyClass {
   [Obsolete("Don't use OldMethod, use NewMethod instead", true)]
   
   static void OldMethod() {
      Console.WriteLine("It is the old method");
   }
   
   static void NewMethod() {
      Console.WriteLine("It is the new method"); 
   }
   
   public static void Main() {
      OldMethod();
   }
}

Когда вы пытаетесь скомпилировать программу, компилятор выдает сообщение об ошибке:

 Don't use OldMethod, use NewMethod instead

Создание пользовательских атрибутов

.Net Framework позволяет создавать пользовательские атрибуты, которые могут использоваться для хранения декларативной информации и могут быть получены во время выполнения. Эта информация может быть связана с любым целевым элементом в зависимости от критериев проектирования и потребностей приложения.

Создание и использование пользовательских атрибутов включает четыре шага:

  • Объявление пользовательского атрибута
  • Построение пользовательского атрибута
  • Примените пользовательский атрибут к целевому элементу программы
  • Доступ к атрибутам через отражение

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

Объявление пользовательского атрибута

Новый пользовательский атрибут должен быть производным от класса System.Attribute . Например,

//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]

public class DeBugInfo : System.Attribute

В предыдущем коде мы объявили пользовательский атрибут с именем DeBugInfo .

Построение пользовательского атрибута

Давайте создадим пользовательский атрибут с именем DeBugInfo , который хранит информацию, полученную в результате отладки любой программы. Пусть он хранит следующую информацию —

  • Кодовый номер для ошибки
  • Имя разработчика, который выявил ошибку
  • Дата последнего просмотра кода
  • Строковое сообщение для хранения замечаний разработчика

Класс DeBugInfo имеет три частных свойства для хранения первых трех сведений и открытое свойство для хранения сообщения. Следовательно, номер ошибки, имя разработчика и дата проверки являются позиционными параметрами класса DeBugInfo, а сообщение является необязательным или именованным параметром.

Каждый атрибут должен иметь хотя бы один конструктор. Позиционные параметры должны быть переданы через конструктор. Следующий код показывает класс DeBugInfo

//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]

public class DeBugInfo : System.Attribute {
   private int bugNo;
   private string developer;
   private string lastReview;
   public string message;
   
   public DeBugInfo(int bg, string dev, string d) {
      this.bugNo = bg;
      this.developer = dev;
      this.lastReview = d;
   }

   public int BugNo {
      get {
         return bugNo;
      }
   }
   
   public string Developer {
      get {
         return developer;
      }
   }
   
   public string LastReview {
      get {
         return lastReview;
      }
   }
   
   public string Message {
      get {
         return message;
      }
      set {
         message = value;
      }
   }
}

Применение пользовательского атрибута

Атрибут применяется, помещая его непосредственно перед его целью —

[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle {
   //member variables
   protected double length;
   protected double width;
   public Rectangle(double l, double w) {
      length = l;
      width = w;
   }
   [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
   
   public double GetArea() {
      return length * width;
   }
   [DeBugInfo(56, "Zara Ali", "19/10/2012")]
   
   public void Display() {
      Console.WriteLine("Length: {0}", length);
      Console.WriteLine("Width: {0}", width);
      Console.WriteLine("Area: {0}", GetArea());
   }
}

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

C # — Отражение

Объекты отражения используются для получения информации о типе во время выполнения. Классы, предоставляющие доступ к метаданным работающей программы, находятся в пространстве имен System.Reflection .

Пространство имен System.Reflection содержит классы, которые позволяют получать информацию о приложении и динамически добавлять типы, значения и объекты в приложение.

Приложения отражения

Отражение имеет следующие приложения —

  • Это позволяет просматривать информацию об атрибутах во время выполнения.

  • Это позволяет исследовать различные типы в сборке и создавать экземпляры этих типов.

  • Это позволяет позднее связывание с методами и свойствами

  • Это позволяет создавать новые типы во время выполнения, а затем выполняет некоторые задачи, используя эти типы.

Это позволяет просматривать информацию об атрибутах во время выполнения.

Это позволяет исследовать различные типы в сборке и создавать экземпляры этих типов.

Это позволяет позднее связывание с методами и свойствами

Это позволяет создавать новые типы во время выполнения, а затем выполняет некоторые задачи, используя эти типы.

Просмотр метаданных

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

Объект MemberInfo класса System.Reflection должен быть инициализирован для обнаружения атрибутов, связанных с классом. Для этого вы определяете объект целевого класса, как —

System.Reflection.MemberInfo info = typeof(MyClass);

Следующая программа демонстрирует это —

using System;

[AttributeUsage(AttributeTargets.All)]
public class HelpAttribute : System.Attribute {
   public readonly string Url;
   
   public string Topic   // Topic is a named parameter {
      get {
         return topic;
      }
      
      set {
         topic = value;
      }
   }
   
   public HelpAttribute(string url)   // url is a positional parameter {
      this.Url = url;
   }
   private string topic;
}

[HelpAttribute("Information on the class MyClass")]
class MyClass {

}

namespace AttributeAppl {

   class Program {
   
      static void Main(string[] args) {
         System.Reflection.MemberInfo info = typeof(MyClass);
         object[] attributes = info.GetCustomAttributes(true);
         for (int i = 0; i < attributes.Length; i++) {
            System.Console.WriteLine(attributes[i]);
         }
         Console.ReadKey();
      }
   }
}

Когда он скомпилирован и запущен, он отображает имя пользовательских атрибутов, прикрепленных к классу MyClass

HelpAttribute

пример

В этом примере мы используем атрибут DeBugInfo, созданный в предыдущей главе, и используем отражение для чтения метаданных в классе Rectangle .

using System;
using System.Reflection;

namespace BugFixApplication {
   //a custom attribute BugFix to be
   //assigned to a class and its members
   [AttributeUsage(AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]

   public class DeBugInfo : System.Attribute {
      private int bugNo;
      private string developer;
      private string lastReview;
      public string message;
      
      public DeBugInfo(int bg, string dev, string d) {
         this.bugNo = bg;
         this.developer = dev;
         this.lastReview = d;
      }
      
      public int BugNo {
         get {
            return bugNo;
         }
      }
      
      public string Developer {
         get {
            return developer;
         }
      }
      
      public string LastReview {
         get {
            return lastReview;
         }
      }
      
      public string Message {
         get {
            return message;
         }
         set {
            message = value;
         }
      }
   }
   [DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
   [DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
   
   class Rectangle {
      //member variables
      protected double length;
      protected double width;
      public Rectangle(double l, double w) {
         length = l;
         width = w;
      }
      
      [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
      public double GetArea() {
         return length * width;
      }
      
      [DeBugInfo(56, "Zara Ali", "19/10/2012")]
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle
   
   class ExecuteRectangle {
      static void Main(string[] args) {
         Rectangle r = new Rectangle(4.5, 7.5);
         r.Display();
         Type type = typeof(Rectangle);
         
         //iterating through the attribtues of the Rectangle class
         foreach (Object attributes in type.GetCustomAttributes(false)) {
            DeBugInfo dbi = (DeBugInfo)attributes;
            
            if (null != dbi) {
               Console.WriteLine("Bug no: {0}", dbi.BugNo);
               Console.WriteLine("Developer: {0}", dbi.Developer);
               Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
               Console.WriteLine("Remarks: {0}", dbi.Message);
            }
         }

         //iterating through the method attribtues
         foreach (MethodInfo m in type.GetMethods()) {
            
            foreach (Attribute a in m.GetCustomAttributes(true)) {
               DeBugInfo dbi = (DeBugInfo)a;
               
               if (null != dbi) {
                  Console.WriteLine("Bug no: {0}, for Method: {1}", dbi.BugNo, m.Name);
                  Console.WriteLine("Developer: {0}", dbi.Developer);
                  Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
                  Console.WriteLine("Remarks: {0}", dbi.Message);
               }
            }
         }
         Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Length: 4.5
Width: 7.5
Area: 33.75
Bug No: 49
Developer: Nuha Ali
Last Reviewed: 10/10/2012
Remarks: Unused variable
Bug No: 45
Developer: Zara Ali
Last Reviewed: 12/8/2012
Remarks: Return type mismatch
Bug No: 55, for Method: GetArea
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks: Return type mismatch
Bug No: 56, for Method: Display
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks: 

C # — Свойства

Свойства являются именованными членами классов, структур и интерфейсов. Переменные или методы-члены в классе или структурах называются полями . Свойства являются расширением полей и доступны с использованием того же синтаксиса. Они используют методы доступа, с помощью которых можно читать, записывать или манипулировать значениями приватных полей.

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

Например, у нас есть класс с именем Student, с закрытыми полями для возраста, имени и кода. Мы не можем напрямую получить доступ к этим полям за пределами области действия класса, но у нас могут быть свойства для доступа к этим частным полям.

Accessors

Метод доступа к свойству содержит исполняемые операторы, которые помогают в получении (чтении или вычислении) или установке (записи) свойства. Декларации доступа могут содержать метод доступа get, набор доступа set или оба. Например —

// Declare a Code property of type string:
public string Code {
   get {
      return code;
   }
   set {
      code = value;
   }
}

// Declare a Name property of type string:
public string Name {
   get {
      return name;
   }
   set {
      name = value;
   }
}

// Declare a Age property of type int:
public int Age { 
   get {
      return age;
   }
   set {
      age = value;
   }
}

пример

Следующий пример демонстрирует использование свойств —

using System;
namespace tutorialspoint {
   class Student {
      private string code = "N.A";
      private string name = "not known";
      private int age = 0;
      
      // Declare a Code property of type string:
      public string Code {
         get {
            return code;
         }
         set {
            code = value;
         }
      }
      
      // Declare a Name property of type string:
      public string Name {
         get {
            return name;
         }
         set {
            name = value;
         }
      }
      
      // Declare a Age property of type int:
      public int Age {
         get {
            return age;
         }
         set {
            age = value;
         }
      }
      public override string ToString() {
         return "Code = " + Code +", Name = " + Name + ", Age = " + Age;
      }
   }
   
   class ExampleDemo {
      public static void Main() {
      
         // Create a new Student object:
         Student s = new Student();
         
         // Setting code, name and the age of the student
         s.Code = "001";
         s.Name = "Zara";
         s.Age = 9;
         Console.WriteLine("Student Info: {0}", s);
         
         //let us increase age
         s.Age += 1;
         Console.WriteLine("Student Info: {0}", s);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Student Info: Code = 001, Name = Zara, Age = 9
Student Info: Code = 001, Name = Zara, Age = 10

Абстрактные свойства

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

using System;
namespace tutorialspoint {
   public abstract class Person {
      public abstract string Name {
         get;
         set;
      }
      public abstract int Age {
         get;
         set;
      }
   }
   
   class Student : Person {
   
      private string code = "N.A";
      private string name = "N.A";
      private int age = 0;
      
      // Declare a Code property of type string:
      public string Code {
         get {
            return code;
         }
         set {
            code = value;
         }
      }
      
      // Declare a Name property of type string:
      public override string Name {
         get {
            return name;
         }
         set {
            name = value;
         }
      }
      
      // Declare a Age property of type int:
      public override int Age {
         get {
            return age;
         }
         set {
            age = value;
         }
      }
      public override string ToString() {
         return "Code = " + Code +", Name = " + Name + ", Age = " + Age;
      }
   }
   
   class ExampleDemo {
      public static void Main() {
         // Create a new Student object:
         Student s = new Student();
         
         // Setting code, name and the age of the student
         s.Code = "001";
         s.Name = "Zara";
         s.Age = 9;
         Console.WriteLine("Student Info:- {0}", s);
         
         //let us increase age
         s.Age += 1;
         Console.WriteLine("Student Info:- {0}", s);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Student Info: Code = 001, Name = Zara, Age = 9
Student Info: Code = 001, Name = Zara, Age = 10

C # — Индексаторы

Индексатор позволяет индексировать объект, например, массив. Когда вы определяете индексатор для класса, этот класс ведет себя подобно виртуальному массиву . Затем вы можете получить доступ к экземпляру этого класса, используя оператор доступа к массиву ([]).

Синтаксис

Одномерный индексатор имеет следующий синтаксис —

element-type this[int index] {

   // The get accessor.
   get {
      // return the value specified by index
   }
   
   // The set accessor.
   set {
      // set the value specified by index
   }
}

Использование индексаторов

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

Определение свойства включает в себя предоставление имени свойства. Индексаторы определяются не с именами, а с ключевым словом this , которое ссылается на экземпляр объекта. Следующий пример демонстрирует концепцию —

using System;

namespace IndexerApplication {
   
   class IndexedNames {
      private string[] namelist = new string[size];
      static public int size = 10;
      
      public IndexedNames() {
         for (int i = 0; i < size; i++)
         namelist[i] = "N. A.";
      }
      
      public string this[int index] {
      
         get {
            string tmp;
         
            if( index >= 0 && index <= size-1 ) {
               tmp = namelist[index];
            } else {
               tmp = "";
            }
            
            return ( tmp );
         }
         set {
            if( index >= 0 && index <= size-1 ) {
               namelist[index] = value;
            }
         }
      }
      
      static void Main(string[] args) {
         IndexedNames names = new IndexedNames();
         names[0] = "Zara";
         names[1] = "Riz";
         names[2] = "Nuha";
         names[3] = "Asif";
         names[4] = "Davinder";
         names[5] = "Sunil";
         names[6] = "Rubic";
         
         for ( int i = 0; i < IndexedNames.size; i++ ) {
            Console.WriteLine(names[i]);
         }
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Zara
Riz
Nuha
Asif
Davinder
Sunil
Rubic
N. A.
N. A.
N. A.

Перегруженные индексаторы

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

В следующем примере демонстрируются перегруженные индексаторы —

using System;

namespace IndexerApplication {

   class IndexedNames {
      private string[] namelist = new string[size];
      static public int size = 10;
      
      public IndexedNames() {
         for (int i = 0; i < size; i++) {
            namelist[i] = "N. A.";
         }
      }
      
      public string this[int index] {
         
         get {
            string tmp;
            
            if( index >= 0 && index <= size-1 ) {
               tmp = namelist[index];
            } else {
               tmp = "";
            }
            
            return ( tmp );
         }
         set {
            if( index >= 0 && index <= size-1 ) {
               namelist[index] = value;
            }
         }
      }
      
      public int this[string name] {
         
         get {
            int index = 0;
            
            while(index < size) {
               if (namelist[index] == name) {
                return index;
               }
               index++;
            }
            return index;
         }

      }

      static void Main(string[] args) {
         IndexedNames names = new IndexedNames();
         names[0] = "Zara";
         names[1] = "Riz";
         names[2] = "Nuha";
         names[3] = "Asif";
         names[4] = "Davinder";
         names[5] = "Sunil";
         names[6] = "Rubic";
         
         //using the first indexer with int parameter
         for (int i = 0; i < IndexedNames.size; i++) {
            Console.WriteLine(names[i]);
         }
         
         //using the second indexer with the string parameter
         Console.WriteLine(names["Nuha"]);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Zara
Riz
Nuha
Asif
Davinder
Sunil
Rubic
N. A.
N. A.
N. A.
2

C # — делегаты

Делегаты C # аналогичны указателям на функции в C или C ++. Делегат — это переменная ссылочного типа, которая содержит ссылку на метод. Ссылка может быть изменена во время выполнения.

Делегаты особенно используются для реализации событий и методов обратного вызова. Все делегаты неявно являются производными от класса System.Delegate .

Объявление делегатов

Объявление делегата определяет методы, на которые может ссылаться делегат. Делегат может ссылаться на метод, который имеет ту же подпись, что и подпись делегата.

Например, рассмотрим делегата —

public delegate int MyDelegate (string s);

Предыдущий делегат может использоваться для ссылки на любой метод, который имеет единственный строковый параметр и возвращает переменную типа int .

Синтаксис для объявления делегата —

delegate <return type> <delegate-name> <parameter list>

Выездные делегаты

После того, как тип делегата объявлен, объект делегата должен быть создан с новым ключевым словом и связан с определенным методом. При создании делегата аргумент, передаваемый новому выражению, записывается аналогично вызову метода, но без аргументов метода. Например —

public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);

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

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl {
   
   class TestDelegate {
      static int num = 10;
      
      public static int AddNum(int p) {
         num += p;
         return num;
      }

      public static int MultNum(int q) {
         num *= q;
         return num;
      }
      
      public static int getNum() {
         return num;
      }

      static void Main(string[] args) {
         //create delegate instances
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         
         //calling the methods using the delegate objects
         nc1(25);
         Console.WriteLine("Value of Num: {0}", getNum());
         nc2(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Value of Num: 35
Value of Num: 175

Многоадресная рассылка делегата

Делегировать объекты можно с помощью оператора «+». Составной делегат вызывает двух делегатов, из которых он был составлен. Только делегаты одного типа могут быть составлены. Оператор «-» может использоваться для удаления делегата компонента из составного делегата.

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

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl {

   class TestDelegate {
      static int num = 10;
      
      public static int AddNum(int p) {
         num += p;
         return num;
      }

      public static int MultNum(int q) {
         num *= q;
         return num;
      }
      
      public static int getNum() {
         return num;
      }

      static void Main(string[] args) {
         //create delegate instances
         NumberChanger nc;
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         nc = nc1;
         nc += nc2;
         
         //calling multicast
         nc(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Value of Num: 75

Использование делегатов

В следующем примере демонстрируется использование делегата. Делегат printString может использоваться для ссылки на метод, который принимает строку в качестве входных данных и ничего не возвращает.

Мы используем этот делегат для вызова двух методов: первый выводит строку в консоль, а второй — в файл —

using System;
using System.IO;

namespace DelegateAppl {

   class PrintString {
      static FileStream fs;
      static StreamWriter sw;
      
      // delegate declaration
      public delegate void printString(string s);

      // this method prints to the console
      public static void WriteToScreen(string str) {
         Console.WriteLine("The String is: {0}", str);
      }
      
      //this method prints to a file
      public static void WriteToFile(string s) {
         fs = new FileStream("c:\\message.txt",
         FileMode.Append, FileAccess.Write);
         sw = new StreamWriter(fs);
         sw.WriteLine(s);
         sw.Flush();
         sw.Close();
         fs.Close();
      }
      
      // this method takes the delegate as parameter and uses it to
      // call the methods as required
      public static void sendString(printString ps) {
         ps("Hello World");
      }
      
      static void Main(string[] args) {
         printString ps1 = new printString(WriteToScreen);
         printString ps2 = new printString(WriteToFile);
         sendString(ps1);
         sendString(ps2);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

The String is: Hello World

C # — События

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

Использование делегатов с событиями

События объявляются и генерируются в классе и связываются с обработчиками событий с использованием делегатов в том же классе или каком-либо другом классе. Класс, содержащий событие, используется для публикации события. Это называется классом издателя . Другой класс, который принимает это событие, называется классом подписчика . События используют модель издатель-подписчик .

Издатель — это объект, который содержит определение события и делегата. Ассоциация события-делегата также определена в этом объекте. Объект класса издателя вызывает событие и уведомляется о других объектах.

Подписчик — это объект, который принимает событие и предоставляет обработчик события. Делегат в классе издателя вызывает метод (обработчик события) класса подписчика.

Объявление событий

Чтобы объявить событие внутри класса, сначала должен быть объявлен тип делегата для события. Например,

public delegate string MyDel(string str);

Далее само событие объявляется с использованием ключевого слова event

event MyDel MyEvent;

Предыдущий код определяет делегат с именем BoilerLogHandler и событие с именем BoilerEventLog , которое вызывает делегат при его возникновении.

пример

using System;

namespace SampleApp {
   public delegate string MyDel(string str);
	
   class EventProgram {
      event MyDel MyEvent;
		
      public EventProgram() {
         this.MyEvent += new MyDel(this.WelcomeUser);
      }
		
      public string WelcomeUser(string username) {
         return "Welcome " + username;
      }
		
      static void Main(string[] args) {
         EventProgram obj1 = new EventProgram();
         string result = obj1.MyEvent("Tutorials Point");
         Console.WriteLine(result);
      }

   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Welcome Tutorials Point

C # — Коллекции

Классы коллекций — это специализированные классы для хранения и поиска данных Эти классы обеспечивают поддержку стеков, очередей, списков и хеш-таблиц. Большинство классов коллекции реализуют одинаковые интерфейсы.

Классы коллекций служат различным целям, таким как динамическое выделение памяти для элементов и доступ к списку элементов на основе индекса и т. Д. Эти классы создают коллекции объектов класса Object, который является базовым классом для всех типов данных в C #.

Различные классы коллекций и их использование

Ниже приведены различные часто используемые классы пространства имен System.Collection . Нажмите на следующие ссылки, чтобы проверить их детали.

Sr.No. Класс и описание и использование
1 ArrayList

Он представляет упорядоченную коллекцию объекта, которая может быть проиндексирована индивидуально.

Это в основном альтернатива массиву. Однако, в отличие от массива, вы можете добавлять и удалять элементы из списка в указанной позиции, используя индекс, и размер массива автоматически изменяется. Это также позволяет динамическое выделение памяти, добавление, поиск и сортировку элементов в списке.

2 Хеш-таблица

Он использует ключ для доступа к элементам в коллекции.

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

3 SortedList

Он использует ключ и индекс для доступа к элементам в списке.

Сортированный список — это комбинация массива и хеш-таблицы. Он содержит список элементов, к которым можно получить доступ с помощью ключа или индекса. Если вы обращаетесь к элементам с помощью индекса, это ArrayList, а если вы получаете доступ к элементам с помощью ключа, это Hashtable. Коллекция предметов всегда сортируется по значению ключа.

4 стек

Он представляет коллекцию объектов « последний пришел — первый вышел» .

Он используется, когда вам нужен доступ «первым пришел — первым вышел». Когда вы добавляете элемент в список, это называется толканием элемента, а когда вы удаляете его, он называется выталкиванием элемента.

5 Очередь

Он представляет собой коллекцию объектов « первым пришел — первым вышел» .

Он используется, когда вам нужен доступ первым, первым и первым. Когда вы добавляете элемент в список, он называется enqueue, а когда вы удаляете элемент, он называется deque .

6 BitArray

Он представляет собой массив двоичного представления, используя значения 1 и 0.

Он используется, когда вам нужно сохранить биты, но заранее не знать их количество. Вы можете получить доступ к элементам из коллекции BitArray, используя целочисленный индекс , который начинается с нуля.

Он представляет упорядоченную коллекцию объекта, которая может быть проиндексирована индивидуально.

Это в основном альтернатива массиву. Однако, в отличие от массива, вы можете добавлять и удалять элементы из списка в указанной позиции, используя индекс, и размер массива автоматически изменяется. Это также позволяет динамическое выделение памяти, добавление, поиск и сортировку элементов в списке.

Он использует ключ для доступа к элементам в коллекции.

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

Он использует ключ и индекс для доступа к элементам в списке.

Сортированный список — это комбинация массива и хеш-таблицы. Он содержит список элементов, к которым можно получить доступ с помощью ключа или индекса. Если вы обращаетесь к элементам с помощью индекса, это ArrayList, а если вы получаете доступ к элементам с помощью ключа, это Hashtable. Коллекция предметов всегда сортируется по значению ключа.

Он представляет коллекцию объектов « последний пришел — первый вышел» .

Он используется, когда вам нужен доступ «первым пришел — первым вышел». Когда вы добавляете элемент в список, это называется толканием элемента, а когда вы удаляете его, он называется выталкиванием элемента.

Он представляет собой коллекцию объектов « первым пришел — первым вышел» .

Он используется, когда вам нужен доступ первым, первым и первым. Когда вы добавляете элемент в список, он называется enqueue, а когда вы удаляете элемент, он называется deque .

Он представляет собой массив двоичного представления, используя значения 1 и 0.

Он используется, когда вам нужно сохранить биты, но заранее не знать их количество. Вы можете получить доступ к элементам из коллекции BitArray, используя целочисленный индекс , который начинается с нуля.

C # — Generics

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

Вы пишете спецификации для класса или метода с параметрами замены для типов данных. Когда компилятор встречает конструктор для класса или вызов функции для метода, он генерирует код для обработки определенного типа данных. Простой пример поможет понять концепцию —

using System;
using System.Collections.Generic;

namespace GenericApplication {

   public class MyGenericArray<T> {
      private T[] array;
      
      public MyGenericArray(int size) {
         array = new T[size + 1];
      }
      
      public T getItem(int index) {
         return array[index];
      }
      
      public void setItem(int index, T value) {
         array[index] = value;
      }
   }
   
   class Tester {
      static void Main(string[] args) {
         
         //declaring an int array
         MyGenericArray<int> intArray = new MyGenericArray<int>(5);
         
         //setting values
         for (int c = 0; c < 5; c++) {
            intArray.setItem(c, c*5);
         }
         
         //retrieving the values
         for (int c = 0; c < 5; c++) {
            Console.Write(intArray.getItem(c) + " ");
         }
         
         Console.WriteLine();
         
         //declaring a character array
         MyGenericArray<char> charArray = new MyGenericArray<char>(5);
         
         //setting values
         for (int c = 0; c < 5; c++) {
            charArray.setItem(c, (char)(c+97));
         }
         
         //retrieving the values
         for (int c = 0; c< 5; c++) {
            Console.Write(charArray.getItem(c) + " ");
         }
         Console.WriteLine();
         
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

0 5 10 15 20
a b c d e

Особенности дженериков

Дженерики — это техника, которая обогащает ваши программы следующими способами:

  • Это помогает максимизировать повторное использование кода, безопасность типов и производительность.

  • Вы можете создавать общие классы коллекции. Библиотека классов .NET Framework содержит несколько новых универсальных классов коллекции в пространстве имен System.Collections.Generic . Вы можете использовать эти общие классы коллекции вместо классов коллекции в пространстве имен System.Collections .

  • Вы можете создавать свои собственные общие интерфейсы, классы, методы, события и делегаты.

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

  • Вы можете получить информацию о типах, используемых в универсальном типе данных во время выполнения, с помощью рефлексии.

Это помогает максимизировать повторное использование кода, безопасность типов и производительность.

Вы можете создавать общие классы коллекции. Библиотека классов .NET Framework содержит несколько новых универсальных классов коллекции в пространстве имен System.Collections.Generic . Вы можете использовать эти общие классы коллекции вместо классов коллекции в пространстве имен System.Collections .

Вы можете создавать свои собственные общие интерфейсы, классы, методы, события и делегаты.

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

Вы можете получить информацию о типах, используемых в универсальном типе данных во время выполнения, с помощью рефлексии.

Общие методы

В предыдущем примере мы использовали универсальный класс; мы можем объявить универсальный метод с параметром типа. Следующая программа иллюстрирует концепцию —

using System;
using System.Collections.Generic;

namespace GenericMethodAppl {
   
   class Program {
      
      static void Swap<T>(ref T lhs, ref T rhs) {
         T temp;
         temp = lhs;
         lhs = rhs;
         rhs = temp;
      }
      
      static void Main(string[] args) {
         int a, b;
         char c, d;
         a = 10;
         b = 20;
         c = 'I';
         d = 'V';
         
         //display values before swap:
         Console.WriteLine("Int values before calling swap:");
         Console.WriteLine("a = {0}, b = {1}", a, b);
         Console.WriteLine("Char values before calling swap:");
         Console.WriteLine("c = {0}, d = {1}", c, d);
         
         //call swap
         Swap<int>(ref a, ref b);
         Swap<char>(ref c, ref d);
         
         //display values after swap:
         Console.WriteLine("Int values after calling swap:");
         Console.WriteLine("a = {0}, b = {1}", a, b);
         Console.WriteLine("Char values after calling swap:");
         Console.WriteLine("c = {0}, d = {1}", c, d);
         
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Int values before calling swap:
a = 10, b = 20
Char values before calling swap:
c = I, d = V
Int values after calling swap:
a = 20, b = 10
Char values after calling swap:
c = V, d = I

Общие делегаты

Вы можете определить универсальный делегат с параметрами типа. Например —

delegate T NumberChanger<T>(T n);

В следующем примере показано использование этого делегата —

using System;
using System.Collections.Generic;

delegate T NumberChanger<T>(T n);
namespace GenericDelegateAppl {
   
   class TestDelegate {
      static int num = 10;
      
      public static int AddNum(int p) {
         num += p;
         return num;
      }
      
      public static int MultNum(int q) {
         num *= q;
         return num;
      }
      
      public static int getNum() {
         return num;
      }
      
      static void Main(string[] args) {
         //create delegate instances
         NumberChanger<int> nc1 = new NumberChanger<int>(AddNum);
         NumberChanger<int> nc2 = new NumberChanger<int>(MultNum);
         
         //calling the methods using the delegate objects
         nc1(25);
         Console.WriteLine("Value of Num: {0}", getNum());
         nc2(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Value of Num: 35
Value of Num: 175

C # — анонимные методы

Мы обсуждали, что делегаты используются для ссылки на любые методы, которые имеют ту же сигнатуру, что и подпись делегата. Другими словами, вы можете вызвать метод, на который может ссылаться делегат, используя этот объект делегата.

Анонимные методы предоставляют технику для передачи блока кода в качестве параметра делегата. Анонимные методы — это методы без имени, просто тело.

Вам не нужно указывать тип возврата в анонимном методе; оно выводится из оператора return внутри тела метода.

Написание анонимного метода

Анонимные методы объявляются при создании экземпляра делегата с ключевым словом делегата . Например,

delegate void NumberChanger(int n);
...
NumberChanger nc = delegate(int x) {
   Console.WriteLine("Anonymous Method: {0}", x);
};

Блок кода Console.WriteLine («Анонимный метод: {0}», x); это тело анонимного метода.

Делегат может быть вызван как с анонимными методами, так и с именованными методами одинаково, то есть путем передачи параметров метода объекту делегата.

Например,

nc(10);

пример

Следующий пример демонстрирует концепцию —

using System;

delegate void NumberChanger(int n);
namespace DelegateAppl {
   
   class TestDelegate {
      static int num = 10;
      
      public static void AddNum(int p) {
         num += p;
         Console.WriteLine("Named Method: {0}", num);
      }
      
      public static void MultNum(int q) {
         num *= q;
         Console.WriteLine("Named Method: {0}", num);
      }
      
      public static int getNum() {
         return num;
      }
      
      static void Main(string[] args) {
         //create delegate instances using anonymous method
         NumberChanger nc = delegate(int x) {
            Console.WriteLine("Anonymous Method: {0}", x);
         };
         
         //calling the delegate using the anonymous method 
         nc(10);
         
         //instantiating the delegate using the named methods 
         nc =  new NumberChanger(AddNum);
         
         //calling the delegate using the named methods 
         nc(5);
         
         //instantiating the delegate using another named methods 
         nc =  new NumberChanger(MultNum);
         
         //calling the delegate using the named methods 
         nc(2);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Anonymous Method: 10
Named Method: 15
Named Method: 30

C # — Небезопасные коды

C # позволяет использовать переменные-указатели в функции блока кода, когда он отмечен модификатором unsafe . Небезопасный код или неуправляемый код — это блок кода, который использует переменную- указатель .

Примечание. Для выполнения программ, упомянутых в этой главе, на площадке кодирования установите параметр компиляции в « Проект»> «Параметры компиляции»> «Команда компиляции» на

mcs *.cs -out:main.exe -unsafe"

Примечание. Для выполнения программ, упомянутых в этой главе, на площадке кодирования установите параметр компиляции в « Проект»> «Параметры компиляции»> «Команда компиляции» на

mcs *.cs -out:main.exe -unsafe"

указатели

Указатель — это переменная, значением которой является адрес другой переменной, т. Е. Прямой адрес ячейки памяти. подобно любой переменной или константе, вы должны объявить указатель, прежде чем сможете использовать его для хранения любого адреса переменной.

Общая форма объявления указателя —

type *var-name;

Ниже приведены правильные объявления указателей —

int    *ip;    /* pointer to an integer */
double *dp;    /* pointer to a double */
float  *fp;    /* pointer to a float */
char   *ch     /* pointer to a character */

В следующем примере показано использование указателей в C # с использованием модификатора unsafe —

using System;

namespace UnsafeCodeApplication {
   
   class Program {
      
      static unsafe void Main(string[] args) {
         int var = 20;
         int* p = &var;
         Console.WriteLine("Data is: {0} ",  var);
         Console.WriteLine("Address is: {0}",  (int)p);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код был скомпилирован и выполнен, он дает следующий результат —

Data is: 20
Address is: 99215364

Вместо того, чтобы объявлять весь метод небезопасным, вы также можете объявить часть кода небезопасной. Пример в следующем разделе показывает это.

Получение значения данных с помощью указателя

Вы можете извлечь данные, хранящиеся в расположении, на которое ссылается переменная указателя, используя метод ToString () . Следующий пример демонстрирует это —

using System;

namespace UnsafeCodeApplication {
   
   class Program {
      
      public static void Main() {
         
         unsafe {
            int var = 20;
            int* p = &var;
            Console.WriteLine("Data is: {0} " , var);
            Console.WriteLine("Data is: {0} " , p->ToString());
            Console.WriteLine("Address is: {0} " , (int)p);
         }
         
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код был скомпилирован и выполнен, он дает следующий результат —

Data is: 20
Data is: 20
Address is: 77128984

Передача указателей в качестве параметров для методов

Вы можете передать переменную-указатель методу в качестве параметра. Следующий пример иллюстрирует это —

using System;

namespace UnsafeCodeApplication {
   
   class TestPointer {
      
      public unsafe void swap(int* p, int *q) {
         int temp = *p;
         *p = *q;
         *q = temp;
      }
      
      public unsafe static void Main() {
         TestPointer p = new TestPointer();
         int var1 = 10;
         int var2 = 20;
         int* x = &var1;
         int* y = &var2;
         
         Console.WriteLine("Before Swap: var1:{0}, var2: {1}", var1, var2);
         p.swap(x, y);

         Console.WriteLine("After Swap: var1:{0}, var2: {1}", var1, var2);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Before Swap: var1: 10, var2: 20
After Swap: var1: 20, var2: 10

Доступ к элементам массива с помощью указателя

В C # имя массива и указатель на тип данных, совпадающий с данными массива, не совпадают с типом переменной. Например, int * p и int [] p не имеют одинаковый тип. Вы можете увеличивать переменную-указатель p, потому что она не фиксирована в памяти, а адрес массива фиксирован в памяти, и вы не можете увеличить его.

Поэтому, если вам нужен доступ к данным массива с помощью переменной указателя, как мы обычно делаем в C или C ++ (пожалуйста, проверьте: указатели C ), вам нужно исправить указатель, используя ключевое слово fixed .

Следующий пример демонстрирует это —

using System;

namespace UnsafeCodeApplication {
   
   class TestPointer {
      
      public unsafe static void Main() {
         int[]  list = {10, 100, 200};
         fixed(int *ptr = list)
         
         /* let us have array address in pointer */
         for ( int i = 0; i < 3; i++) {
            Console.WriteLine("Address of list[{0}]={1}",i,(int)(ptr + i));
            Console.WriteLine("Value of list[{0}]={1}", i, *(ptr + i));
         }
         
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код был скомпилирован и выполнен, он дает следующий результат —

Address of list[0] = 31627168
Value of list[0] = 10
Address of list[1] = 31627172
Value of list[1] = 100
Address of list[2] = 31627176
Value of list[2] = 200

Компиляция небезопасного кода

Для компиляции небезопасного кода необходимо указать ключ командной строки / unsafe с помощью компилятора командной строки.

Например, чтобы скомпилировать программу с именем prog1.cs, содержащую небезопасный код, из командной строки введите команду —

csc /unsafe prog1.cs

Если вы используете Visual Studio IDE, вам нужно разрешить использование небезопасного кода в свойствах проекта.

Для этого —

  • Откройте свойства проекта , дважды щелкнув узел свойств в обозревателе решений.

  • Нажмите на вкладку Build .

  • Выберите опцию « Разрешить небезопасный код ».

Откройте свойства проекта , дважды щелкнув узел свойств в обозревателе решений.

Нажмите на вкладку Build .

Выберите опцию « Разрешить небезопасный код ».

C # — многопоточность

Поток определяется как путь выполнения программы. Каждый поток определяет уникальный поток управления. Если ваше приложение включает в себя сложные и трудоемкие операции, то часто бывает полезно установить разные пути выполнения или потоки, при этом каждый поток выполняет определенную работу.

Нити — это легкие процессы . Одним из распространенных примеров использования потоков является реализация параллельного программирования в современных операционных системах. Использование потоков экономит время процессора и увеличивает эффективность приложения.

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

Жизненный цикл темы

Жизненный цикл потока начинается, когда создается объект класса System.Threading.Thread, и заканчивается, когда поток завершается или завершает выполнение.

Ниже приведены различные состояния в жизненном цикле потока —

  • Состояние без старта — это ситуация, когда создается экземпляр потока, но метод Start не вызывается.

  • Состояние готовности — это ситуация, когда поток готов к работе и ожидает цикл ЦП.

  • Not Runnable State — поток не является исполняемым, когда

    • Метод сна был вызван
    • Метод ожидания был вызван
    • Заблокировано операциями ввода / вывода
  • Мертвое состояние — это ситуация, когда поток завершает выполнение или прерывается.

Состояние без старта — это ситуация, когда создается экземпляр потока, но метод Start не вызывается.

Состояние готовности — это ситуация, когда поток готов к работе и ожидает цикл ЦП.

Not Runnable State — поток не является исполняемым, когда

Мертвое состояние — это ситуация, когда поток завершает выполнение или прерывается.

Основная тема

В C # класс System.Threading.Thread используется для работы с потоками. Это позволяет создавать и получать доступ к отдельным потокам в многопоточном приложении. Первый поток, выполняемый в процессе, называется основным потоком.

Когда программа на C # начинает выполнение, основной поток создается автоматически. Потоки, созданные с использованием класса Thread , называются дочерними потоками основного потока. Вы можете получить доступ к потоку, используя свойство CurrentThread класса Thread.

Следующая программа демонстрирует выполнение основного потока —

using System;
using System.Threading;

namespace MultithreadingApplication {
   
   class MainThreadProgram {
      
      static void Main(string[] args) {
         Thread th = Thread.CurrentThread;
         th.Name = "MainThread";
         Console.WriteLine("This is {0}", th.Name);
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

This is MainThread

Свойства и методы класса Thread

В следующей таблице приведены некоторые наиболее часто используемые свойства класса Thread.

Sr.No. Описание недвижимости
1

CurrentContext

Получает текущий контекст, в котором выполняется поток.

2

CurrentCulture

Получает или задает культуру для текущего потока.

3

CurrentPrinciple

Получает или задает текущего участника потока (для безопасности на основе ролей).

4

CurrentThread

Получает текущий запущенный поток.

5

CurrentUICulture

Получает или задает текущую культуру, используемую Resource Manager для поиска ресурсов, специфичных для данной культуры, во время выполнения.

6

ExecutionContext

Получает объект ExecutionContext, который содержит информацию о различных контекстах текущего потока.

7

Является живым

Получает значение, указывающее состояние выполнения текущего потока.

8

IsBackground

Получает или задает значение, указывающее, является ли поток фоновым потоком.

9

IsThreadPoolThread

Получает значение, указывающее, принадлежит ли поток к пулу управляемых потоков.

10

ManagedThreadId

Получает уникальный идентификатор для текущего управляемого потока.

11

название

Получает или задает имя потока.

12

приоритет

Получает или задает значение, указывающее приоритет планирования потока.

13

ThreadState

Получает значение, содержащее состояния текущего потока.

CurrentContext

Получает текущий контекст, в котором выполняется поток.

CurrentCulture

Получает или задает культуру для текущего потока.

CurrentPrinciple

Получает или задает текущего участника потока (для безопасности на основе ролей).

CurrentThread

Получает текущий запущенный поток.

CurrentUICulture

Получает или задает текущую культуру, используемую Resource Manager для поиска ресурсов, специфичных для данной культуры, во время выполнения.

ExecutionContext

Получает объект ExecutionContext, который содержит информацию о различных контекстах текущего потока.

Является живым

Получает значение, указывающее состояние выполнения текущего потока.

IsBackground

Получает или задает значение, указывающее, является ли поток фоновым потоком.

IsThreadPoolThread

Получает значение, указывающее, принадлежит ли поток к пулу управляемых потоков.

ManagedThreadId

Получает уникальный идентификатор для текущего управляемого потока.

название

Получает или задает имя потока.

приоритет

Получает или задает значение, указывающее приоритет планирования потока.

ThreadState

Получает значение, содержащее состояния текущего потока.

В следующей таблице приведены некоторые из наиболее часто используемых методов класса Thread.

Sr.No. Метод и описание
1

публичный void Abort ()

Вызывает исключение ThreadAbortException в потоке, в котором он вызывается, чтобы начать процесс завершения потока. Вызов этого метода обычно завершает поток.

2

public static LocalDataStoreSlot AllocateDataSlot ()

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

3

public static LocalDataStoreSlot AllocateNamedDataSlot (имя строки)

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

4

public static void BeginCriticalRegion ()

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

5

public static void BeginThreadAffinity ()

Уведомляет хост, что управляемый код собирается выполнить инструкции, которые зависят от идентификатора текущего физического потока операционной системы.

6

public static void EndCriticalRegion ()

Уведомляет хост о том, что выполнение собирается ввести область кода, в которой эффекты прерывания или необработанного исключения потока ограничены текущей задачей.

7

public static void EndThreadAffinity ()

Уведомляет хост, что управляемый код завершил выполнение инструкций, которые зависят от идентификатора текущего физического потока операционной системы.

8

публичная статическая пустота FreeNamedDataSlot (имя строки)

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

9

открытый статический объект GetData (слот LocalDataStoreSlot)

Извлекает значение из указанного слота в текущем потоке в текущем домене текущего потока. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

10

публичный статический AppDomain GetDomain ()

Возвращает текущий домен, в котором работает текущий поток.

11

публичный статический AppDomain GetDomainID ()

Возвращает уникальный идентификатор домена приложения

12

public static LocalDataStoreSlot GetNamedDataSlot (имя строки)

Ищет именованный слот данных. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

13

public void Interrupt ()

Прерывает поток, находящийся в состоянии потока WaitSleepJoin.

14

public void Join ()

Блокирует вызывающий поток до тех пор, пока поток не завершится, продолжая при этом выполнять стандартную прокачку COM и SendMessage. Этот метод имеет разные перегруженные формы.

15

public static void MemoryBarrier ()

Синхронизирует доступ к памяти следующим образом: Процессор, выполняющий текущий поток, не может переупорядочить инструкции таким образом, чтобы доступ к памяти до выполнения вызова MemoryBarrier выполнялся после обращений к памяти, которые следуют после вызова MemoryBarrier.

16

общедоступная статическая пустота ResetAbort ()

Отменяет прерывание, запрошенное для текущего потока.

17

public static void SetData (слот LocalDataStoreSlot, данные объекта)

Устанавливает данные в указанном слоте текущего запущенного потока для текущего домена этого потока. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

18

public void Start ()

Начинает поток.

19

public static void Sleep (int millisecondsTimeout)

Заставляет нить приостановиться на некоторое время.

20

общедоступная статическая пустота SpinWait (int iterations)

Заставляет поток ждать количество раз, определенное параметром iterations

21

открытый статический байт VolatileRead (адрес байта)

public static double VolatileRead (ссылка на двойной адрес)

public static int VolatileRead (ref int address)

публичный статический объект VolatileRead (ссылка на адрес объекта)

Читает значение поля. Значение является последним, записанным любым процессором в компьютере, независимо от количества процессоров или состояния кэша процессора. Этот метод имеет разные перегруженные формы. Только некоторые из них приведены выше.

22

public static void VolatileWrite (адрес байта, значение байта)

public static void VolatileWrite (ссылка двойной адрес, двойное значение)

public static void VolatileWrite (ref int address, int value)

public static void VolatileWrite (ref Адрес объекта, Значение объекта)

Немедленно записывает значение в поле, чтобы оно было доступно всем процессорам компьютера. Этот метод имеет разные перегруженные формы. Только некоторые из них приведены выше.

23

public static bool Yield ()

Заставляет вызывающий поток передать выполнение другому потоку, который готов к запуску на текущем процессоре. Операционная система выбирает поток для уступки.

публичный void Abort ()

Вызывает исключение ThreadAbortException в потоке, в котором он вызывается, чтобы начать процесс завершения потока. Вызов этого метода обычно завершает поток.

public static LocalDataStoreSlot AllocateDataSlot ()

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

public static LocalDataStoreSlot AllocateNamedDataSlot (имя строки)

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

public static void BeginCriticalRegion ()

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

public static void BeginThreadAffinity ()

Уведомляет хост, что управляемый код собирается выполнить инструкции, которые зависят от идентификатора текущего физического потока операционной системы.

public static void EndCriticalRegion ()

Уведомляет хост о том, что выполнение собирается ввести область кода, в которой эффекты прерывания или необработанного исключения потока ограничены текущей задачей.

public static void EndThreadAffinity ()

Уведомляет хост, что управляемый код завершил выполнение инструкций, которые зависят от идентификатора текущего физического потока операционной системы.

публичная статическая пустота FreeNamedDataSlot (имя строки)

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

открытый статический объект GetData (слот LocalDataStoreSlot)

Извлекает значение из указанного слота в текущем потоке в текущем домене текущего потока. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

публичный статический AppDomain GetDomain ()

Возвращает текущий домен, в котором работает текущий поток.

публичный статический AppDomain GetDomainID ()

Возвращает уникальный идентификатор домена приложения

public static LocalDataStoreSlot GetNamedDataSlot (имя строки)

Ищет именованный слот данных. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

public void Interrupt ()

Прерывает поток, находящийся в состоянии потока WaitSleepJoin.

public void Join ()

Блокирует вызывающий поток до тех пор, пока поток не завершится, продолжая при этом выполнять стандартную прокачку COM и SendMessage. Этот метод имеет разные перегруженные формы.

public static void MemoryBarrier ()

Синхронизирует доступ к памяти следующим образом: Процессор, выполняющий текущий поток, не может переупорядочить инструкции таким образом, чтобы доступ к памяти до выполнения вызова MemoryBarrier выполнялся после обращений к памяти, которые следуют после вызова MemoryBarrier.

общедоступная статическая пустота ResetAbort ()

Отменяет прерывание, запрошенное для текущего потока.

public static void SetData (слот LocalDataStoreSlot, данные объекта)

Устанавливает данные в указанном слоте текущего запущенного потока для текущего домена этого потока. Для повышения производительности используйте поля, помеченные атрибутом ThreadStaticAttribute.

public void Start ()

Начинает поток.

public static void Sleep (int millisecondsTimeout)

Заставляет нить приостановиться на некоторое время.

общедоступная статическая пустота SpinWait (int iterations)

Заставляет поток ждать количество раз, определенное параметром iterations

открытый статический байт VolatileRead (адрес байта)

public static double VolatileRead (ссылка на двойной адрес)

public static int VolatileRead (ref int address)

публичный статический объект VolatileRead (ссылка на адрес объекта)

Читает значение поля. Значение является последним, записанным любым процессором в компьютере, независимо от количества процессоров или состояния кэша процессора. Этот метод имеет разные перегруженные формы. Только некоторые из них приведены выше.

public static void VolatileWrite (адрес байта, значение байта)

public static void VolatileWrite (ссылка двойной адрес, двойное значение)

public static void VolatileWrite (ref int address, int value)

public static void VolatileWrite (ref Адрес объекта, Значение объекта)

Немедленно записывает значение в поле, чтобы оно было доступно всем процессорам компьютера. Этот метод имеет разные перегруженные формы. Только некоторые из них приведены выше.

public static bool Yield ()

Заставляет вызывающий поток передать выполнение другому потоку, который готов к запуску на текущем процессоре. Операционная система выбирает поток для уступки.

Создание тем

Потоки создаются путем расширения класса Thread. Затем расширенный класс Thread вызывает метод Start (), чтобы начать выполнение дочернего потока.

Следующая программа демонстрирует концепцию —

using System;
using System.Threading;

namespace MultithreadingApplication {
   
   class ThreadCreationProgram {
      
      public static void CallToChildThread() {
         Console.WriteLine("Child thread starts");
      }
      
      static void Main(string[] args) {
         ThreadStart childref = new ThreadStart(CallToChildThread);
         Console.WriteLine("In Main: Creating the Child thread");
         Thread childThread = new Thread(childref);
         childThread.Start();
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

In Main: Creating the Child thread
Child thread starts

Управление потоками

Класс Thread предоставляет различные методы для управления потоками.

В следующем примере демонстрируется использование метода sleep () для приостановки потока на определенный период времени.

using System;
using System.Threading;

namespace MultithreadingApplication {
   
   class ThreadCreationProgram {
      
      public static void CallToChildThread() {
         Console.WriteLine("Child thread starts");
         
         // the thread is paused for 5000 milliseconds
         int sleepfor = 5000; 
         
         Console.WriteLine("Child Thread Paused for {0} seconds", sleepfor / 1000);
         Thread.Sleep(sleepfor);
         Console.WriteLine("Child thread resumes");
      }
      
      static void Main(string[] args) {
         ThreadStart childref = new ThreadStart(CallToChildThread);
         Console.WriteLine("In Main: Creating the Child thread");
         Thread childThread = new Thread(childref);
         childThread.Start();
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes

Уничтожение Тем

Метод Abort () используется для уничтожения потоков.

Среда выполнения прерывает поток, создавая исключение ThreadAbortException . Это исключение не может быть перехвачено, элемент управления отправляется в блок finally , если таковой имеется.

Следующая программа иллюстрирует это —

using System;
using System.Threading;

namespace MultithreadingApplication {
   
   class ThreadCreationProgram {
      
      public static void CallToChildThread() {
         
         try {
            Console.WriteLine("Child thread starts");
            
            // do some work, like counting to 10
            for (int counter = 0; counter <= 10; counter++) {
               Thread.Sleep(500);
               Console.WriteLine(counter);
            }
            
            Console.WriteLine("Child Thread Completed");
         } catch (ThreadAbortException e) {
            Console.WriteLine("Thread Abort Exception");
         } finally {
            Console.WriteLine("Couldn't catch the Thread Exception");
         }
      }
      
      static void Main(string[] args) {
         ThreadStart childref = new ThreadStart(CallToChildThread);
         Console.WriteLine("In Main: Creating the Child thread");
         Thread childThread = new Thread(childref);
         childThread.Start();
         
         //stop the main thread for some time
         Thread.Sleep(2000);
         
         //now abort the child
         Console.WriteLine("In Main: Aborting the Child thread");
         
         childThread.Abort();
         Console.ReadKey();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —