Итератор поиска элементов коллекции

137
17 ноября 2019, 06:00

Пришло время работы с интерфейсами и наступила проблема. Не понимаю как работает при определенном условии, Итератор для поиска элементов коллекции, удовлетворяющих заданному условию. Вот мой код и попытка реализовать IEnumerable:

class Program
{
    static void Main(string[] args)
    {
        List<Software> soft = new List<Software>()
            {new FreeSoftware("Adobe", "China"),
            new FreeSoftware("Illustration", "China"),
            new FreeSoftware("Vdobe", "China"),
            new FreeSoftware("Kaspersky", "China"),
            new SharewareSoftware("Dr.Web", "USA", new DateTime(2019, 03, 04), 0, 0, 6),
            new ProprietarySoftware("Avast", "Australia", new DateTime(2019, 02, 04), 0, 0, 6, 200)
        };
        Collection c = new Collection(soft);
        c.Search("Vdobe");
        Console.ReadKey();
    }
}
public abstract class Software : IComparable<Software>
{
    public string name_soft;
    public string made;
    public virtual bool can => true;
    public int CompareTo(Software soft)
    {
        Software p = soft as Software;
        if (p == null) throw new InvalidCastException();
        if (name_soft.First() > p.name_soft.First()) return 1;
        else if (name_soft.First() == p.name_soft.First()) return 0;
        else return -1;
    }
    public override string ToString()=>$"Название продукта - {name_soft} Страна производства - {made}";
    public void Search(List<Software> soft)
    {
        Console.WriteLine("\n\n\n\n ~Поиск софта который можно использовать~");
        foreach (var i in soft)
        {
            if (i.can)
            {
                Console.WriteLine($"{i.ToString()}");
            }
        }
    }
}
public class FreeSoftware : Software
{
    public FreeSoftware(string name, string made)
    {
        base.name_soft = name;
        base.made = made;
    }
    public override string ToString()
    {
        return base.ToString();
    }
    public override bool can => base.can;
}
public class SharewareSoftware : Software
{
    public DateTime date_instal;
    private int year, month, day;
    public DateTime period_free;
    public SharewareSoftware(string name, string made, DateTime date_instal, int year, int month, int day)
    {
        base.name_soft = name;
        base.made = made;
        this.date_instal = date_instal;
        this.year = year;
        this.month = month;
        this.day = day;
        period_free = date_instal.AddDays(day).AddMonths(month).AddYears(year);
    }
    public override bool can => DateTime.Now < period_free;
    public override string ToString()=>$"{base.ToString()} Дата установки {date_instal.ToString("d")} Период бесплатного использования до {period_free.ToString("d")}";
}
public class ProprietarySoftware : Software
{
    public DateTime date_instal;
    public DateTime time_use;
    private int year, month, day;
    private double price;
    public ProprietarySoftware(string name, string made, DateTime date_instal, int year, int month, int day, double price)
    {
        base.name_soft = name;
        base.made = made;
        this.date_instal = date_instal;
        this.year = year;
        this.month = month;
        this.day = day;
        time_use = date_instal.AddDays(day).AddMonths(month).AddYears(year);
        this.price = price;
    }
    public override bool can => DateTime.Now < time_use;
    public override string ToString()=> $"{base.ToString()} Дата установки {date_instal.ToString("d")} Время использования до {time_use.ToString("d")} Цена {price}";
}
public class Collection : Software,IEnumerable<Software> { 
    private List<Software> soft;
    public Collection() : this(new List<Software>()) { }
    public Collection(List<Software> soft)
    {
        this.soft = soft;
    }
    public void Add_To_Collection(Software s)=>this.soft.Add(s);
    public void Remove_To_Collection(int a) =>this.soft.RemoveAt(a);
    public void Show_Collection() {
        foreach (var i in soft)
        {
            Console.WriteLine(i.ToString());
        }
    }
    public override string ToString()=> $"Название коллекции {nameof(soft)} коллекция содержит {soft.Count} элементов";
    public void Sort()=> soft.Sort();
    public List<Software> Soft
    {
        get => soft;
    }
    public IEnumerable Search(string name)
    {
        foreach (var i in soft)
        {
            if (i.name_soft == name)
            {
                yield return i.ToString();
            }
        }
    }
    public IEnumerator<Software> GetEnumerator()
    {
        return ((IEnumerable<Software>)soft).GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable<Software>)soft).GetEnumerator();
    }
}

Я попытался реализовать, но что-то не так я сделал и не работает... Я так понял, что я не правильно понимаю, как реализовывать.. И вот ещё вопрос, что бы не создавать ещё одну тему: создать обобщённый метод с типом возврата List, который возвращает из коллекции лишь те объекты, тип которых указан в качестве обобщенного параметра метода, т. е. в качестве обобщённого параметра метода указывается тип дочернего класса, а из коллекции возвращаются только объекты указанного типа.

Answer 1

У меня получилось так

