Почему HashSet, но не установлен в C #? - PullRequest
24 голосов
/ 21 июня 2009

Старый вопрос

Насколько я понимаю, C # в некотором смысле имеет типы HashSet и set. Я понимаю, что такое HashSet. Но почему set это отдельное слово? Почему не каждый набор HashSet<Object>?

Новый вопрос

Почему C # не имеет общего типа Set, аналогичного типу Dictionary? С моей точки зрения, я хотел бы иметь набор со стандартной производительностью поиска / добавления / удаления. Мне было бы все равно, реализовано ли это с помощью хэшей или как-то еще. Так почему бы не создать класс набора, который на самом деле был бы реализован как HashSet в этой версии C #, но, возможно, несколько отличался бы в будущей версии?

Или почему бы не по крайней мере интерфейс ISet?

Ответ

Узнал спасибо всем, кто ответил ниже: ICollection реализует многое из того, что вы ожидаете от ISet. С моей точки зрения, однако, ICollection реализует IEnumerable, в то время как наборы не должны быть перечисляемыми --- пример: набор действительных чисел от 1 до 2 (даже больше, наборы могут генерироваться динамически). Я согласен, что это небольшая разглагольствование, поскольку «нормальным программистам» редко нужны бесчисленные множества.

Хорошо, я думаю, что понял. HashSet должен был называться Set, но слово Set в некотором смысле зарезервировано. В частности, создатели архитектуры .NET хотели иметь согласованный набор (sic!) Классов для разных языков. Это означает, что каждое имя стандартного класса не должно совпадать ни с одним ключевым словом в языках .NET. Однако слово Set используется в VB.NET, который фактически не учитывает регистр (не так ли?), Поэтому, к сожалению, там нет места для маневра.

Тайна разгадана:)

Эпилог

Новый ответ Алекса Y. ссылается на страницу MSDN , которая описывает предстоящий интерфейс .NET 4.0 ISet, который ведет себя так, как я думал, и должен быть реализован на HashedSet. Счастливый конец.

Ответы [ 7 ]

19 голосов
/ 21 июня 2009

(На ваш первоначальный вопрос о set был дан ответ. IIRC, "set" - это слово с самыми разными значениями в английском языке ... очевидно, это также влияет на вычисления.)

Я думаю, что хорошо иметь HashSet<T> с таким именем, но я бы, конечно, приветствовал ISet<T> интерфейс. Учитывая, что HashSet<T> появился только в .NET 3.5 (что само по себе было удивительно), я подозреваю, что в конечном итоге мы можем получить более полную коллекцию типов на основе множеств. В частности, эквивалент Java LinkedHashSet, который поддерживает порядок вставки, был бы полезен в некоторых случаях.

Если честно, интерфейс ICollection<T> фактически покрывает большую часть того, что вы хотели бы в ISet<T>, так что, возможно, это не требуется. Тем не менее, вы можете утверждать, что основная цель набора (который главным образом связан с защитой и только косвенно заключается в возможности перебирать элементы) не совсем совпадает с коллекцией. Это сложно. На самом деле, действительно математический набор не может быть итеративным или счетным - например, у вас может быть «набор действительных чисел от 1 до 2». Если бы у вас был числовой тип с произвольной точностью, счет был бы бесконечным, и повторение по нему не имело бы никакого смысла.

