Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сортировка объеков 
:(
    Опции темы
Лена
Дата 24.10.2007, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 879
Регистрация: 16.8.2006

Репутация: нет
Всего: 11



Допустим есть массив пользовательских объектов:
//в Main
Car[]myAutos = new Car[5];
myAutos[0] = new Car("Rusty", 80,1);
myAutos[1] = new Car("mary", 40,234);
//и т.д.

Чтобы была возможность отсортировать методом Array.Sort(myAutos); надо добавить в класс Сar поддрежку интрефейса IComparable:

Код

public class Car: IComparable
{
.....
//Планируется сортировка по свойству carID описанному в классе Car
//Реализация метода интрефейса:
int IComparable.CompareTo(oblect obj)
  {
  Car temp = (Car)obj;
  if(this.carID > temp.carID)
  return 1;
  if(this.carID < temp.carID)
  return -1;
  else 0;
  }
.....
}

После такого объявления можно использовать Array.Sort(myAutos);

Объсните почему в классе Car надо писать так:
int IComparable.CompareTo(oblect obj)?
Можно ли заменить на:
public int CompareTo(oblect obj) ???



Это сообщение отредактировал(а) Лена - 24.10.2007, 17:48
PM MAIL   Вверх
tol05
Дата 24.10.2007, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 36
Всего: 170



Цитата(Лена @  24.10.2007,  17:43 Найти цитируемый пост)
Объсните почему в классе Car надо писать так:
int IComparable.CompareTo(oblect obj)?

потому что ты используешь явную реализацию интерфейса IComparable. Если бы ты писала 
Код

int CompareTo(oblect obj)
{
 ...
}
то тогда можно было бы использовать вызов обычного метода класса Car.CompareTo(myObj)
Но это не совсем хорошо с точки зрения полиморфизма.

Цитата(Лена @  24.10.2007,  17:43 Найти цитируемый пост)
Можно ли заменить на:
public IComparable CompareTo(oblect obj) ???

нельзя. CompareTo интерфейса IComparable должен возвращать int, а не IComparable smile Это общепринятое соглашение для стандарной сортировки (обязательное условие). 
Иначе прийдется тебе по-своему определять метод Sort(), работающий не с int, а с IComparable, в чем нет никакого смысла - это ходьба по кругу...

Если ты уберешь наследование от IComparable, тогда можешь писать... Просто создашь метод Car.CompareTo, который не имеет ничего общего с сортировкой.


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Лена
Дата 24.10.2007, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 879
Регистрация: 16.8.2006

Репутация: нет
Всего: 11



Про вовращаемое значение int я поняла и исправила, но вы уже ответили. smile 
Тогда такой вопрос:
Например есть интрефейс ICloneable он имеет метод Сlone.

Вот есть такой рабочий код:
Код

public class Point : ICloneable
{
..........
//реализация метода интерфейса
public object Clone()
{
return new Point(this.x, this.y);
}
..........
}


Почему же в этом случае автор не написал:
object ICloneable.Clone() ?

Все таки будет работать сортировка в первом коде если класс Car будет иметь один метод public int CompareTo(oblect obj) и унаследован от IComparable?

PM MAIL   Вверх
OLEG_NET
Дата 24.10.2007, 18:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 15.5.2007

Репутация: 1
Всего: 1



потому что был создан один метод Clone и он принадлежит интерфейсу ,если ты захочешь чтобы у тебя этот метод мог наследоваться в других классах ,ты должна будешь написать свой метод,так как по-умолчанию методы интерфейса невиртуальные,и тогда будешь ставить перед Clone имя интерфейса,а еще это нужно для того чтобы явно вызывать объект интерфейса 
PM MAIL   Вверх
Лена
Дата 24.10.2007, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 879
Регистрация: 16.8.2006

Репутация: нет
Всего: 11



Из того, что я поняла имя интрефейса используется при нотации метода (например, int IComparable.CompareTo(oblect obj)) только для того, чтобы в коде Main можно было вызвать такой метод только через интрефейсную ссылку. Также удобно использовать эту натацию при множественном наследовании интрефейсов с одинаковыми именами у методов, чтобы они не перекрывали друг друга.

Делаю ли я правильный вывод?:
Сортировка в первом коде будет работать и в случае такого обявления int IComparable.CompareTo(oblect obj) и в случае если это объявление будет заменено на public int CompareTo(oblect obj).  Ошибки не будет. smile 
PM MAIL   Вверх
OLEG_NET
Дата 24.10.2007, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 15.5.2007

Репутация: 1
Всего: 1



Вывод правильный! smile 
PM MAIL   Вверх
kurzon
Дата 24.10.2007, 21:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 307
Регистрация: 12.8.2007

Репутация: 0
Всего: -11



Код

using System;
using System.Collections.Generic;
using System.Text;

namespace Con_Sort
{
   


    struct Book
    {
        public Book(string author, int year)
        {
            this._year = year;
            this._author = author;
        }

        private int _year;

        public int Year
        {
            get { return this._year; }
            set { this._year = value; }
        }

        private string _author;

        public string Author
        {
            get { return this._author; }
            set { this._author = value; }
        }

        public override string ToString()
        {
            return String.Format("Название книги :{0}, Год :{1}", Author, Year);
        }
    }
 class Teenager
    {
        private static Random random = new Random();
        private static readonly string[] messages = new string[6]
            { 
                "Троесент!", 
                "Ватсон!", 
                "Фаронов!", 
                "Шилд!", 
                "Агуров!", 
                "Глинський!" 
            };

        public static string Complain()
        {
            return messages[random.Next(messages.Length)];
        }
    }

    class Program
    {
        static void PrintBookTitles(Book[] books)
        {
            foreach (Book book in books)
            {
                Console.WriteLine(book);
            }
        }

        static void Main(string[] args)
        {
            Book[] books = new Book[10];
            Random random = new Random();

            for (int i = 0; i < books.Length; i++)
            {
                books[i] = new Book(Teenager.Complain(), random.Next(2007));
            }

            PrintBookTitles(books);
            Console.ReadLine();

            Array.Sort(books, delegate(Book a, Book b)
                    {
                        return a.Year.CompareTo(b.Year);
                    });
        
            Console.WriteLine("После сортировки:");

            PrintBookTitles(books);
            Console.ReadLine();
        }

        }
    }




Это сообщение отредактировал(а) kurzon - 24.10.2007, 21:59
PM MAIL   Вверх
tol05
Дата 24.10.2007, 23:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 36
Всего: 170



kurzon ударил кодом по балаболам smile

Цитата(Лена @  24.10.2007,  18:55 Найти цитируемый пост)
Из того, что я поняла имя интрефейса используется при нотации метода (например, int IComparable.CompareTo(oblect obj)) только для того, чтобы в коде Main можно было вызвать такой метод только через интрефейсную ссылку.

не только поэтому. То, что можно вызывать из Main интерфейсную ссылку - это следствие. А причина - в том, что сами библиотеки .Net (стандартные) построены через использование указателей на интерфейсы.

Это удобно с точки зрения полиморфизма. 
Это позволяет избавится от boxing\unboxing value types - если эти типы реализуют интерфейсы..
Это обеспечивает защищенность типа, мы имеем ссылку на интерфейс - значит можем вызывать только члены интерфейса, а их немного, их тип и кол-во постоянны и не не зависят от типа, реализующего интерфейс.

Цитата(Лена @  24.10.2007,  18:55 Найти цитируемый пост)
Сортировка в первом коде будет работать и в случае такого обявления int IComparable.CompareTo(oblect obj) и в случае если это объявление будет заменено на public int CompareTo(oblect obj).  Ошибки не будет.

ошибки не будет, т.к. метод Sort требует параметр типа IComparer. Получив параметр типа Car, CLR попытается привести его к IComparer и это получится. Но это - плохой стиль, в принципе. Что такое типозащищенность? Ты можешь передать в Sort и не Сar, а что угодно, под видом object. Компилятор ошибки не заметит. Но во время выполнения, когда этот obj будет приводиться к IComparer и окажется, что этот obj не реализует интерфейса - ты получишь run time error.


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Лена
Дата 25.10.2007, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 879
Регистрация: 16.8.2006

Репутация: нет
Всего: 11



Спасибо, в общих чертах понятно: надо всегда в производном классе реализовывать интрефейсные методы через полное имя для надежности (int IComparable.CompareTo(oblect obj)).

Код автора в книге:
Код

public class Point : ICloneable
{
..........
//реализация метода интерфейса
public object Clone()
{
return new Point(this.x, this.y);
}
..........
}


Лучше так реализовывать:
Код

public class Point : ICloneable
{
..........
//реализация метода интерфейса
object ICloneable.Clone()
{
return new Point(this.x, this.y);
}
..........
}

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

Нет у меня глубоко понимание полезности интрефейсов после С++. Можно же было просто абстракные классы с абстакными методами делать и их наследовать и реализовывать в производных. Туман.  smile 

P.S.
Новая идея реализвать класс Car сразу двумя методами:


Код

public int CompareTo(Car car)//тут убрали object
{
if (this.carID > car.carID)
return 1;
if (this.carID < car.carID)
return -1;
else
return 0;
}

int IComparable.CompareTo(oblect obj)
  {
  Car temp = (Car)obj;
  if(this.carID > temp.carID)
  return 1;
  if(this.carID < temp.carID)
  return -1;
  else 0;
  }


 smile 

Это сообщение отредактировал(а) Лена - 25.10.2007, 10:13
PM MAIL   Вверх
tol05
Дата 25.10.2007, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 36
Всего: 170



Нормальная идея. 
Когда требуется безопасный CompareTo, но с параметром object - через IComparable.CompareTo

Когда работа только с Car - через
Код

public int CompareTo(Car car)

кстати, зачем код дублировать? В IComparable.CompareTo() нужно CompareTo(Car car) вызывать (раз уж приводишь объект к Car). Если что-то изменится в алгоритме сравнения, то в двух местах менять не прийдется.


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
VisualProgrammerNET
Дата 26.10.2007, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Почётный халявщик
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.10.2005
Где: Зеленоград

Репутация: 1
Всего: 6



К слову, какой алгоритм сортировки используется стандартным дотнетовским Sort()? 


--------------------
3 ГОДА НА user posted image 
PM MAIL ICQ   Вверх
Zapozidon
Дата 26.10.2007, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 26.8.2007

Репутация: нет
Всего: 1



MSDN про Sort:
Цитата

This method uses Array.Sort, which uses the QuickSort algorithm.

Другие наверняка тоже.
PM MAIL   Вверх
VisualProgrammerNET
Дата 26.10.2007, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Почётный халявщик
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.10.2005
Где: Зеленоград

Репутация: 1
Всего: 6



Да уж, метод Хоара особо быстрым не назовёшь... Надо будет учесть =)


--------------------
3 ГОДА НА user posted image 
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0780 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.