public class SoftwareCollection : ICollection<ASoftware>
{
    private List<ASoftware> _softwares = new List<ASoftware>();
    #region Реализация ICollection<T>
    public int Count => _softwares.Count;
    public bool IsReadOnly => false;
    public void Add(ASoftware item)
    {
        if (item == null)
            throw new ArgumentNullException(nameof(item));
        _softwares.Add(item);
    }
    public void Clear()
    {
        _softwares.Clear();
    }
    public bool Contains(ASoftware item)
    {
        if (item == null)
            throw new ArgumentNullException(nameof(item));
        return _softwares.Contains(item);
    }
    public void CopyTo(ASoftware[] array, int arrayIndex)
    {
        if (array == null)
            throw new ArgumentNullException(nameof(array));
        _softwares.CopyTo(array, arrayIndex);
    }
    public IEnumerator<ASoftware> GetEnumerator()
    {
        return _softwares.GetEnumerator();
    }
    public bool Remove(ASoftware item)
    {
        if (item == null)
            throw new ArgumentNullException(nameof(item));
        return _softwares.Remove(item);
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return _softwares.GetEnumerator();
    } 
    #endregion
    /// <summary>
    /// Сортировка
    /// </summary>
    public void Sort()
    {
        _softwares.Sort();
    }

    /// <summary>
    /// Получение коллекции нужного типа программ
    /// </summary>
    /// <typeparam name="T">тип программ в коллекции</typeparam>
    /// <param name="type">искомый тип программ</param>
    /// <returns>коллекции нужного типа программ</returns>
    public List<T> GetSoftwarByType<T>(Type type) where T : class
    {
        return _softwares.Where(s => s.GetType().Equals(type))
                         .Select(s => s as T)
                         .ToList();
    }
}

Работаем с этим так

class Program
{
    static void Main(string[] args)
    {
        SoftwareCollection softwares = new SoftwareCollection
        {
            new FreeSoftware("FileZilla", "США"),
            new ProprietarySoftware("Adobe Photoshop", "США",
                    DateTime.Parse("12.12.2018"), TimeSpan.FromDays(360), 3600),
            new SharewareSoftware("WinRar", "Россия",
                    DateTime.Parse("12.12.2018"), TimeSpan.FromDays(90)),
            new ProprietarySoftware("ABBYY FineReader", "Россия",
                    DateTime.Parse("06.06.2017"), TimeSpan.FromDays(360), 2800),
            new FreeSoftware("FireFox Mozilla", "США")
        };
        //
        Console.WriteLine("=====До сортировки======");
        PrintCollection(softwares);
        Console.WriteLine("========================");
        Console.WriteLine("Для продолжения нажмите Ввод...");
        Console.ReadLine();
        softwares.Sort();
        Console.WriteLine("=====После сортировки======");
        PrintCollection(softwares);
        Console.WriteLine("========================");
        Console.WriteLine("Для продолжения нажмите Ввод...");
        Console.ReadLine();

        var freeSoftwares = softwares.GetSoftwarByType<FreeSoftware>(typeof(FreeSoftware));
        Console.WriteLine("=====Только Free=====");
        foreach (var item in freeSoftwares)
        {
            Console.WriteLine(item);
        }
        Console.WriteLine("========================");
        Console.ReadKey();
    }
    private static void PrintCollection(SoftwareCollection softwares)
    {
        foreach (var software in softwares)
        {
            if (software is FreeSoftware)
            {
                Console.WriteLine((software as FreeSoftware));
            }
            else if (software is SharewareSoftware)
            {
                Console.WriteLine((software as SharewareSoftware));
            }
            else if (software is ProprietarySoftware)
            {
                Console.WriteLine((software as ProprietarySoftware));
            }
            else
            {
                Console.WriteLine(software);
            }
            Console.WriteLine();
        }
    }
}

Пример целиком можно посмотреть здесь. Рекомендую посмотреть, т.к. там еще можете подсмотреть реализацию IComparable<T>.

READ ALSO
Почему проект не запускается без sudo?

Почему проект не запускается без sudo?

Имею Ubuntu и установленный dotnet core 2Создал проект asp

166
Проблема с методом SaveChanges

Проблема с методом SaveChanges

Использую метод SaveChanges чтобы сохранить изменения, внесенные пользователем на сайтеНа локальном сервере все работает хорошо, как только загружаю...

143
Проблема с tcp-сервером c#

Проблема с tcp-сервером c#

При создании экземпляра класса InputUserInfoForm сервер принимает соединение, хотя в данном классе нет ничего для соединения с нимУже час ищу ошибку,...

158
Не могу понять как правильно писать Xpath функции

Не могу понять как правильно писать Xpath функции

Мне нужно запарсить сайт с помощью HtmlAgilityPack На сайте есть ссылки и у всех такой класс: class="css-ytumd6 e1j8zk4s1" Я не могу разобраться как правильно...

178