Точно так же идея «добавления» к набору не всегда имеет смысл. Изменчивость - сложная задача при именовании коллекций: (* ​​1014 *

РЕДАКТИРОВАТЬ: Хорошо, отвечая на комментарий: ключевое слово set никоим образом не является наследием Visual Basic. Это операция, которая устанавливает значение свойства, а не get, которая возвращает операцию. Это не имеет ничего общего с идеей множества как операции.

Представьте себе, что вместо этого ключевые слова на самом деле были fetch и assign, например,

// Not real code!
public int Foo
{
    fetch
    {
        return fooField;
    } 
    assign
    {
        fooField = value;
    } 
}

Цель ясна там? Теперь реальный эквивалент этого в C # равен

public int Foo
{
    get
    {
        return fooField;
    } 
    set
    {
        fooField = value;
    } 
}

Так что если вы напишите:

x = y.Foo;

, который будет использовать get часть свойства. Если вы напишите:

y.Foo = x;

, который будет использовать set part.

Это понятнее?

5 голосов
/ 21 июня 2009

Единственной причиной этого кажется отсутствие ресурсов для идеальной реализации этого в .NET 3.5.

.NET 4.0 будет включать ISet , а также его новую реализацию в дополнение к HashSet - SortedSet . Проверьте предоставленные ссылки на библиотеку MSDN - они уже доступны в .NET 4.0 beta1.

5 голосов
/ 21 июня 2009

Нет набора <T>. В этом блоге BCL team есть много подробностей о HashSet, включая не совсем убедительное обсуждение включения хэша в название. Я подозреваю, что не всем в команде BCL понравилось решение использовать имя HashSet <T>.

4 голосов
/ 21 июня 2009

set - ключевое слово языка C #, существующее с версии 1.0. Is используется для определения присваивающей значение части свойства (а get используется для реализации считывающей значение части свойства). В этом контексте вы должны понимать слово «набор» как глагол, как при установке значения.

HashSet<T> является конкретным воплощением математической концепции Сета. Впервые он был представлен в .NET 3.5. Это сообщение в блоге команды BCL объясняет больше о причинах этого, а также некоторые подсказки, почему имя HashSet<T>, а не просто Set<T>: http://blogs.msdn.com/bclteam/archive/2006/11/09/introducing-hashset-t-kim-hamilton.aspx.

В случае HashSet<T> вы должны понимать слово «набор» как существительное.

3 голосов
/ 21 июня 2009

Set является зарезервированным ключевым словом в VB.NET (это эквивалентно установке в C #). VB.NET может использовать классы / методы / и т. Д. С тем же именем, что и ключевые слова, но они должны быть записаны в квадратных скобках, что ужасно:

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
2 голосов
/ 21 июня 2009

Ах, хорошо, теперь я понимаю ваш вопрос
Не уверен, что смогу на 100% увидеть необходимость ISet<T>.
Я предполагаю, что вопрос в том, какое поведение вы считаете важным для набора?
Добавить, удалить, содержит и т. Д. Если так, то ICollection<T> уже предоставляет интерфейс для этого.
Если это такие операции над множествами, как Union, Intersect и т. Д., Тогда это то, что вы считаете достаточно универсальным, чтобы абстрагироваться от применения стиля контракта?

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

Оригинальный пост

BCL вообще не имеет коллекции Set, по крайней мере, насколько я знаю.
Есть несколько сторонних наборов, таких как Iesi.Collections
HashSet<T> была введена в .NET 3.5 для создания коллекции быстрых наборов, т.е. там, где вы хотите коллекцию без дубликатов. Он также имеет типичные операции над множествами, такие как объединение и соединение. Проверьте эту ссылку от команды BCL на HashSet

Обычно вы используете его там, где ранее вам приходилось использовать List<T>, и проверяете наличие дубликатов при добавлении.
Добавление элементов в HashSet<T> также может быть значительно быстрее , чем список

Некоторые дополнительные сведения:
Еще одна приятная особенность HashSet заключается в том, что он не выдает исключение, если вы пытаетесь добавить дубликат, просто не удается добавить дублирующую запись, что избавляет вас от необходимости помещать множество блоков try.catch вокруг каждого добавления - nice:)

0 голосов
/ 21 июня 2009

Я почти уверен, что в BCL нет класса Set<T>, по крайней мере, в .NET 3.5 (и, кажется, не .NET 4.0). Во всяком случае, чего бы вы ожидали от такого класса?

HashSet<T> сама по себе представляет собой обычную структуру данных набора, которая использует хэш-коды (метод GetHashCode объекта) для сравнения элементов. Это просто эффективный способ реализации набора типа. (Другие методы проверки равенства, вероятно, будут иметь более низкую производительность.)

...