views:

256

answers:

4

I am implementing a list, and I am wondering about the definition of the IndexOutOfRange. Which one of the following do you think is better?

/// <exception cref="IndexOutOfRangeException">if index is less than 0
/// or greater than <see cref="Count"/>
public T this[int index] { get { return myArray[index]; } }

Or

/// <exception cref="IndexOutOfRangeException">if index outside the valid range
/// for an array of length equal to <see cref="Count"/></exception>
public T this[int index] { get { return myArray[index]; } }

I am thinking about the case when this class would be used from a .NET language that indexes arrays starting from 1. I don't know much about the topic, but is the second version better than the first by any means?

A: 

Is it possible you could also have a "Base" property, then you could say:

/// <exception cref="IndexOutOfRangeException">if index is less than <see cref="Base" />

If you can't have a Base property, then the second version is better, if you have to be careful about 1-based arrays.

Chris Cameron
+1  A: 

Slightly OT: can you encapsulate a list rather than an array, and then everything falls out in the wash since the encapsulated list will generate appropriate exceptions?

Edit: if you really need the array internally, how about wrapping it in a list inside the accessor first, and then selecting by index. This way the translation from list index to array index occurs inside the language of your component rather than the caller's.

Presumably the semantics of list indexing doesn't change across .Net languages? This is what your component should follow since it implements the list interface.

Edit again: actually, is this a problem at all??

People access your array through the accessor, which is written in a language that you control and so know where array indexing starts from. Even if you call your (say) C# class from a VB.Net caller, the accessor will still use C#'s idea of array indexes, won't it?

Dan Vinton
Thanks for your suggestion, but I'm hoping to get better performance by using the array directly.
Hosam Aly
Are you sure you need to optimise yet?
Dan Vinton
I forgot to mention that I also need to handle some synchronization between threads.
Hosam Aly
Thanks for the edit. This looks like a nice idea, except that it would cause a large performance overhead. Thanks for your help though!
Hosam Aly
Dan, you are correct. There is absolutely no problem from languages with different array bases, UNLESS he also wants his class's array-index operator to behave like the calling language's. But I don't think it's a good idea to try to do that.
Rob Kennedy
Now that's the answer I was looking for. I'm sorry that I have not phrased my question well. What I really wanted to know was whether access rules would change if a library is being used from another language. Thanks a lot! (And many thanks for your patience :) )
Hosam Aly
A: 

IList<T> already documents the exception (ArgumentOutOfRangeException, not IndexOutOfRangeException). If you are implementing the interface and not changing the documented behavior, why do you need to document it? If you're going to document it at all, it ought to agree with the interface.

EDIT: Just noticed your implementation (or at least the implication by naming of your implementation). I agree with @Dan, you really ought to base it on List<T> instead of an array so that the implementation agrees with the interface. Under that condition, there is no need to re-document the exception. If you don't change the underlying implementation then you ought to catch the IndexOutOfRangeException and map it to the ArgumentOutOfRangeException documented by the interface.

tvanfosson
I am actually changing the documented behavior to a simpler one, which makes code simpler and faster, and is sufficient for my needs.(And to tell the truth, I was never convinced that an indexer should throw any exception other than IndexOutOfRangeException, except for debugging purposes.)
Hosam Aly
My question is more about whether the case could happen. Consider I shall do a check. Should I write "if (index < 0)" or "if (index < myArray.GetLowerBound(0)"?
Hosam Aly
A: 

As an aside - you can always simply inherit from Collection<T> as a starting point... this provides the raw code, while letting you customize things. You can inherit from List<T>, but unlike Collection<T> there are no useful virtual methods on List<T>.

Marc Gravell
Thanks for the suggestion; I didn't know of this class. However, I think I need finer control over my collection, because I need to handle some concurrency issues.
Hosam Aly
Ah, the old "composition vs inheritance" question...
Dan Vinton