Вторая половина ответов на вопросы (987661), страница 8
Текст из файла (страница 8)
abstract class Shape
{ /* Создается абстрактный класс, наличие abstract обязательно! */
public int a,h;
public Shape (int x,int y)
{…}
public abstract void Show_area();// реализация не нужна – метод абстрактный, фиксируется лишь интерфейс метода
}
class Tri:Shape
{
int s;
public Tri(int x, int y) :base(x, y)
{…}
public override void Show_area()
{…}
}
class Square:Shape
{
int s;
public Square(int x, int y):base(x, y)
{…}
public override void Show_area()
{…}
}
class Class1
{
static void Main(string[] args)
{
Shape q; //указатель на абстрактный класс
// q=new Shape(4,6); это ошибка, нельзя создать объект
// абстрактного класса!
q = new Tri(10,20);
q.Show_area();
q = new Square(10,20);
q.Show_area();
Console.ReadLine();
} } }
Указатель на абстрактный класс может указывать на любой класс-наследник.
65. Класс List, создание и работа с классом List с нестандартными элементами
Представляет строго типизированный список объектов, доступных по индексу. Поддерживает методы для поиска по списку, выполнения сортировки и других операций со списками.
Класс List<T> является универсальным эквивалентом класса ArrayList. Он реализует универсальный интерфейс IList<T> с помощью массива, размер которого динамически увеличивается по мере необходимости.
Класс List<T> использует компаратор проверки на равенство и компаратор упорядочения.
Такие методы, как Contains, IndexOf, LastIndexOf и Remove, используют компаратор проверки на равенство для элементов списка. Компаратор проверки на равенство, используемый по умолчанию для типа T, определяется следующим образом. Если тип T реализует универсальный интерфейс IEquatable<T>, в качестве компаратора проверки на равенство используется метод Equals(T) этого интерфейса; в противном случае по умолчанию используется метод Object.Equals(Object).
Такие методы, как BinarySearch и Sort, используют компаратор упорядочения для элементов списка. Компаратор, используемый по умолчанию для типа T, определяется следующим образом. Если тип T реализует универсальный интерфейс IComparable<T>, в качестве компаратора по умолчанию используется метод CompareTo(T) этого интерфейса; в противном случае, если тип T реализует неуниверсальный интерфейс IComparable, в качестве компаратора по умолчанию используется метод CompareTo(Object) этого интерфейса. Если тип T не реализует ни один из интерфейсов, компаратор по умолчанию не определяется; в этом случае компаратор или делегат сравнения должен быть задан явным образом.
Сортировка списка List<T> не гарантируется. Необходимо отсортировать List<T> до выполнения операций (таких, как BinarySearch), для которых требуется отсортированный список List<T>.
Доступ к элементам этой коллекции осуществляется с помощью целочисленного индекса. Индексы в этой коллекции начинаются с нуля.
Список List<T> принимает null в качестве допустимого значения для ссылочных типов и разрешает дублирование элементов.
Делая выбор между классами List<T> и ArrayList, предлагающими сходные функциональные возможности, следует помнить, что класс List<T> в большинстве случаев обрабатывается быстрее и является потокобезопасным. Если в качестве типа T класса List<T> используется ссылочный тип, оба класса действуют идентичным образом. Однако если в качестве типа T используется тип значений, необходимо принять во внимание особенности, связанные с реализацией и упаковкой.
В следующем примере кода демонстрируются несколько свойств и методов универсального класса List<T>. С помощью конструктора по умолчанию создается список строк с емкостью по умолчанию. Выводится значение свойства Capacity, а затем с помощью метода Add добавляется несколько элементов. Выводится список этих элементов, а затем снова выводится значение свойства Capacity и вместе с ним — значение свойства Count, показывающее, что емкость увеличивается по мере необходимости.
С помощью метода Contains проверяется наличие некоторого элемента в списке, с помощью метода Insert в середину списка вставляется новый элемент, после чего снова выводится содержимое списка.
С помощью свойства по умолчанию Item (индексатор в C#) из списка извлекается элемент, с помощью метода Remove удаляется первый экземпляр дублированного элемента, добавленный ранее, и содержимое списка выводится вновь. Метод Remove всегда удаляет первый обнаруженный им экземпляр.
С помощью метода TrimExcess емкость уменьшается в соответствии с числом элементов, и выводятся значения свойств Capacity и Count. Если незадействованная емкость составляет менее 10% от общей емкости, изменение размера списка не требуется.
В заключение используется метод Clear для удаления всех элементов из списка, и выводятся значения свойств Capacity и Count.
using System;
using System.Collections.Generic;
public class Example
{
public static void Main()
{
List<string> dinosaurs = new List<string>();
Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);
dinosaurs.Add("Tyrannosaurus");
dinosaurs.Add("Amargasaurus");
dinosaurs.Add("Mamenchisaurus");
dinosaurs.Add("Deinonychus");
dinosaurs.Add("Compsognathus");
Console.WriteLine();
foreach(string dinosaur in dinosaurs)
{
Console.WriteLine(dinosaur);
}
Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);
Console.WriteLine("Count: {0}", dinosaurs.Count);
Console.WriteLine("\nContains(\"Deinonychus\"): {0}",
dinosaurs.Contains("Deinonychus"));
Console.WriteLine("\nInsert(2, \"Compsognathus\")");
dinosaurs.Insert(2, "Compsognathus");
Console.WriteLine();
foreach(string dinosaur in dinosaurs)
{
Console.WriteLine(dinosaur);
}
Console.WriteLine("\ndinosaurs[3]: {0}", dinosaurs[3]);
Console.WriteLine("\nRemove(\"Compsognathus\")");
dinosaurs.Remove("Compsognathus");
Console.WriteLine();
foreach(string dinosaur in dinosaurs)
{
Console.WriteLine(dinosaur);
}
dinosaurs.TrimExcess();
Console.WriteLine("\nTrimExcess()");
Console.WriteLine("Capacity: {0}", dinosaurs.Capacity);
Console.WriteLine("Count: {0}", dinosaurs.Count);
dinosaurs.Clear();
Console.WriteLine("\nClear()");
Console.WriteLine("Capacity: {0}", dinosaurs.Capacity);
Console.WriteLine("Count: {0}", dinosaurs.Count);
}
66. Принципы построения языка LINQ.
Базовыми единицами данных в LINQ являются последовательности и элементы. Последовательность – это любой объект, который реализует обобщенный интерфейс IEnumerable, а элемент – это просто элемент последовательности. В следующем примере массив строк names – это последовательность, а Tom, Dick и Harry – элементы:
string[] names = {“Tom”, “Dick”, “Harry” };
Такая последовательность называется локальной, потому что представляет локальную коллекцию объектов в памяти.
Оператор запроса – это метод, преобразующий последовательность. В типичном случае оператор запроса принимает входную последовательность и возвращает результат преобразования – выходную последовательность. В классе Enumerable из пространства имен System.Linq имеется около 40 операторов запроса, и все они реализованы как статические методы расширения. Они называются стандартными операторами запроса.
Запрос – это выражение, которое преобразует последовательности с помощью операторов запроса. Простейший запрос состоит из одной входной последовательности и одного оператора. Например, мы может применить оператор Where к строковому массиву и извлечь те его элементы, длина которых не меньше четырех символов:
string[] names = {“Tom”, “Dick”, “Harry” };
IEnumerable<string> filteredNames = System.Linq.Enumerable.Where (names, n => n.Length >= 4);
foreach (string n in filteredNames)
Console.Write(n+”|”); //Dick|Harry|
Поскольку стандартные операторы запроса реализованы в виде методов расширения, мы можем вызвать Where непосредственно для массива names так, словно это метод экземпляра:
IEnumerable<string> filteredNames = names.Where (n => n.Length >= 4);
Чтобы можно было откомпилировать эту строчку, вы должны импортировать пространство имен System.Linq. Вот полный код примера:
using System;
using System.Linq;
class LinqDemo {
static void Main() {
string[] names = {“Tom”, “Dick”, “Harry” };
IEnumerable<string> filteredNames = names.Where (n => n.Length >= 4);
foreach (string name in filteredNames) Console.Write (name+ “|”);
}} // Результат: Dick|Harry|
Мы могли бы еще больше сократить запрос с помощью неявного приведения типа переменной filteredNames:
var filteredNames = names.Where (n => n.Length >= 4);
Большинство операторов запроса принимает лямбда-выражение в качестве аргумента. Лямбда-выражение помогает направить и сформировать запрос. В нашем примере лямбда-выражение выглядит так:
n => n.Length >= 4.
Входной аргумент соответствует входному элементу. В этом случае аргумент n представляет имя в массиве и имеет тип string. Оператор Where требует, чтобы лямбда-выражение возвращало значение типа bool. Когда оно истинно, элемент должен быть включен в исходную последовательность.
Такие запросы называются лямбда-запросами. В языке C# имеется специальный синтаксис для написания запросов, и он называется синтаксисом, облегчающим восприятие запроса. Предыдущий пример, переписанный в соответствии с эти синтаксисом: