2008-09-30 2 views
6

я узнавал об основах C#, но не встретилось хорошее объяснение того, что это:Что такое «< >» синтаксис в C#

var l = new List<string>(); 

Я не знаю, что <string> делает или если это List, что делает магию. Я также видел, что объекты были выброшены в теги < >.

Может кто-нибудь объяснить это мне примерами, пожалуйста?

ответ

24

Это общий синтаксис для C#.

Основная концепция заключается в том, что она позволяет использовать заполнитель Type и подставлять действительный тип во время компиляции.

Например, старый способ:

ArrayList foos = new Arraylist(); 
foos.Add("Test"); 

работал путем ArrayList хранения списка System.Objects (Базовый тип для всех вещей, .NET).

Таким образом, при добавлении или извлечения объекта из списка, CLR бы бросить его на объект, в основном то, что на самом деле это происходит:

foos.Add("Test" as System.Object); 
string s = foos[1] as String. 

Это приводит к потере производительности от отливки, и ее также небезопасно, потому что я могу это сделать:

ArrayList listOfStrings = new ArrayList(); 
listOfStrings.Add(1); 
listOfStrings.Add("Test"); 

Это будет компилировать просто отлично, даже если я кладу целое число в listOfStrings.

Обобщения изменил все это, теперь с помощью Generics я могу объявить, что тип моей коллекции ожидает:

List<int> listOfIntegers = new List<int>(); 
List<String> listOfStrings = new List<String>(); 

listOfIntegers.add(1); 

// Compile time error. 
listOfIntegers.add("test"); 

Это обеспечивает время компиляции типобезопасность, а также позволяет избежать дорогостоящих операций литья.

Способ, которым вы пользуетесь, довольно прост, хотя есть некоторые усовершенствованные граничные случаи. Основная концепция заключается в том, чтобы сделать ваш тип типа агностиком с помощью заполнителя типа, например, если бы я хотел создать общий класс «Добавить два вещи».

public class Adder<T> 
{ 
    public T AddTwoThings(T t1, T t2) 
    { 
     return t1 + t2; 
    } 
} 

Adder<String> stringAdder = new Adder<String>(); 
Console.Writeline(stringAdder.AddTwoThings("Test,"123")); 

Adder<int> intAdder = new Adder<int>(); 
Console.Writeline(intAdder.AddTwoThings(2,2)); 

Для более подробного объяснения дженериков я не могу рекомендовать книгу CLR с помощью C#.

1

Это .NET Generics. Тип в пределах <> обозначает тип элемента, содержащегося в списке.

с ArrayList вы должны отбрасывать элементы внутри ...

int x = (int)myArrayList[4]; 

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

int x = myList[4]; 

Дженерики доступны в .NET 2.0 и новее.

1

Это дженерики. Вы создаете список, содержащий только строки. Вы также можете сказать

List<int> 

и получить список, который содержит только int.

Дженерики - огромная тема, слишком большая для одного ответа здесь.

+0

Спасибо за это, и я отредактировал вопрос – 2008-09-30 22:01:33

+0

NP. Я также удалил свое предложение. В отверстие памяти они уходят. – 2008-09-30 22:02:43

5

Это дженерики - это форма типа параметризация. В вашем примере это означает, что l относится к списку строк - список будет содержать только строки: компилятор относится к нему (в значительной степени), как если бы везде, где API docs упоминает «T», на самом деле он говорит «строка». Таким образом, вы можете добавлять к нему только строки, и если вы используете индексатор, вам не нужно указывать на строку и т. Д.

Чтобы быть честным, предоставление подробных сведений о дженериках в онлайн-форуме практически невозможно. (В C# in Depth я беру около 50 страниц, рассказывающих о дженериках.) Однако, вооружившись именем функции, вы должны быть в гораздо лучшем положении, чтобы узнать больше. MSDN "Introduction to C# Generics", вероятно, является хорошей отправной точкой.

Задавать конкретные вопросы о дженериках на SO, скорее всего, даст хорошие результаты - я просто не думаю, что это действительно можно правильно рассмотреть в одном вопросе/ответе.

+0

Спасибо, хороший ответ. – 2008-09-30 22:04:22

1

Это дженерики в действии. Обычный список хранит элементы типа Object. Это требует литья между типами. Это также позволит вам хранить любой элемент в одном экземпляре списка. Когда вы повторяете элементы в этом списке, вы не можете быть уверены, что все они имеют определенный тип (по крайней мере, без литья каждого элемента). Например позволяет сказать, что вы создаете список, как это:

List listOfStrings = new List(); 

Ничто не мешает кому-то делать что-то вроде этого:

listOfStrings.add(6); //Not a string 

Общий список позволит вам указать строго типизированные список.

List<string> listOfStrings = new List<string>(); 
listOfStrings.add("my name"); //OK 
listofStrings.add(6); //Throws a compiler error 

Существует более тщательные примеры здесь Generics

0

<> для дженериков. В вашем конкретном примере это означает, что List представляет собой список строк, а не список INT.

Дженерики используются, чтобы обеспечить тип, ну, общий. Он используется ALOT в коллекциях, чтобы позволить им принимать разные типы, чтобы они могли функционировать как обычный массив и по-прежнему улавливать недопустимые типы, назначаемые во время компиляции. В основном это позволяет классу сказать: «Мне нужно быть связанным с определенным типом T, но я не хочу жестко кодировать именно этот тип и позволять пользователю выбирать его».Простой массив, например, может выглядеть примерно так:

public class MyArray<T> { 
    private T[] _list; 

    public MyArray() : this.MyArray(10); 
    public MyArray(int capacity) 
    { _list = new T[capacity]; } 

    T this[int index] { 
     get { return _list[index]; } 
     set { _list[index] = value; } 
    } 
} 

Здесь мы имеем частный список типа Т, доступ к которому с помощью нашего класса, как обычный массив. Нам все равно, что это такое, это не имеет значения для нашего кода. Но любой, кто использует класс, может использовать его, например, MyArray<string>, чтобы создать список строк, в то время как кто-то другой может использовать его как MyArray<bool> и создать список флагов.

Смежные вопросы