Исключительные ситуации. Обработка исключений. Блоки try-catch-finally. — КиберПедия 

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

Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...

Исключительные ситуации. Обработка исключений. Блоки try-catch-finally.

2019-08-03 267
Исключительные ситуации. Обработка исключений. Блоки try-catch-finally. 0.00 из 5.00 0 оценок
Заказать работу

/начало из предыдущего вопроса/

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

При наличии блока finally можно опустить блок catch.

 

Исключительные ситуации. Обработка исключений. Создание собственного исключения

Генерация пользовательского исключения делается с помощью слова throw. Не обязательно писать в try.

 

Пример:

try {

       int i=Convert.ToInt32(textBox1.Text);

       if (i>200) throw new Exception («Число больше 200»);

       catch (Exception e)

       {button1.Text=e.message

}

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

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

class В {

private float t;

public float get_T(){return t;}

public void set_T(float tt){

if(tt < 35 || tt>42) { throw new System. ArgumentException ();}

else t=tt;}}

 

Наследование классов. Иерархии классов. Примеры.

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

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

Напоминание: методы производного класса могут работать только с открытыми (public) и защищёнными (protected и protected internal) членами базового класса, и если классы находятся в одной сборке, то членами, имеющими уровень доступа internal. Но не могут работать с собственными (private)членами базового класса.

 

Пример:

с lass cir: vec {

public int R;

public void fun(void)

{ return x*y+R;}}

 

Класс cir является наследником класса vec, метод fun использует наравне с полем R, поля базового класса x,y, что возможно в том случае, когда уровень доступности указанных полей либо public, protected.

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

 

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

 

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

 

class B{ public int x;

public B(int xx) { x=xx; }

}

 

class C:B{

public C(int xx):base(xx) {}}

 

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

 

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

Запрет наследования: классы объявленные как sealed.

Класс String пространства имен System является закрытым для наследования.

class T{

       public int x,y;

       public int sum()

       {return x+y;}

       }

class P: T{

       public int z;

       }

class S: P{

       public int u;

       public int pr()

       {return x*z*u;}      }

В этом примере определены три класса: Т, P, S. Как мы видим из описания, класс Р является производным от класса Т, а на основе класса Р строится класс S. Таким образом, можно создавать весьма разветвленные иерархии классов.

                Отметим, что метод pr() класса S наравне с полем u, использует поля x,z, которые достались в наследство, такое оказалось возможным, потому, что поля имеют уровень доступа public. Производный класс получает в наследство все члены базового класса, но методы производного класса не могут напрямую работать с членами уровня доступа private, да и возможность работы с членами базового класса уровня internal, зависит от того в одной ли сборке находятся базовый и производный классы

 

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

Рисунок 1. Пример иерархии классов.

               

Виртуальные и невиртуальные методы. Ссылки базовых классов. Примеры.

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

Примеры.

B b=new C();// классы В и С определены выше

B d=new D();

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

Если нужно перейти от ссылки базового класса к ссылке производного класса, то надо выполнить преобразование типов.

C c; c=(C)d; b=c;

 

Поскольку по ссылке базового класса не всегда ясно на какой объект она указывает, то в С# введены специальные операторы is и as, которые выполняют проверку возможно ли сделать соответствующее преобразование типов.

class T{

       public int x,y;

       public int sum()

       {return x+y;}

       }

class P: T{

       public int z;

       }

class S: P{

       public int u;

       public int pr()

       {return x*z*u;}      }

 

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

T t=new P();

S s = new S();

t=s;

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

Итак, работая через ссылку t, с объектами классов P и S, мы можем обращаться к полям x,y и методу sum, остальные поля и методы классов P и S будут недоступны. 

Если для объекта типа S надо вызвать метод рr, определенный в этом классе, а работаем с объектом через ссылку базового класса t? В этом случае надо выполнить преобразование типов: ((S)t).pr(). Обратите внимание, как расставлены скобки. Поскольку операция доступа – точка - имеет больший приоритет, чем преобразование типов, то приходится преобразование типов брать в скобки ((S)t), и только потом использовать операцию доступа.

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

Для решения подобных проблем используются виртуальные методы.

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

Например.

class N{

                   public int p=2,q=3;

                   public virtual int pr()

                   {return p*q;}

       }

       class M: N{

                   public int g=4;

                   public override int pr()

                   {return p*q*g;}

       }

       class K: M {

       public int r=5;

       public override int pr()

                   {return p*q*g*r;}

       }

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

                   N n= new M();

                              int i=n.pr();

                              n= new K();

                              int j = n.pr();

                                  

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

При вызове невиртуального метода, метод определяется типом ссылки. Невиртуальный метод не переопределяется в классах-наследниках.

Класс object. Переопределение метода ToString(). Примеры.

Слово object является псевдонимом библиотечного класса System.Object, который считается базовым классом для всех остальных классов и типов, включая и структурные типы. Можно сказать, что все остальные типы являются производными от object. Это, в частности, означает, что переменная ссылочного типа object может ссылаться на объект любого другого типа. Кроме того, в любом классе можно переопределить методы из этого класса.

Метод ToString, по умолчанию, возвращает полное имя типа. Но для встроенных числовых типов, например, или он переопределен и возвращает строковые записи значений, что удобно для операций вывода. Поэтому данный метод часто переопределяют и в других классах. Метод а.Equals(b) возвращает true (истину) только, если a и b являются ссылками на один объект. Этот метод часто переопределяют, для того, что бы он возвращал значение истина для равных объектов.

Рассмотрим пример такого переопределения для класса Vector.

class Vector

{public float x; public float y;

public override string ToString()

{return x.ToString()+","+y.ToString();}// здесь мы пользуемся тем, //что метод ToString переопределен для типа float.

 

public override bool Equals(Object o)

{if(o==null) return false;

if(!(o is Vector)) return false;

Vector oo=(Vector)o;

if(!x.Equals(oo.x))return false; // здесь мы пользуемся тем, //что метод Equals переопределен для типа float.

if(!y.Equals(oo.y))return false;

return true;}

 

}

Создадим вектор, т.е. объект класса Vector.

Vector v=new Vector();

 

v.x=8; v.y=9;

label1.Text=v.ToString();

В результате работы этого фрагмента программы на форму будет выведена запись – 8, 9, т.е. координаты вектора v.

 

Создадим еще один вектор vv, с какими же координатами:

Vector vv=new Vector();

vv.x=8; vv.y=9;

 

Следующая команда выведет значение true, хотя v,vv разные вектора. Label2.Text= v.Equals(vv).ToString();

 

27. Преобразование типов. Операторы is и as.

В программировании нередко значения переменных одного типа присваиваются переменным другого типа. Например, в приведенном ниже фрагменте кода целое значение типа int присваивается переменной с плавающей точкой типа float:
int i; float f; i = 10; f = i;

Если в одной операции присваивания смешиваются совместимые типы данных, то значение в правой части оператора присваивания автоматически преобразуется в тип, указанный в левой его части. Поэтому в приведенном выше фрагменте кода значение переменной i сначала преобразуется в тип float, а затем присваивается переменной f.

Зададимся вопросом, всегда ли возможно преобразование типов? Когда будут возникать сообщения об ошибках, как это повлияет на надежность разрабатываемых программ?

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

Например, типы bool и int несовместимы. Правда, преобразование несовместимых типов все-таки может быть осуществлено путем приведения. Приведение типов, по существу, означает явное их преобразование.

Оператор is никогда не генерирует исключение, он работает со всеми типами. Он имеет следующий вид: Ссылка is Тип Оператор is возвращает значение булево типа, true - если объект на который указывает ссылка можно привести к типу, стоящему после is и false – если ссылка нулевая или объект нельзя привести к указанному типу.

Например.

 

int i=8;

Object o=new Object();

 

Boolean b=(i is Object); //b будет равно true Boolean

b1=(o is int); //b1 будет равно false

 

Оператор as работает со ссылочными типами, он производит нужное преобразование типов, если оно возможно и возвращает null, если оно невозможно. Команда A a=o as A; будет выполнена успешно, но в ссылку а будет записан null, и любое обращение к а как к объекту, например, a.ToString(); вызовет генерацию исключения. Проверку того, не получила ли ссылка нулевого значения, должен выполнить программист. В нашем случае – if(a!=null)a.ToString();

 


Поделиться с друзьями:

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

Наброски и зарисовки растений, плодов, цветов: Освоить конструктивное построение структуры дерева через зарисовки отдельных деревьев, группы деревьев...

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

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



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.049 с.