Подтвердить что ты не робот

Какова цель иметь имена классов между символами "Меньше чем" и "Больше, чем" на С#?

Я не понимаю следующее объявление класса:

public abstract class Class1 <TDomainServiceContract, TDomainService>
{
   ...
}

Я знаю, что TDomainServiceContract и TDomainService, но почему они используются между символами < и >?

4b9b3361

Ответ 1

Параметры между < и > являются параметрами типового типа. Generics, на очень высоком уровне, позволяют вам создать класс, который не зависит от конкретного типа одного или нескольких параметров, свойств или методов. Это немного сложно объяснить словами, но наиболее распространенное использование дженериков содержится в коллекциях.

До генериков большинство разработчиков использовали такие вещи, как ArrayList, чтобы отслеживать коллекции объектов. Недостатком этого была безопасность; потому что вы можете поместить любой object в ArrayList, а это значит, что вам нужно было вернуть объект обратно к ожидаемому типу (делая код менее чистым), и у вас не было ничего, что помешало бы вам добавить что-то, что не было такого типа (т.е. я мог бы иметь ArrayList, что я мог бы содержать только объекты string, но я мог бы - случайно - поставить int или DbConnection и т.д.), а вы 'd никогда не узнайте, пока вы не закончите выполнение.

ArrayList myStrings = new ArrayList();

myStrings.Add("foo");
myStrings.Add("bar");
myStrings.Add(1); // uh-oh, this isn't going to turn out well...

string string1 = (string)myStrings[0];
string string2 = (string)myStrings[1];
string string3 = (string)myStrings[2]; // this will compile fine but fail at 
                                       // runtime since myStrings[2] is an int, 
                                       // not a string

После введения дженериков мы получили класс List<T>. Это один класс, который принимает один общий аргумент типа, а именно тип объектов, которые вы ожидаете от списка. Таким образом, я могу иметь List<string> или List<int>, которые будут: a) не требовать кастинга, так как индексы возвращают string и int соответственно, и b) будут безопасны во время компиляции, так как я знаю, что в эти списки могут быть помещены только те string или int (опять же, соответственно).

List<string> myStrings = new List<string>();

myStrings.Add("foo");
myStrings.Add("bar");
myStrings.Add(1); // this will not compile, as an int is not a string

Точка дженериков состоит в том, чтобы сказать, что вас не волнует, каков фактический тип объекта, с которым вы работаете, но потребитель вашего класса может. Другими словами, механики того, как список может хранить string, int, a DbConnection и т.д., Являются идентичными, но generics делают это так, чтобы информация этого типа, поступающая от потребителя вашего класса, t потеряно в вашей абстракции.

Ответ 3

Это указывает на то, что при использовании класса вы можете предоставить любой тип для TDomainServiceContract, который реализует DomainContext. Поэтому допустим такой класс:

public class MyDomainContext : DomainContext
{
    ...
}

Я могу использовать этот класс при создании нового Class1 следующим образом:

var o = new Class1<MyDomainContext, MyDomainService>();

поскольку он реализует DomainContext. То же самое относится к TDomainService.

Ответ 4

Еще один способ взглянуть на это - в более простом примере. Например:

List<String> myStrings = new List<String>();
myStrings.Add("One");
//Etc.

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