I would never hard code a call like this.

    string x = s.Substring(0, 999);  // should return "test", not throw
    string x = s.Substring(0, -1 );  // should return Empty , not throw

That would be silly.  However, these calls occur due to inline
computation.

    string x = s.Substring(FindStart(...), FindEnd(...));

Let suppose that the function FindEnd() returns -1 because some
delimiter is not found (like IndexOf()).  I would prefer Substring to
simple return Empty not throw.

If Substring did *not* throw I could do this.

    string x = s.Substring(0, s.IndexOf('=') ).Trim().ToUpper();

I could count on Substring returning the *very reasonable* value of
Empty if the token was not found.  Since it does throw, I must do
this.

    int i = s.IndexOf('=');
    string x;
    if (i > 0)
        x = s.Substring(0, i ).Trim().ToUpper();
    else
        x = string.Empty;

My point is...

I see this little 'if' block every time I want to use Substring.  It
would be much more convenient if the Substring simply didn't throw.
For the same reason that you don't want to be forced to do an 'if'
block before every division.

Just because everything doesn't throw an exception, that doesn't imply
that we are returning to the bad old days.  Consider
StreamReader.ReadLine() for example.  It returns null if you are at
the end of the stream.  It would not be as convenient to use 'in its
typical application' if it threw an exception.

Cheers...David

----- Original Message -----
From: "Ian Griffiths" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Monday, May 06, 2002 8:26 PM
Subject: Re: [DOTNET] Why does Substring() throw?


"David Ferguson" <[EMAIL PROTECTED]> wrote:

> The fact that Substring() throws if any little parameter is
> off makes it almost unusable.  Don't you think?

I disagree for the examples that you have shown:

>   string s = "test";
>   string x = s.Substring(0, 999);  // should return "test", not throw

What's wrong with s.SubString(0); ?

I think the use of 999 to indicate "longer than any string could ever
possibly be" is extremely bad practice.  Strings can easily be longer than
999 characters.  If you mean "from here to the end of the string" then just
say so - the String class provides you with a method for doing precisely
that.  Why feed in whacky constants and expect the framework to guess the
required semantics when you can just say what you mean?


>   string x = s.Substring(0, -1 );  // should return Empty , not throw

Why would you ever do this?  Asking for a string of negative length is quite
clearly a programming error, since no such thing can exist.  The class is
simply telling you this rather than attempting to guess what you might have
meant if your code hadn't contained that programming error.  If you want an
empty string, say so.



>   string z = s.Substring(999, 4);  // should return Empty , not throw

This is the only case where I can see that it might conceivably be useful to
get back nothing, since it would save you from having special handling to
detect the case when you've run off the end of the string.  On the other
hand, what if running off the end of the string was an error?  In that case
I *would* require special handling, and would probably be cursing the string
class for not doing it for me.  And since for all the other cases it makes
sense to throw an exception for attempting to access a non-existent part of
a string, it is consistent for it to do so here.



> I think it shouldn't throw for the same reason the division
> by zero doesn't.  It is just too much trouble to always test
> every division.

...just like it's too much trouble to test the return value from every
system call?  Surely this it is the programmer's job to deal with this kind
of thing - to ignore such things would be pure negligence.

If there's an error case, the last thing I want is for the code to silently
swallow it and press on regardless.  That's how it was in the bad old days,
and we changed for a good reason.


C# raises a DivideByZeroException if you divide an integer by zero.  Doesn't
VB?  Floating point numbers don't raise an exception admittedly - you get
Infinity (or NaN if both numbers were zero).  But for integers I want it to
throw an exception since there is no reasonable integer result for dividing
a number by zero.  I'm not entirely happy that FP numbers don't throw here
either actually, mostly because it means that I have to check every time I
do a divide...

So I disagree entirely with the philsophy behind what you are saying
(assuming I have understood you correctly) - I think that if the system were
silently to swallow errors, it would require *much* more effort on the
programmer's part to write working code.  Of course it would make it much
easier to write flakey code.  But I don't want to write flakey code.


> You can't just do simple calculations and get the
> substring because it might through.

If it throws, it is because you have bad input.  This means you should check
your input.  This is a basic requirement for any piece of code.  Failure to
check input is probably the single biggest cause of security holes in
software systems.  So I approve of anything that detects bad input and flags
it as an error - it keeps me honest (i.e. I have no option but to check my
input; since I should be doing that anyway if I want my code to be robust,
it's a good thing that I have no option).  I dislike anything that attempts
to press on regardless in the fact of manifestly bad input.

For these methods to behave as I believe you are suggesting rather smacks of
On Error Resume Next...  :-)


--
Ian Griffiths
DevelopMentor

You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to