Проблемы со списком, содержащим несколько типов данных

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

  • Использует дженерики с одним отложенным типом с ограничением IComparable‹>;
  • Список‹> должен быть создан (приватный), чтобы содержать объекты отложенного типа;
  • Должен быть предусмотрен метод Add(), позволяющий добавлять объекты в список‹>;
  • Метод Minimum() должен возвращать минимальное значение, хранящееся в списке‹>;
  • Метод Maximum() должен возвращать максимальное значение, хранящееся в списке‹>;
  • Метод Main() должен демонстрировать использование вашего универсального класса.

Ниже приводится моя жалкая попытка выполнить эту задачу.

Программа.cs:

using System;
using System.Collections.Generic;

namespace task_eleven_point_three
{
    class Program
    {
        static void Main(string[] args)
        {
            Generics<Type> Test = new Generics<Type>();

            Test.Add(3.1232M);
            Test.Add(1534);
            Test.Add(-74);
            Test.Add(432F);

            Console.WriteLine(Test.Maximum());
            Console.WriteLine(Test.Minimum());
        }
    }
}

Вот еще один класс, который я назвал Generics.

using System;
using System.Collections.Generic;

namespace task_eleven_point_three
{
    class Generics<T>
    {
        private List<T> _List = new List<T>();

        public TYPE Maximum<TYPE>()
            where TYPE : IComparable<TYPE>
        {
            TYPE Result = _List[0];

            for (int i = 1; i > _List.Count - 1; i++)
            {
                if (_List[i].CompareTo(Result) == 1)
                    Result = _List[i];
            }

            return Result;
        }

        public TYPE Minimum<TYPE>()
            where TYPE : IComparable<TYPE>
        {
            TYPE Result = _List[0];

            for (int i = 1; i > _List.Count - 1; i++)
            {
                if (_List[i].CompareTo(Result) == -1)
                    Result = _List[i];
            }

            return Result;
        }

        public void Add(T value)
        {
            _List.Add(value);
        }
    }
}

Вот некоторые из ошибок, которые у меня есть в настоящее время:

  • Невозможно неявно преобразовать тип "T" в "TYPE"
  • «T» не содержит определения для «CompareTo», и не удалось найти метод расширения «CompareTo», принимающий первый аргумент типа «T» (вам не хватает директивы using или ссылки на сборку?)
  • Аргументы типа для метода 'task_eleven_point_three.Generics.Maximum()' не могут быть выведены из использования. Попробуйте явно указать аргументы типа.

Я обычно не борюсь с задачами программирования, но дженерики меня действительно смущают. Если бы кто-то мог исправить мой код и сказать мне, что я сделал неправильно, я был бы очень признателен.


person SuperDicko    schedule 26.05.2014    source источник
comment
Может быть, это неуместно, но... должно ли это быть в цикле i ‹ _List.Count - 1 ???   -  person apomene    schedule 26.05.2014


Ответы (5)


Дженерики могут сбивать с толку, так что не расстраивайтесь.

В первом пункте вашего вопроса упоминается ограничение типа, которое вы еще не рассмотрели, но в данном случае это важно. Он ограничивает универсальные типы, которые вы можете использовать, так что функции максимума и минимума имеют смысл.

Структура вашего класса должна выглядеть так:

class GenericList<T> where T : IComparable<T> // <-- this is the type constraint: only allow types that implement IComparable<T>
{
    private List<T> _list = new List<T>();
    public void Add(T element)
    {
        // code for Add
    }

    public T Maximum()
    {
         // code for Maximum
    }

    public T Minimum()
    {
        // code for minimum
    }
}
person Rik    schedule 26.05.2014
comment
Я сделал все, что вы сказали, и теперь у меня нет ошибок в моем классе дженериков. Однако компилятору по-прежнему совсем не нравится мой метод Main. Добавление в список приводит к ошибке Ошибка 3. Лучший перегруженный метод, соответствующий 'task_eleven_point_three.Generics‹T›.Add(T)', имеет несколько недопустимых аргументов и не может преобразовать какой-либо тип данных в 'T'. - person SuperDicko; 26.05.2014

class Program
{
    static void Main(string[] args)
    {
        Container<int> container = new Container<int>();
        container.AddItem(4);
        container.AddItem(11);
        container.AddItem(6);

        Console.WriteLine(container.GetMaximum());

        Container<Person> container2 = new Container<Person>();
        container2.AddItem(new Person() { Age = 36 });
        container2.AddItem(new Person() { Age = 47 });
        container2.AddItem(new Person() { Age = 48 });

        Console.WriteLine(container2.GetMaximum().Age);
    }
}

public class Container<T> where T : IComparable<T>
{
    private  readonly List<T> _items = new List<T>();

    public void AddItem(T item)
    {
        _items.Add(item);
    }

    public T GetMaximum()
    {
        return _items.Max();
    }
}

