#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 и использовать этот тип явно.