Кодовый контракт для предотвращения дублирования в списке

В настоящее время я проверяю с помощью этого контракта, что параметр и возвращаемое значение не равны нулю. Теперь мне нужен способ проверить, что независимо от того, какую ветвь переключателя он использует, результирующий IEnumerable не должен иметь дубликатов в своих кодовых значениях. Возможно ли это с помощью кодовых контрактов. Я пытаюсь использовать Contract.ForAll, но безуспешно.

internal static IEnumerable<MenuItemAction> GetMenuActions(MenuItem menuItem)
{
    Contract.Requires(menuItem != null);
    Contract.Ensures(Contract.Result<IEnumerable<MenuItemAction>>() != null);

    switch (menuItem.Code)
    {
        case 0:
            return new MenuItemAction[3] { 
        new MenuItemAction(){Code = 0, Label = "."}, 
        new MenuItemAction(){Code = 1, Label = ".."}, 
        new MenuItemAction(){Code = 2, Label = "..."}
    };
        case 1:
            return new MenuItemAction[2] { 
        new MenuItemAction(){Code = 3, Label = "."}, 
        new MenuItemAction(){Code = 4, Label = ".."}
    };
        case 2:
            return new MenuItemAction[2] { 
        new MenuItemAction(){Code = 5, Label = "."}, 
        new MenuItemAction(){Code = 6, Label = ".."}
    };
        default: return null;
    }
}

person Erre Efe    schedule 25.08.2012    source источник


Ответы (2)


Пытаться

Contract.Ensures(
    Contract.Result<IEnumerable<MenuItemAction>>() != null &&
    Contract.Result<IEnumerable<MenuItemAction>>().Count() == 
        Contract.Result<IEnumerable<MenuItemAction>>()
           .Select(m => m.Code)
           .Distinct()
           .Count()
);
person Olivier Jacot-Descombes    schedule 25.08.2012
comment
Спасибо за ответ, но Distinct вернет отдельные элементы из массива, и он может содержать разные элементы в каждом поле, кроме кода. Свойство кода элементов в массиве должно быть уникальным, но не другими свойствами. - person Erre Efe; 25.08.2012
comment
Я изменил свой пример соответственно. - person Olivier Jacot-Descombes; 25.08.2012

Какой был код для contract.ForAll? Что вы заметили?

Хотя на самом деле вы не спрашивали об альтернативах, я бы посоветовал вам рассмотреть возможность использования множества вместо массива.

Переопределите Equals и GetHashCode в MenuItemAction, и каждый раз, когда вам нужна коллекция отдельных элементов, используйте коллекцию Set.

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

Все сводится к тому, чего именно вы хотите достичь? Вы хотите обеспечить разные значения или хотите, чтобы никто не ввел одно и то же значение дважды? (Вы пытаетесь защитить содержимое или использование?).

Независимо от того, может ли код MenueItem находиться за пределами диапазона 0-4? Или, другими словами, вы действительно имеете в виду, что метод возвращает значение null в случае, если код OutOfRange (подсказка :-))

person Vitaliy    schedule 25.08.2012
comment
Меню на самом деле загружается из какого-то странного XML, но в основном я хочу утверждать с помощью контракта, что результирующие элементы IEnumerable MenuItemAction имеют разные свойства кода для каждого значения. Я имею в виду, что может быть 1, 2 или любые объекты MenuItemAction, но каждый из них должен иметь различное значение для свойства Code. - person Erre Efe; 25.08.2012