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

Почему 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. ссылается на страницу

4b9b3361

Ответ 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 объекта) для сравнения элементов. Это просто эффективный способ реализации заданного типа. (Другие методы проверки равенства, вероятно, будут иметь более низкую производительность.)