Будет ли работать этот код одинаково (универсальный класс с ограничением базового класса по сравнению с неродовым классом «аналог»)

#c# #generics #interface #implementation

#c# #общие #интерфейс #реализация

Вопрос:

Я тестирую реализацию интерфейса IComparer для моего инвентаря классов. У меня есть две версии его реализации, будет ли это работать одинаково? (Вопрос 1)

 class Inventory
{
    public string name;
    double cost;
    int onhand;
    public Inventory(string n, double c, int h)
    { //...    }
    }
}
class CustomInvComparer : IComparer<Inventory>
    {
        public int Compare(Inventory x, Inventory y)
        {
            return string.Compare(x.name, y.name, StringComparison.Ordinal);
        }
    }
class CompInv<T> : IComparer<T> where T : Inventory
    {
        public int Compare(T x, T y)
        {
            return string.Compare(x.name, y.name, StringComparison.Ordinal);
        }
    }
  

И почему в случаях реализации интерфейса IComparer для int32 и для string не работают «вторые варианты» (без комментария будет основной ошибкой CS0701). Я знаю, что «вторые варианты» (прокомментированные) неверны с точки зрения синтаксиса «Ограничения на параметры типа (руководство по программированию на C #)», но я не вижу логической разницы с предыдущим вариантом «где T: Инвентаризация»? (Вопрос 2)

     class CustomStringComparer : IComparer<System.String>
{
    public int Compare(System.String x, System.String y)
    {
        return x.CompareTo(y);
    }
}

//class CompStr<T> : IComparer<T> where T : System.String
//{
//    public int Compare(T x, T y)
//    {
//        return string.Compare(x, y, StringComparison.Ordinal);
//    }
//}

class CustomIntComparer : IComparer<System.Int32>
{
    public int Compare(System.Int32 x, System.Int32 y)
    {
        return x.CompareTo(y);
    }
}

//class CompStr<T> : IComparer<T> where T : System.Int32
//    {
//    public int Compare(T x, T y)
//    {
//        return string.Compare(x, y, StringComparison.Ordinal);
//    }
//}
  

Комментарии:

1. Взгляните на это

2. Я писал ранее «»вторые варианты» (прокомментированные) неверны с точки зрения синтаксиса». Мои вопросы — почему это сделано так? И при добавлении что дает «where T: struct»

3. Пожалуйста, задавайте по одному вопросу за раз. Пожалуйста, также убедитесь, что каждый задаваемый вами вопрос ясен .

4. @PeterDuniho Хорошо, я упрощаю — я снимаю дополнительные вопросы. Два вопроса, связанных один с другим. Это нормально?

Ответ №1:

У меня есть две версии его реализации, будет ли это работать одинаково? (Вопрос 1)

Две ваши IComparer<T> реализации имеют точно такую же логику, так что в этом смысле они будут работать точно так же. Единственное существенное отличие заключается в том, что универсальная версия будет работать не только для сравнения типов Inventory , но и для любого подкласса Inventory . Также.

Поскольку из-за различия параметров типа в универсальных интерфейсах вы можете использовать неродовую версию в сценариях, где используется Inventory подкласс, это различие не имеет большого практического значения. Вы должны быть в состоянии использовать любой из них в точно таких же ситуациях.

Что касается вашего второго вопроса:

И почему в случаях реализации интерфейса IComparer для int32 и для string не работают «вторые варианты» (без комментария будет основной ошибкой CS0701)

Ответ на это прямо в сообщении об ошибке:

Тип, используемый в качестве ограничения, должен быть интерфейсом, незапечатанным классом или параметром типа.

System.String это закрытый класс, и System.Int32 это вообще не класс. Ни один из них не является параметром интерфейса или типа. Таким образом, ни один из них не квалифицируется как ограничение.

Говоря более практически: причина, по которой закрытые классы и типы значений (структуры, т. Е. что-то вроде System.Int32 ) не являются допустимыми ограничениями, заключается в том, что они не имели бы никакого смысла в качестве ограничения. Ограничение позволяет параметру type быть типом, который наследует тип ограничения. Но закрытые классы и типы значений не могут иметь унаследованных типов. Таким образом, использование их в качестве ограничения дало бы нулевую выгоду. В таких ситуациях вам было бы лучше опустить параметр type и использовать этот тип явно.