Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which exception to throw when there are too many elements in a collection

I want the collection in my class to be limited to up to 6 elements:

public class Foo
{
  private ICollection bars;

  public ICollection Bars
  {
    get { return this.bars; }
    set 
    {
      if (value != null && value.Count > 6)
      {
        throw new Exception("A Foo can only have up to 6 Bars."); // Which exception to throw?
      }
    }
  }
}

What is the proper exception to throw in this case?

According to the documentation, ArgumentException shall be thrown:

when one of the arguments provided to a method is not valid.

But this is not a method.

ArgumentOutOfRange shall be thrown:

when the value of an argument is outside the allowable range of values as defined by the invoked method.

Which is intended fo accessing elements outside the size of the collection, not when the collection is too large.

Is there any other exception that suits better this case?

like image 307
J.A.I.L. Avatar asked Oct 15 '13 07:10

J.A.I.L.


3 Answers

I would use ArgumentException.

Why?

It's the argument that has a problem, not the object of type Foo. It the problem would be caused by the object of type Foo, then an InvalidOperationException would be more appropriate.

I would not use ArgumentOutOfRangeException, as there is no range of allowed ICollections. I would use this exception only if the parameter (and not its Count property) is IComparable, and its value is below a minimum or above a maximum. Note that there is no hard law that states this as the rule to follow, it's just what feels intuitive to most .NET developers.

At least as important as the type of the exception, is the message though. Make sure that clearly explains what the real problem is. The message should be targeted at the developer of the calling code, not at an end user, because the developper can and should write code that never throws this exception. It's what Eric Lippert would call a boneheaded exception and Krzysztof Cwalina would call a usage error.

Finally, don't focus on the word "method". A property has a get method and a set method. The code that is throwing the exception is in the set method, as others have pointed out.

like image 54
Kris Vandermotten Avatar answered Sep 18 '22 09:09

Kris Vandermotten


I would go with the ArgumentException (or InvalidOperationException as per @Ramunas suggestion).

Explanation:
Regarding the But this is not a method. statement, at the bottom line, there is no real difference between a method and a property. Meaning:

 public ICollection Bars
  {
    get { return this.bars; }
    set 
    {
      if (value != null && value.Count > 6)
      {
        throw Exception("A Foo can only have up to 6 Bars."); // Which exception to throw?
      }
    }
  }

Is equivalent to:

Public ICollection get_Bars()
{    
    return this.bars;    
}

Public ICollection set_Bars(ICollection value)
{    
  if (value != null && value.Count > 6)
  {
    throw new Exception("A Foo can only have up to 6 Bars."); // Which exception to throw?
  }   
}
like image 34
Avi Turner Avatar answered Sep 22 '22 09:09

Avi Turner


If you are setting constraints on what "too large" means, you can set a ConstraintException. According to the documentation, ConstraintException "Represents the exception that is thrown when attempting an action that violates a constraint.". Hope this helps.

like image 36
Blairg23 Avatar answered Sep 20 '22 09:09

Blairg23