Скачать презентацию
Идет загрузка презентации. Пожалуйста, подождите
Презентация была опубликована 11 лет назад пользователемinfosystemology.ru
1 Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные (два операнда) Общее понятие оператора Виды операторов: 1. Логические (==, !=,, =) 2. Математические (+, -, *, /, ++, --, %,
2 Список операторов Унарные операторы: +, -, !, ~, ++, --, true, false Бинарные операторы: +, -, *, /, %, &, |, ^, >, ==, !=, >, =, , new, is, sizeof, typeof 2
3 3 Оператор сравнения class Fraction { public int A { get; set; } public int B { get; set; } public static bool operator < (Fraction left, Fraction right) { return (left.A / left.B < right.A / right.B); } Fraction f1 = new Fraction { A = 2, B = 3 }; Fraction f2 = new Fraction { A = 3, B = 4 }; if (f1 < f2) { }
4 Перегрузка оператора – реализация статического операторного метода, определяющего результат применения данной операции к объекту(ам) класса. Цель перегрузки: обеспечить краткую и удобную форму записи операций над объектами, аналогично операциям над встроенными типами данных. Рекомендации: 1. Перегрузка как правило имеет смысл в случае тех типов, поведение которых подобно примитивным (например, классы, представляющие числа, математические объекты и т.п.). 2. Смысл перегружаемой операции для данного типа должен быть прозрачен.
5 Правила перегрузки 1. Перегрузка применима только к пользовательским типам, или их смеси со встроенными (т.е. как минимум один из операндов – объект вашего класса). 2. Перегружать можно только существующие операции. 3. При перегрузке нельзя изменить приоритет операций. 4. Параметры операторного метода передаются без ref, out, params. 5. При перегрузке симметричных операций необходимо реализовать оба варианта: != и ==,, …
6 Унарный минус class Vector2D { private double x; private double y; public Vector2D(double x, double y) { this.x = x; this.y = y; } public static Vector2D operator - (Vector2D v) { return new Vector2D(-v.x, -v.y); } Vector2D v1 = new Vector2D(15.5, 23.0); Vector2D v2 = -v1; 6
7 Префиксный инкремент class Vector2D { private double x; private double y; public Vector2D(double x, double y) { this.x = x; this.y = y; } public static Vector2D operator ++ (Vector2D v) { v.x++; v.y++; return v; } Vector2D v1 = new Vector2D(1, 1); Vector2D v2 = v1++; 7
8 Оператор явного преобразования class Fraction { private int a = 0; private int b = 0; public static explicit operator double (Fraction frac) { return (frac.a / frac.b); } Fraction f = new Fraction(); double fd = (double)f; double fd2 = f; //error Оператор явного не вызывается автоматически (неявно) 8
9 Оператор неявного преобразования - Оператор неявного может быть вызван явно; - Нельзя перегрузить обе формы; - Нельзя определять преобразования: в тип object, в производный тип, из одного интерфейса в другой. 9 class Fraction { private int a = 0; private int b = 0; public static implicit operator double (Fraction frac) { return (frac.a / frac.b); } Fraction f = new Fraction(); double fd2 = f; double fd = (double)f;
10 class Vector2D { private double x; private double y; public Vector2D() : this(0.0, 0.0) { } public Vector2D(double x, double y) { this.x = x; this.y = y; } public static Vector2D operator + (Vector2D a, Vector2D b) { Vector2D c = new Vector2D(); c.x = a.x + b.x; c.y = a.y + b.y; return c; //return new Vector2D(a.x + b.x, a.y + b.y); } Vector2D v1 = new Vector2D(15.5, 23.0); Vector2D v2 = new Vector2D(21.5, 40.5); Vector2D v3 = v1 + v2; Бинарный плюс 10
11 Индексаторы тип_элемента this [тип_индекса значение_индекса] { // Аксессор чтения get { } // Аксессор записи set { } 11
12 class Array { private float [] array; public Array(int size) { array = new float[size]; } public float this[int index] { get { if (index = this.array.Length) throw new IndexOutOfRangeException("Индекс за пределами!"); return this.array[index]; } set { if (index = this.array.Length) throw new IndexOutOfRangeException("Индекс за пределами!"); this.array[index] = value; } 12
13 class Program { static void Main() { try { Array someArray = new Array(10); someArray[5] = 1; float f = someArray[50]; } catch (Exception e) { Console.WriteLine(e.Message); } 1. Допустимо использовать только 1 аксессор. 2. В set-аксессор внешнее значение передается через value. 3. Индексатор можно перегружать. 4. Тип индекса и их количество – любое. 5. Индексатор нельзя объявлять как static 6. Тип индекса не может дополняться модификатором ref или out 13
14 class Time { private int hour = 0; private int min = 0; private int sec = 0; …. } class Program { static void Main() { Time t = new Time(); Console.WriteLine(t); // ??? } 14 Перегрузка ToString
15 class Time { private int hour = 0; private int min = 0; private int sec = 0; public override string ToString() { return string.Format("{0:00}:{1:00}:{2:00}", this.hour, this.min, this.sec); } … Time t = new Time(); Console.WriteLine(t); 15
16 Операторы сравнения В C# существует понятие 2-х видов сравнения: 1.Равенство ссылок. 2.Равенство значений. Time t1 = new Time(); // class Time Time t2 = t1; bool isSameObject1 = ( t1 == t2 ); bool isSameObject2 = System.Object.ReferenceEquals(t1, t2); 16 Для ссылочных типов (кроме string) оператор == по умолчанию сравнивает ссылки (также, как и ReferenceEquals).ReferenceEquals
17 17 Для типов по значению (кроме struct) оператор == сравнивает значения. int x = 0, y = 1; if (x == y) { } Point p1, p2; // struct Point bool isSameObject = ( p1 == p2 ); // Не определен!
18 { … public override bool Equals(System.Object obj) { if (obj == null) return false; Time t = obj as Time; if ((System.Object)t == null) return false; return (hour == t.hour) && (min == t.min) && (sec == t.sec); } … } 18 Для сравнения ссылочных типов по значению перегружается метод Equals.
19 public bool Equals(Time t) { if ((object)t == null) { return false; } return (hour == t.hour) && (min == t.min) && (sec == t.sec); } public override int GetHashCode() { return hour ^ min ^ sec; } 19
20 Новая реализация Equals должна соответствовать гарантиям: 1.x.Equals(x) возвращает true. 2. x. Equals (y) возвращает то же значение, что и y. Equals (x). 3. если (x. Equals (y) && y. Equals (z)) возвращает true, то x. Equals (z) возвращает true. 4. Последовательные вызовы x. Equals (y) возвращают то же значение до тех пор, пока объекты, на которые ссылается x и y, не будут изменены. 5. x. Equals (null) возвращает false. 20 В Equals не следует выбрасывать исключения.
21 21 public static bool operator ==(ThreeDPoint a, ThreeDPoint b) { // If both are null, or both are same instance, return true. if (System.Object.ReferenceEquals(a, b)) { return true; } // If one is null, but not both, return false. if (((object)a == null) || ((object)b == null)) { return false; } // Return true if the fields match: return a.x == b.x && a.y == b.y && a.z == b.z; } public static bool operator !=(ThreeDPoint a, ThreeDPoint b) { return !(a == b); }
22 22 Для структур (которым по смыслу нужна операция сравнения): 1. Перегружаем ==. 3. Перегружаем Equals, для чего наследуем IEquatable. Для классов (чаще из области математики, кому реально нужны сравнения): 1. Перегружаем Equals (помня о 5 гарантиях). 2. Не перегружаем ==, он будет работать эквивалентно object.ReferenceEquals.
Еще похожие презентации в нашем архиве:
© 2024 MyShared Inc.
All rights reserved.