Почему HashSet, но не установлен в С#?
Старый вопрос
Я понимаю, что С# имеет в некотором смысле типы HashSet
и set
. Я понимаю, что такое HashSet
. Но почему set
- это отдельное слово? Почему не каждый набор HashSet<Object>
?
Новый вопрос
Почему С# не имеет общего типа set
, аналогичного типу Dictionary
? С моей точки зрения, я хотел бы иметь набор со стандартным представлением/добавлением/удалением. Мне было бы все равно, реализовано ли это с помощью хэшей или чего-то еще. Итак, почему бы не создать класс классов, который фактически будет реализован как HashSet
в этой версии С#, но, возможно, несколько отличается в будущей версии?
Или почему бы не по крайней мере интерфейс ISet
?
Ответ
Спасибо всем, кто ответил ниже: ICollection
реализует многое из того, что вы ожидаете от ISet
. С моей точки зрения, ICollection
реализует IEnumerable
, в то время как для наборов не нужно перечислить --- пример: набор действительных чисел между 1 и 2 (тем более набор может генерироваться динамически). Я согласен, что это незначительное разглашение, поскольку "нормальным программистам" редко нужны несчетные множества.
Хорошо, думаю, я понял. HashSet
должен был называться set
, но слово set
зарезервировано в некотором смысле. Более конкретно, создатели архитектуры .NET хотели иметь последовательный набор (sic!) Классов для разных языков. Это означает, что каждое имя стандартного класса не должно совпадать с каким-либо ключевым словом на языках .NET. Слово set
, однако, используется в VB.NET, который на самом деле нечувствителен к регистру (это?), Поэтому, к сожалению, там нет места для маневра.
Тайна решена:)
Эпилог
Новый ответ Alex Y. ссылается на страницу
Ответы
Ответ 1
(На ваш исходный вопрос о set
был дан ответ. IIRC, "set" - это слово с самыми разными значениями на английском языке... очевидно, это влияет и на вычисления.)
Я думаю, что это хорошо, чтобы иметь HashSet<T>
с этим именем, но я, безусловно, приветствую интерфейс ISet<T>
. Учитывая, что HashSet<T>
поступает только в .NET 3.5 (что само по себе было удивительно), я подозреваю, что в конечном итоге мы получим более полную коллекцию наборов типов. В частности, эквивалент Java LinkedHashSet
, который поддерживает порядок вставки, будет полезен в некоторых случаях.
Чтобы быть справедливым, интерфейс ICollection<T>
фактически охватывает большую часть того, что вы хотите в ISet<T>
, поэтому, возможно, это не требуется. Тем не менее, вы можете утверждать, что основная цель набора (в основном это касается сдерживания и только тангенциально о возможности итерации элементов) не совсем такая же, как в коллекции. Это сложно. Фактически, действительно математический набор не может быть итерируемым или счетным - например, у вас может быть "набор действительных чисел между 1 и 2." Если бы вы имели числовой тип с произвольной точностью, счетчик был бы бесконечным, и итерация по нему не имела бы никакого смысла.
Точно так же идея "добавления" к множеству не всегда имеет смысл. Mutability - сложный бизнес при именовании коллекций: (
EDIT: Хорошо, отвечая на комментарий: ключевое слово set
никоим образом не является наследием, связанным с Visual Basic. Это операция, которая устанавливает значение свойства vs get
, которое извлекает операцию. Это не имеет ничего общего с идеей набора как операции.
Представьте, что вместо этого ключевые слова были фактически fetch
и assign
, например.
// Not real code!
public int Foo
{
fetch
{
return fooField;
}
assign
{
fooField = value;
}
}
Является ли цель понятной? Теперь реальный эквивалент этого в С# равен
public int Foo
{
get
{
return fooField;
}
set
{
fooField = value;
}
}
Итак, если вы пишете:
x = y.Foo;
который будет использовать часть свойства get
. Если вы пишете:
y.Foo = x;
который будет использовать часть set
.
Является ли это более ясным?
Ответ 2
Нет Set <T>
. Это сообщение сообщение в блоге BCL содержит много подробностей о HashSet, включая не совсем окончательное обсуждение включения хэша в название. Я подозреваю, что не всем в команде BCL понравилось решение использовать имя HashSet <T>
.
Ответ 3
Единственная причина этого - нехватка ресурсов для реализации этого идеально в .NET 3.5.
.NET 4.0 будет включать ISet, а также его новую реализацию в дополнение к HashSet - SortedSet. Проверьте предоставленные ссылки на библиотеку MSDN - они уже доступны в .NET 4.0 beta1.
Ответ 4
set
- это ключевое слово языка С#, которое существует с версии 1.0. Is используется для определения части, присваивающей значение свойства (и get
используется для реализации части, считывающей значение свойства). В этом контексте вы должны понимать слово "set" как глагол, как при установке значения.
HashSet<T>
- это особая реализация математической концепции набора. Он был впервые представлен в .NET 3.5. Это сообщение в блоге BCL Team объясняет больше о причинах этого, а также некоторые подсказки, почему имя HashSet<T>
, а не только Set<T>
: http://blogs.msdn.com/bclteam/archive/2006/11/09/introducing-hashset-t-kim-hamilton.aspx.
В случае HashSet<T>
вы должны понимать слово "set" как существительное.
Ответ 5
Установить зарезервированное ключевое слово в VB.NET(это эквивалентно набору в С#). VB.NET может использовать классы/методы/etc с тем же именем, что и ключевые слова, но они должны быть написаны между квадратными скобками, что уродливо:
Imports Wintellect.PowerCollections 'PowerCollections contains a class called Set'
Public Class Test
Private _myValue As Integer
Public Property MyValue() As Integer
Get
Return _myValue
End Get
Set ' Set as keyword'
_myValue = value
End Set
End Property
Public Function X As [Set](Of Integer)
Dim a As New [Set](Of Integer) ' Set as class'
Return a
End Function
End Class
Ответ 6
Ах, я понимаю ваш вопрос сейчас
Не уверен, что я могу на 100% увидеть потребность в ISet<T>
.
Я думаю, вопрос в том, что вы видите как существенное поведение для набора?
Это Add, Remove, Contains и т.д. Если это так, то ICollection<T>
уже предоставляет интерфейс для этого.
Если он устанавливает такие операции, как Union, Intersect и т.д., То это то, что вы считаете достаточно общим, чтобы абстрагироваться от принудительного исполнения контракта?
Я должен сказать, что я не знаю правильного ответа на этот вопрос - я думаю, что он открыт для обсуждения, и я подозреваю, что команда BCL может положить что-то подобное в будущей версии, но это зависит от них. Я лично не вижу в нем массивной недостающей части функциональности
Оригинальное сообщение
У BCL нет коллекции Set вообще, по крайней мере, насколько я знаю.
Там есть несколько сторонних Set libs, например Iesi.Collections
HashSet<T>
был введен в .NET 3.5 для создания быстрой коллекции наборов, в которой вы хотите получить коллекцию без дубликатов. Он также имеет типичные операции с множеством, такие как Union и Join.
Проверьте эту ссылку из команды BCL на HashSet
Обычно вы используете его, где ранее вам приходилось использовать List<T>
и проверять дубликаты при добавлении.
Добавление элементов в HashSet<T>
также может значительно быстрее, чем List
Дополнительная информация:
Еще одна приятная особенность HashSet заключается в том, что она не генерирует исключение, если вы пытаетесь добавить дубликат, просто не удается добавить дублируемую запись, которая избавляет вас от необходимости добавлять много блоков try.catch вокруг каждого add - nice:)
Ответ 7
Я уверен, что в BCL нет класса Set<T>
, по крайней мере, в .NET 3.5 (а не .NET 4.0). Что бы вы ожидали, так это необходимость в таком классе?
HashSet<T>
сама по себе является обычной структурой данных, которая использует хэш-коды (метод GetHashCode
объекта) для сравнения элементов. Это просто эффективный способ реализации заданного типа. (Другие методы проверки равенства, вероятно, будут иметь более низкую производительность.)