0

I'm currently checking with this contract that the parameter and the return value aren't null. Now, I need a way to check that no matter what branch of the switch it takes then the resulting IEnumerable must not have duplicates on its code values. Is this possible using code contracts. I try to use the Contract.ForAll but with no luck.

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;
    }
}
Erre Efe
  • 15,387
  • 10
  • 45
  • 77

2 Answers2

3

Try

Contract.Ensures(
    Contract.Result<IEnumerable<MenuItemAction>>() != null &&
    Contract.Result<IEnumerable<MenuItemAction>>().Count() == 
        Contract.Result<IEnumerable<MenuItemAction>>()
           .Select(m => m.Code)
           .Distinct()
           .Count()
);
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • Thanks for the reply but the Distinct will return the distinct elements from the array and it can contain distinct ones on every field except the code. Code property of the elements within the array must be unique but not other properties – Erre Efe Aug 25 '12 at 19:40
  • I changed my example accordingly. – Olivier Jacot-Descombes Aug 25 '12 at 19:43
1

What was the code for the contract.ForAll? What did you observe?

Though you didn't actually ask for alternatives, I would suggest you consider using a setinstead of an Array.

Override the Equals and GetHashCode on MenuItemAction and each time you want a collection of distinct items- use the Set collection.

It guarantees that the values are unique and if you want to know whether duplicates have been encountered all you need to do is check the return value of the Add method.

It all comes down to what exactly you want to achieve? Do you want to ensure distinct values or do you want to ensure no one puts the same value twice? (Are you trying to protect the contents or the usage?).

Regardless, does the code of a MenueItem can be outside of the range 0-4? Or in other words- do you actually mean for the method to return null in case the code is OutOfRange (hint hint :-))

Vitaliy
  • 8,044
  • 7
  • 38
  • 66
  • The menu is actually loaded from some weird XML but basically what I want to assert with the contract is that the resulting IEnumerable MenuItemAction elements has different Code properties for each values. I mean can have 1, 2 or any MenuItemAction objects but every one must have a different value for its Code property. – Erre Efe Aug 25 '12 at 19:42