Российский Государственный Технологический Университет им. К.Э. Циолковского
Опубликован: 02.03.2007 | Доступ: свободный | Студентов: 5678 / 802 | Оценка: 3.96 / 3.45 | Длительность: 27:04:00
ISBN: 978-5-9556-0086-4
Лекция 3:

Управляющие операторы и методы

< Лекция 2 || Лекция 3: 123456 || Лекция 4 >

Методы

В C# методы определяются в рамках объявления класса. Методы (функции) являются членами класса и определяют функциональность объектов — членов класса (нестатические методы – методы объектов) и непосредственно функциональность самого класса (статические методыметоды класса).

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

Различают статические (со спецификатором static ) и нестатические методы (объявляются без спецификатора).

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

ОбъявлениеМетода ::= ЗаголовокМетода ТелоМетода
ЗаголовокМетода ::= [СпецификаторМетода] 
ТипВозвращаемогоЗначения
Имя
([СписокПараметров])

СпецификаторМетода ::= СпецификаторДоступности
::= new
::= static
::= virtual
::= sealed
::= override
::= abstract
::= extern

СпецификаторДоступности ::= public
::= private
::= protected
::= internal
::= protected internal

ТипВозвращаемогоЗначения ::= void | ИмяТипа 
ТелоМетода ::= БлокОператоров
 ::= ;

Имя ::= Идентификатор
СписокПараметров ::= [СписокПараметров ,] ОбъявлениеПараметра
ОбъявлениеПараметра ::= [СпецификаторПередачи] ИмяТипа ИмяПараметра 
::= [СпецификаторСписка] ИмяТипаСписка ИмяПараметра
СпецификаторПараметра ::= СпецификаторПередачи | СпецификаторСписка
СпецификаторПередачи ::= ref | out 
СпецификаторСписка ::= params
ИмяТипаСписка ::= ИмяТипа[]
Листинг 3.1.

Тело метода может быть пустым! В этом случае за заголовком метода располагается точка с запятой.

Класс, объявление которого содержит только объявления статических методов, называется статическим классом и может объявляться со спецификатором static:

public static class XXX
{
static int f1(int x)
 {
  return 1;
 }

static int f2(int x)
 { 
 return 2;
 }
}

Вызов метода