public class Person : IComparable<Person>
{
    public int Age { get; set; }

    public int CompareTo(Person other)
    {
        return Age.CompareTo(other.Age);
    }
}

Посетите эту страницу: http://msdn.microsoft.com/en-us/library/ms379564%28VS.80%29.aspx

person user3636971    schedule 26.05.2014

У вас есть два разных общих параметра, TYPE и T - это совершенно отдельные аргументы, один из них принадлежит вашему классу, другой принадлежит вашим методам. Вам нужно использовать только один аргумент типа, а не два.

А также вам нужно добавить IComparable<T> к T, вы пытаетесь вызвать метод CompareTo для T, но ограничение не существует для T, вы применили его к TYPE, поэтому вы получаете следующую ошибку:

«T» не содержит определения для «CompareTo».

Измените свой код следующим образом:

class Generics<TYPE> where TYPE : IComparable<TYPE>
{ 
    private List<TYPE> _List = new List<TYPE>();

А также удалите ВСЕ ТИПЫ, которые вы указываете после имени метода:

Например, измените это:

public TYPE Minimum<TYPE>()

To:

public TYPE Minimum()

И убрать все ограничения на методы.

Кроме того, дженерики строго типизированы. Это означает, что если вы создаете Generics<int>, вы не можете добавить его к float или double без преобразования. Вы должны найти общий тип между всеми вашими типами, который в данном случае равен object, а не Type. Или используйте двойной или десятичный

person Selman Genç    schedule 26.05.2014
comment
Я изменил все T на TYPE, и я получаю эту ошибку несколько раз: Ошибка 14 Невозможно неявно преобразовать тип 'TYPE' в 'TYPE @Selman22 - person SuperDicko; 26.05.2014

Я бы предложил следующие изменения в вашем коде, которые на самом деле помогут вам понять, что вы делаете:

  • T - ваш общий параметр типа. Вам не нужен ТИП. Прежде чем продолжить, убедитесь, что вы понимаете, что такое дженерики. Проверьте эту тему: Что такое синтаксис ‹ › в C#
  • Измените имя вашего Generics<T> на что-то вроде MyList или MyCollection или... Таким образом, когда вы его читаете, он издает красивый звук, и вы можете получить представление о том, о чем ваш класс: MyList of T, MyList of int и т. д.
  • Вам нужно ограничение на IComparable<T>. Поскольку это студенческое задание, я не буду рассказывать, как это сделать, но объясню, что это значит. Наложение ограничения на параметр универсального типа T означает, что ваш T должен реализовать/расширить интерфейс/класс, указанный в ограничении. Таким образом, если бы в вашем классе было ограничение, говорящее class MyClass<T> where T : IEnumerable<char> (которое читается как MyClass of T, где T реализует IEnumerable of char), это означает, что вы НЕ сможете создать экземпляр MyList<int>, потому что ' int' не реализует IEnumerable<char>. С другой стороны, строка реализует IEnumerable<char>, и будет допустимо следующее: MyClass<string>. Кроме того, внутри вашего класса вы сможете вызывать любой метод, определенный в IEnumerable<char>, для ваших T-объектов.

Удачи!

person Edin    schedule 26.05.2014
comment
Спасибо за совет. Я переименовал класс, содержащий список, в MyList. TYPE также был полностью удален. Однако компилятору по-прежнему совсем не нравится мой метод Main. Добавление в список приводит к ошибке Ошибка 3. Лучший перегруженный метод, соответствующий 'task_eleven_point_three.Generics‹T›.Add(T)', имеет несколько недопустимых аргументов и не может преобразовать какой-либо тип данных в 'T'. Есть еще предложения? - person SuperDicko; 26.05.2014
comment
Какова ваша T, когда вы создаете MyList<T>? - person Edin; 26.05.2014
comment
На данный момент это MyList<T> Test = new MyList<T>(); я полагаю, что это неправильно. Я получаю эту ошибку дважды: Ошибка 1 Не удалось найти имя типа или пространства имен «T» (вам не хватает директивы использования или ссылки на сборку?) - person SuperDicko; 26.05.2014
comment
Вы используете T в своем классе, чтобы указать общий аргумент. Но при использовании вашего класса вы должны указать реальный тип для универсального аргумента T. Помните об ограничении, которое вы определили, и подумайте о примере, который я привел в своем ответе: я не смог бы создать экземпляр MyClass<T>, но MyClass<string> или MyClass<IEnumerable<char>> скомпилировался бы... - person Edin; 26.05.2014

В некоторых точках вы используете T, а в других вы TYPE

T для TYPE, как вы указали в объявлении класса

public void Add(T value)
{
    _List.Add(value);
}

Изменить выше на это

public void Add(TYPE value)
{
    _List.Add(value);
}

и аналогичные для других мест

person Muhammad Zaighum    schedule 26.05.2014