Тип интерфейс Интерфейс – именованный набор методов, не имеющих реализации. Определение интерфейса может содержать • методы (только сигнатуры) • свойства • индексаторы • события В классе, реализующем интерфейс, должны быть реализованы все методы интерфейса. Интерфейс описывает общую функциональность различных типов. public interface System.IDisposable { void Dispose(); } public interface System.IComparable { int CompareTo ( Object obj ); } Определение интерфейса Имя интерфейса рекомендуется начитать с буквы I. Методы интерфейса не имеют модификаторов доступа. По умолчанию все методы интерфейса являются открытыми (public) и виртуальными (virtual). Интерфейс может быть унаследован от нескольких интерфейсов. public interface ICollection : IEnumerable { int Count {get;} bool IsSynchronized {get;} object SyncRoot {get;} void CopyTo( Array array, int index ); } public interface IEnumerable { IEnumerator GetEnumerator(); } Реализация интерфейсов В типе, реализующем интерфейс, должны быть реализованы все методы интерфейса и все методы унаследованных интерфейсов. Методы интерфейса могут быть реализованы явно и неявно. • При неявной реализации в типе определяется метод с соответствующей сигнатурой без указаний на интерфейс. Этот метод виден как обычный метод типа. • При явной реализации в определении метода в типе явно указывается имя интерфейса. Тип может содержать одновременно явную реализацию интерфейса и метод с тем же именем и сигнатурой. При помощи явной реализации можно реализовать два интерфейса с одинаковыми методами. public class ArrayList : IList, ICollection, IEnumerable, ICloneable { IEnumerator GetEnumerator() { … } … } Реализация интерфейсов -2 Класс, реализующий интерфейс, может наследовать реализацию методов интерфейса от своих базовых классов. public interface Intf1 { void F0(); void F1(); } public interface Intf2 { void F0(); void F2(); void F3(); } public class A : Intf1 { public void F0 () { Console.WriteLine public virtual void { Console.WriteLine public void F2() { Console.WriteLine } static void Main(string[] args) { A a = new A(); Dr d = new Dr(); a.F0(); // A.F0 d.F0(); // A.F0 // d.F3(); // D does not contain a definition for 'F3' явная реализация метода интерфейса Intf1 it1 = a; Intf1 it11 = d; it1.F0(); // A.F0 it11.F0(); // A.F0 ("A.F0");} F1 () ("A.F1");} Intf2 it2 = d; it2.F0(); it2.F3(); ("A.F2");} public class Dr : A, Intf2 { void Intf2.F0() { Console.WriteLine ("Dr.F0");} public override void F1 () { Console.WriteLine ("Dr.F1");} void Intf2.F3() { Console.WriteLine (“Dr.F3");} } // Dr.F0 // Dr.F3 A ar = it11 as A; Dr dr = it11 as Dr; if (ar == null) Console.WriteLine("ar == null"); else Console.WriteLine("ar != null"); // ar != null Console.WriteLine(object.ReferenceEquals(ar, dr)); // true Console.WriteLine(object.ReferenceEquals(ar, it11)); // true } Интерфейс как параметр или как тип возвращаемого значения Возможно неявное преобразование класса к реализуемому им интерфейсу. Метод класса System.Collections.ArrayList public virtual void Sort( IComparer comparer ); как значение параметра принимает ссылку на объект любого типа, который реализует интерфейс IComparer. public interface IComparer { int Compare( object x, object y ); } Особенности реализации интерфейсов Если интерфейс реализован с помощью невиртуального метода, то при вызове через интерфейс будет вызван метод, соответствующий статическому типу в момент приведения к типу интерфейса. Даже если базовый класс реализовал интерфейс, то производный класс снова может реализовать интерфейс. public interface I { void f(); } public class A : I { public void f() { Console.WriteLine("A.f"); } } public class B : A,I { public new void f() { Console.WriteLine("B.f"); } } I i1 = new I i2 = new i1.f(); // i2.f(); // A(); B(); A.f B.f Интерфейс IDisposable Классы, требующие явного освобождения ресурсов, могут предоставлять интерфейс IDisposable interface IDisposable { void Dispose(); } Оператор using - краткая форма try-finally class A : IDisposable { } class B : IDisposable { } using(a = new A()) using(b = new B()) { // … } a = new A(); try { b = new B(); try { … } finally { b.Dispose(); } } finally { a.Dispose(); } Оператор foreach итерационная переменная оператор foreach (type identifier in expression) statement тип итерационной переменной массив или коллекция Коллекция (expression) • должна иметь тип class, struct или interface; • в типе, который имеет коллекция, должен быть определен открытый экземплярный метод GetEnumerator(). В типе, который возвращает метод GetEnumerator(), должны быть определены • свойство Current { get;}, которое дает доступ к текущему элементу коллекции; • метод bool MoveNext(), который возвращает значение • true - если в коллекции еще есть элементы; • false - в противном случае. Тип свойства Current (тип элементов коллекции) должен допускать неявное преобразование к типу <type>. Интерфейсы System.IEnumerable и System.Collections.IEnumerator В классе, реализующем интерфейс IEnumerable, можно использовать оператор foreach. Интерфейс IEnumerable реализован в классе System.Array и классахколлекциях. public interface IEnumerator { object Current {get;} bool MoveNext(); void Reset(); } public interface IEnumerable { IEnumerator GetEnumerator(); } Интерфейс System.Collections.IEnumerator Итераторы(еnumerators) используются только для чтения данных из коллекции, их нельзя использовать для изменения коллекции. При инициализации enumerator позиционируется перед первым элементом коллекции. Вызов Current в этой позиции порождает исключение. Необходимо вызвать MoveNext перед тем, как обратиться к Current. Reset возвращает enumerator в позицию инициализации. Метод MoveNext перемещает Current к следующему элементу. Current возвращает один и тот же объект до тех пор, пока не будут вызваны MoveNext или Reset. MoveNext возвращает false, когда enumerator позиционируется за последним элементом коллекции. Если последний вызов MoveNext возвращает false, вызов Current бросает исключение. Интерфейсы System.IComparable, System.Collections.IComparer public interface IComparable { int CompareTo( object y ); } public interface IComparer { int Compare( object x, object y ); } Возвращаемое значение: <0 x<y 0 x==y >0 x>y ( в методе CompareTo x – вызывающий объект) Интерфейс IComparable реализован в типах string, enum,,double, Int32,… Интерфейсы IComparer и IСomparable используются методами Sort. • В System.Array 8 перегрузок статического метода Sort • B System.Collections.ArrayList 3 экземплярных метода Sort Реализация System.IComparable в типах Double и Single Интерфейс IComparable реализован в типах float, double Возвращаемое значение мeтодов int CompareTo (object value) : отрицательно 0 положительно • значение вызывающего объекта меньше value ; • вызывающий объект - NaN, value – число. • значение вызывающего объекта равно value ; • и вызывающий объект, и value имеют значение NaN, бесконечность или минус бесконечность. • значение вызывающего объекта больше value ; • вызывающий объект - число, value равно NaN ; • value равно null. Реализация System.IComparable в типе string Интерфейс IComparable реализован в типе string. Сравнение выполняется с учетом регистра и текущих региональных установок (current culture). Возвращаемое значение в мeтоде int CompareTo (object value) отрицательно 0 положительно • значение вызывающего объекта меньше value ; • значение вызывающего объекта равно value ; • значение вызывающего объекта больше value ; • value равно null. Методы Sort в System.Array В System.Array определено 8 перегруженных методов Sort() для сортировки одномерных массивов. В элементах одномерного массива должен быть реализован один из интерфейсов IComparable или IComparer public static void Sort( Array array ); // сортирует массив c // использованием IComparable public static void Sort( Array array, IComparer comparer ); // сортирует c // использованием IComparer ( если comparer==null, // используется IComparable) public static void Sort ( Array array, int index, int length ); // сортирует подмножество элементов массива public static void Sort( Array keys, Array items ); // сортирует первый // массив и переставляет элементы второго в среднем // за O(nlog n) операций, значение items может быть // равно null. Класс System.Collections.ArrayList Класс ArrayList используется для работы с массивом элементов, число которых изменяется динамически. Непосредственный базовый класс – System.Object. public class ArrayList : IList, ICollection, IEnumerable, ICloneable {…} Конструкторы: public ArrayList(); public ArrayList( int capacity ); public ArrayList( ICollection c ); Объем (capacity): public virtual int Capacity {get; set;} public virtual void TrimToSize(); Методы Sort в ArrayList Сортировка всей коллекции с использованием метода CompareTo() интерфейса IComparable: public virtual void Sort(); Сортировка всей коллекции или ее части с использованием метода Compare() интерфейса IComparer: public virtual void Sort( IComparer comparer ); public virtual void Sort( int index, int count, IComparer comparer );