Выражение вызова метода — это всего лишь выражение, составная часть оператора (предложения C#). Оно располагается в блоке операторов — в теле метода. Выражению вызова метода может предшествовать выражение, определяющее принадлежность метода классу или объекту.

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

Нестатические методы определяют поведение конкретных объектов-представителей класса и потому вызываются "от имени" объекта-представителя класса, содержащего объявление вызываемого метода. Указание на конкретный объект — это всего лишь выражение, обеспечивающее ссылку на данный объект. Таковым действительно может быть имя объекта, выражение this (которое вообще может быть опущено), выражение индексации и другие выражения ссылочного типа.

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

Обработка исключений

Пусть в классе объявляются методы A и B.

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

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

Если при выполнении метода B возникла исключительная ситуация (например, целочисленное деление на 0), возможно, что метод A узнает об этом, анализируя возвращаемое из B значение. Таким может быть один из сценариев "обратной связи", при котором вызывающий метод узнает о результатах деятельности вызываемого метода.

Недостатки этого сценария заключаются в том, что:

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

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

Некорректная ситуация в ходе выполнения программы (деление на нуль, выход за пределы массива) рассматривается как исключительная ситуация, и метод, в котором она произошла, реагирует на нее ГЕНЕРАЦИЕЙ ИСКЛЮЧЕНИЯ, а не обычным возвращением значения, пусть даже изначально ассоциированного с ошибкой.

Среда выполнения создает объект для представления исключения при его возникновении. Одновременно с этим прерывается обычный ход выполнения программы. Происходит так называемое разматывание стека, при котором управление НЕ оказывается в точке возврата, и если ни в одном из методов, предшествующих вызову, не было предпринято предварительных усилий по ПЕРЕХВАТУ ИСКЛЮЧЕНИЯ, приложение аварийно завершается.

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

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

Следующий пример демонстрирует основные принципы организации генераторов и перехватчиков исключений.

using System;

// Объявление собственного исключения.
// Наследуется базовый класс Exception.
public class xException:Exception
{
// Собственное исключение имеет специальную строчку,
// и в этом ее отличие. 
public string xMessage;

// Кроме того, в поле ее базового элемента
// также фиксируется особое сообщение. 
public xException(string str):base("xException is here...")
{
	xMessage = str;
}

}

// Объявление собственного исключения.
// Наследуется базовый класс Exception.
public class MyException:Exception
{
// Собственное исключение имеет дополнительную
// специальную строчку для кодирования информации
// об исключении. 
public string MyMessage;

// Кроме того, в поле ее базового элемента
// также фиксируется особое сообщение. 
public MyException(string str):base("MyException is here...")
{
    MyMessage = str;
}
}

public class StupidCalcule
{
public int Div(int x1, int x2)
{
// Вот здесь метод проверяет корректность операндов и с помощью оператора  
// throw возбуждает исключение.
 if (x1 != 0 && x2 == 0)
    throw new Exception("message from Exception: Incorrect x2!");
 else if (x1 == 0 && x2 == 0)
    throw new MyException("message from MyException: Incorrect x1 
&& x2!");
 else if (x1 == –1 && x2 == –1)
    throw new xException("message from xException: @#$%*&^???");
	
// Если же ВСЕ ХОРОШО, счастливый заказчик получит ожидаемый результат. 
return (int)(x1/x2);	
}
}

public class XXX  
{

public static void Main()  
{
int ret;
StupidCalcule sc = new StupidCalcule();

// Наше приложение специально подготовлено к обработке исключений!
// Потенциально опасное место (КРИТИЧЕСКАЯ СЕКЦИЯ) ограждено
//	(заключено в блок try)   
try
{
 // Вызов...
 ret = sc.Div(–1,–1);
 // Если ВСЕ ХОРОШО – будет выполнен оператор Console.WriteLine.
 // Потом операторы блока finally, затем операторы за 
 // пределами блоков try, catch, finally.  
Console.WriteLine("OK, ret == {0}.", ret.ToString());
}
catch (MyException e)
{
// Здесь перехватывается MyException.
Console.WriteLine((Exception)e);	
Console.WriteLine(e.MyMessage);	
}
// Если этот блок будет закомментирован – 
// возможные исключения типа Exception и xException
// окажутся неперехваченными. И после блока
// finally приложение аварийно завершится.
catch (Exception e)
{
// А перехватчика xException у нас нет!
// Поэтому в этом блоке будут перехватываться
// все ранее неперехваченные потомки исключения Exception.
// Это последний рубеж.
// Еще один вариант построения последнего рубежа
// выглядит так:
// catch
//{
//  Операторы обработки – сюда. Здесь в любом случае код,
//  реализующий алгоритм последнего перехвата. 

    Console.WriteLine(e);	
}
finally
{
  // Операторы в блоке finally выполняются ВСЕГДА, тогда как
  // операторы, расположенные за пределами блоков try, catch, finally,
  // могут и не выполниться вовсе.
  Console.WriteLine("finally block is here!");	
}
// Вот если блоки перехвата исключения окажутся не
// соответствующими возникшему исключению – нормальное
// выполнение приложения будет прервано – и мы никогда не увидим
// этой надписи.    
Console.WriteLine("Good Bye!");	
}
}
Листинг 3.2.
< Лекция 2 || Лекция 3: 123456 || Лекция 4 >
kewezok kewezok
kewezok kewezok
Елена Шляхт
Елена Шляхт
Объясните плиз в чем отличие а++ от ++а
Почему результат разный?
int a=0, b=0;
Console.WriteLine(a++); //0
Console.WriteLine(++b); //1
a++;
++b;
Console.WriteLine(a); //2
Console.WriteLine(b); //2