Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Обобщенная реализация(Generic)

62K
29 сентября 2010 года
Ringo1
3 / / 29.09.2010
Я новичок в C# и у меня возникла проблема: написал собственный класс, реализующий структуру данных двусвязного списка, а вот обобщенную реализацию,позволяющую хранить объекты написать как-то не получается... кое что есть... но кажется что нада что-то еще. Если брать определенные типы данных как int or double or char, то все вродь работает, а если мы заранее не знаем что за тип данных (ну например если есть экземпляр созданного нами классса)... как тогда определить операцию сравнения например... через интерфеысы? вот в этом что-то и проблема. Подскажите как это все делается.. вот все что написал
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication3
{
class Node<T> // реализация структуры элемента списка

{
public T Data;// хранимое в списке целое число
public Node<T> Next;// "указатель" на следующий элемент списка
public Node<T> Previous;// "указатель" на предыдущий элемент списка
}
/*==============================================================================================*/
class DoubleLinkedList<T>// реализация класса двусвязного списка
{
private int count;//количество элементов в списке
private readonly Node<T> RightBound;//правая граница списка
private readonly Node<T> LeftBound;//левая граница списка
/*=============================================================================================*/
public DoubleLinkedList()//конструктор сласса DoubleLinkedList
{
count = 0;
LeftBound = new Node<T>();//левая граница списка
RightBound = new Node<T>();// правая граница списка
LeftBound.Next = RightBound;
RightBound.Previous = LeftBound;
}
/*==============================================================================================*/
public void AddAfter(Node<T> node, T item)// добавляет узел в список после определенного узла
{
Node<T> newNode = new Node<T>();

newNode.Previous = node;
newNode.Next = node.Next;
newNode.Data = item;
node.Next.Previous = newNode;
node.Next = newNode;
count++;
}
/*=============================================================================================*/
public void Add(T item)// добавляет узел в список
{
AddAfter(LeftBound, item);
}
/*==============================================================================================*/
public bool IsEmpty()
{
if (count == 0)
return true;
else
return false;
}
/*==============================================================================================*/
public int Count()// возвращает количество элементов в списке
{
return count;
}
/*==============================================================================================*/
public int GetNumberOfElements(T num)// возвращает количество элементов в списке с заданным значением
{
int k = 0;
Node<T> CurrentNode = new Node<T>();

CurrentNode = LeftBound.Next;
for (int index = 1; index <= count; index++)
{
if (CurrentNode.Data.Equals(num))
k++;
CurrentNode = CurrentNode.Next;
}
return k;
}
/*==============================================================================================*/
public int[] GetEnumerators(T value)// возвращает все номера элементов списка со значением value, если они есть
{
int[] numerators = new int[GetNumberOfElements(value)];
int k = 0;
Node<T> CurrentNode = new Node<T>();

if (this.GetNumberOfElements(value) == 0)
{
Console.WriteLine("There are no elements with such value in the list");
return numerators;
}
CurrentNode = LeftBound.Next;
for (int index = 1; index <= count; index++)
{
if (CurrentNode.Data.Equals(value))
{
numerators[k] = index;
k++;
}
CurrentNode = CurrentNode.Next;
}
return numerators;
}
/*==============================================================================================*/
public void ListPrinting()//выводит список на экран
{
Node<T> CurrentNode = new Node<T>();

CurrentNode = RightBound.Previous;
for (int i = count; i >= 1; i--)
{
Console.Write(CurrentNode.Data + " ");
CurrentNode = CurrentNode.Previous;
}
Console.WriteLine("\n");
}
/*==============================================================================================*/
public void EraseOne(T value)//Удаляет еллемент списка со значением value
{
Node<T> CurrentNode = new Node<T>();

CurrentNode = LeftBound.Next;
if (count >= 1)
{
for (int i = 1; i <= count; i++)
{
if (CurrentNode.Data.Equals(value))
{
CurrentNode.Previous.Next = CurrentNode.Next;
CurrentNode.Next.Previous = CurrentNode.Previous;
count--;
return;
}
CurrentNode = CurrentNode.Next;
}
Console.WriteLine("Trere are no elements with the value " + value);
}
else
Console.WriteLine("The operation can't be done: list is empty ");
}
/*==============================================================================================*/
public void EraseAllOf(T value)//удаляет все элементы списка с заданным значением
{
if (GetNumberOfElements(value) == 0)
Console.WriteLine("\nThere aren't such elements in the list");
while (GetNumberOfElements(value) > 0)
EraseOne(value);
}
/*==============================================================================================*/
public void CopyTo(DoubleLinkedList<T> List2)//Копируем содержимое исходного списка в List2
{
Node<T> CurrentNode = new Node<T>();

CurrentNode = RightBound.Previous;
for (int i = count; i >= 1; i--)
{
List2.Add(CurrentNode.Data);
CurrentNode = CurrentNode.Previous;
}
}

}
2.1K
29 сентября 2010 года
Norgat
452 / / 12.08.2009
Цитата:
как тогда определить операцию сравнения например... через интерфеысы? вот в этом что-то и проблема. Подскажите как это все делается.. вот все что написал



сделай требование, чтобы T реализовывало стандартный интерфейс IComparable(T): http://msdn.microsoft.com/ru-ru/library/4d7sx9hd(VS.90).aspx

сделать это можно так:

 
Код:
class MyList<T> where T : IComparable<T>
    {
        public T t;

        public static int comp(MyList<T> obj1, MyList<T> obj2)
        {
            return obj1.t.CompareTo(obj2.t);
        }
    }


метод comp - пример использования интерфейса.

пример собственного класса реализующего IComparable(T):

 
Код:
class MyObj : IComparable<MyObj>
    {
        public string str;

        public int CompareTo(MyObj other)
        {
            return str.CompareTo(other.str);
        }
    }


ну и всё вместе:

Код:
static void Main(string[] args)
        {
            var l1 = new MyList<int> { t = 1 };
            var l2 = new MyList<int> { t = 3 };

            if (MyList<int>.comp(l1, l2) > 0)
                Console.WriteLine("l1 > l2");
            else
                Console.WriteLine("l1 <= l2");

            var s1 = new MyList<MyObj>() { t = new MyObj { str = "str" } };
            var s2 = new MyList<MyObj>() { t = new MyObj { str = "str" } };

            if(MyList<MyObj>.comp(s1,s2) == 0)
                Console.WriteLine("s1 = s2");
            else
                Console.WriteLine("s1 <> s2");

            Console.ReadLine();
        }


дальше думаю сам разберёшься, как это у себя использовать.


П.С. на будущее - используй теги CODE для оформления своего кода, иначе в твой код не будут смотреть.
62K
29 сентября 2010 года
Ringo1
3 / / 29.09.2010
Спасибо, все получилось! А насчет тегов кода учту!:)
842
04 октября 2010 года
sigmov
301 / / 16.09.2008
Цитата: Ringo1
а если мы заранее не знаем что за тип данных (ну например если есть экземпляр созданного нами классса)... как тогда определить операцию сравнения например... через интерфеысы? вот в этом что-то и проблема. Подскажите как это все делается.. вот все что написал



Для операций сравнения типов все очень просто.
В NET есть механизм автоидентификации механизмов compare и equate.

 
Код:
protected static IComparer<T> TComarer = Comparer<T>.Default;
protected static IEqualityComparer<T> TEComarer = EqualityComparer<T>.Default;


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

Пример обобщенной реализации:
Код:
public class MyList<T>
    {
        protected static IComparer<T> TComarer = Comparer<T>.Default;

        // ... Поля мои поля ... //
        protected T[] _items;

        // ... Конструктор ... //
        public MyList(params T[] items)
        {
            this._items = items.Clone() as T[];
        }

        // ... Функции ... //
        public T Max()
        {
            if (this._items.Length == 0) throw new IndexOutOfRangeException();
            else
            {
                T max = this._items[0];
                for (int i = 1; i < this._items.Length; i++)
                    if (TComarer.Compare(this._items, max) == 1)
                        max = this._items;
                return max;
            }
        }

    }


А вот для арифметических операций +, - и т.д. универсальность не так проста:
1. В NET 4 - это dynamic типизация
2. B NET 2-3 - это reflection + шаманизм, как например http://depositfiles.com/files/ujobe1mio
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог