Есть ли какие-либо наборы в.NET, которые предотвращают пустые записи?

Я конкретно думаю о наборе, который выполняет контракт набора, но я думаю, что вопрос может относиться к любому виду. Есть ли наборы в платформе.NET, которые предотвращают пустые записи? Определенное поведение, которое я хочу, является этим:

var set = new HashSet<object>();
bool added = set.Add(null);
Console.WriteLine(added); // prints "False"

Это не поведение встроенного HashSet<T>. Есть ли какие-либо наборы, которые действительно имеют это (или подобный) поведением, или действительно ли я - более обеспеченная прокрутка мое собственное? Если последний, что лучший способ состоит в том, чтобы пойти об этом? Если я наследовался непосредственно HashSet<T> или просто оберните его?

Править: Чтобы быть ясным, это - просто неактивное удивление. Главным образом, потому что я не могу думать ни о какой причине, я когда-либо хотел бы позволить null в ряд объектов. У меня нет никакой конкретной потребности в этом.

15
задан Sean Devlin 2 February 2010 в 18:44
поделиться

8 ответов

Нет такого встроенного класса, как HashSet , за исключением этого единственного поведения.

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

Просто инкапсулируйте HashSet и предоставьте необходимые вам элементы. Единственный реальный «код», который вам нужно добавить, - это одна проверка на null для метода Add - в противном случае просто передайте все методы инкапсулированному экземпляру.

Если вы хотите, чтобы это был общий класс, вам нужно добавить дополнительное ограничение для работы только с классами, поскольку вы хотите иметь нулевую проверку:

public class ValueSet<T> : ICollection<T>, IEnumerable<T>, ICollection
    where T : class
{
     private HashSet<T> hashSet = new HashSet<T>();
     // ... Implement all members as needed...
12
ответ дан 1 December 2019 в 02:55
поделиться

А как насчет написания метода расширения для HashSet. Это может быть проще всего.

public static class HashSetExtensions
{
    public static bool AddNonNull<T>(this HashSet<T> set, T item)
        where T : class
    {
        if (item == null)
            return false;

        return set.Add(item);
    }
}

Затем вы можете сделать это:

HashSet<object> test = new HashSet<object>();
test.AddNonNull(null); //Will return false;
7
ответ дан 1 December 2019 в 02:55
поделиться

В любом случае, вы можете использовать кодовые контракты в .NET 4.0 для предотвращения NULL значений, которые будут добавлены в коллекцию. Таким образом, вы также получите проверку времени компиляции, правильный ли код (используя статический анализ, предусмотренный кодом договоров):

public class MyClass {
  private List<Something> nonNullList;

  [ContractInvariantMethod]
  void NonNullEntries() {
    Contract.Invariant(Contract.ForAll(nonNullList, el => el != null));
  }

  public void Add(Something el) {
    Contract.Requires(el != null);
  }

}

Способ, отмеченный ContractInvariTMethod Указывает состояние, которое должно быть В любое время держится (нет null элементов в списке). Я считаю, что статический анализ не может рассуждать об этом (из-за Forall ), но я могу ошибиться. Тем не менее, это, безусловно, может проверить, вы вызываете добавить методом с правильными (ненутренными) аргументами.

0
ответ дан 1 December 2019 в 02:55
поделиться

Поскольку вы отметили этот вопрос с помощью generics , я полагаю, вы ищете общую коллекцию. Такой коллекции не существует в платформе .NET просто потому, что типы значений не могут быть null , поэтому я думаю, вам придется откатить свой собственный, добавив ограничение ограничения на общий тип, который он принимает.

3
ответ дан 1 December 2019 в 02:55
поделиться

A System.Collections.Generics.Dictionary не позволяет добавлять null для TKey (вызывает исключение). Вам придется проигнорировать TValue s тогда в вашем сценарии, если вы собираетесь использовать его таким образом, и функциональность будет аналогична Hashset , за исключением причудливого набора операции конечно.

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

2
ответ дан 1 December 2019 в 02:55
поделиться

Два варианта:

Edit: Извините, я пропустил, что ему нужен набор, а не коллекция. По крайней мере, предпочтительный элемент, который я перечислил, все еще действителен. :)

Preferred:

В методе, который добавляет элементы в коллекцию, бросьте ArgumentNullException, если они вызываются с недействительным значением.

Не предпочтительно:

Вытекает из Collection и переопределяет InsertItem и SetItem для сброса ArgumentNullException, если их значение является нулевым.

0
ответ дан 1 December 2019 в 02:55
поделиться

Что ж, первоначальная причина, по которой я выбрал OpenID, заключалась в том, чтобы кто-то другой мог обработать как можно больше реализации и безопасности аутентификации для меня.

После просмотра OpenID появляется что-то называемое «немедленным запросом» ( http://openid.net/specs/openid-authentication-2_0.html#anchor28 ).

При запросе аутентификации Доверяющая сторона МОЖЕТ запросить, чтобы ОП не взаимодействовала с конечным пользователем. В этом случае ОП ДОЛЖЕН немедленно ответить либо утверждением, что аутентификация успешна, либо ответом, указывающим, что запрос не может быть выполнен без дальнейшего взаимодействия с пользователем.

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

Этот метод выполнения, по-видимому, является способом, которым OpenID предлагает его выполнить с помощью документа Best Practices .

-121--2308818-

В целом сайт становится проще переваривать для остальной части Интернета. Данные можно использовать повторно, объединять, создавать перекрестные ссылки и сохранять.

Простым примером было бы иметь в любом месте на сайт широту и долготу (гео). С помощью микроформатов любой, кто ищет эту широту и долготу, может быть легко связан со своим веб-сайтом, увеличивая трафик, узнавая об этом человеке/компании и позволяя пользователям легко сохранять эту информацию. (Хотя я сталкивался с этим мало лично, это скорее «будущее» вещей, чем настоящее. Но всегда хорошо быть в курсе событий).

Вторым примером может быть визитная карточка (hCard), где браузер может легко сохранить и перенести ее в адресную книгу, так что только один визит на сайт и посетитель имеет информацию, сохраненную локально. Особенно полезно, если они получают хиты с мобильного телефона.

-121--4903969-

Мне неизвестна коллекция .NET, которая делает это, поскольку на основе переданного типа значение null фактически является допустимой записью, таким образом, добавление успешно выполнено.

Я, скорее всего, начну с класса System.Collections.ObjectModel.Collection для развертывания собственного.

1
ответ дан 1 December 2019 в 02:55
поделиться

Вам придется создавать свои собственные. Если вы хотите, чтобы Add возвращала bool (был ли элемент не null и, следовательно, добавлен или наоборот), вам придется начать с нуля. Я бы рекомендовал наследоваться от List и бросать ArgumentNullExceptions. То есть, если вы действительно не хотите добавлять нули, исключения могут быть лучшим способом и, конечно, более простым.

-1
ответ дан 1 December 2019 в 02:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: