Index and length must refer to a location within the string

T

tshad

I am getting this error with a bunch of my substring statements where I
don't know what the size of the string will be.

So I do something like:

if ((AppSettings.formName.ToUpper() != "ERC") &&
(((((string)r["tagName"]).Length >= 3) &&
(((string)r["tagName"]).Substring(0, 3) == "RMS")) ||
(((((string)r["tagName"]).Length >= 8) &&
(((string)r["tagName"]).Substring(0, 8) == "ROOM_ABV")))))


I had to add the length test to prevent this from happening.

Is this the best way around this.

Thanks,

Tom
 
T

tshad

Mark Rae said:
Difficult to tell without knowing what you're actually trying to do...

Just trying to test (or get) a substring of a string.

When testing for almost anything names, address, comments etc where you
would not know the length of a string - I assume you always would need to
test the size of the string against either the index value and/or the
length. Since it doesn't blank fill what you are checking there would
always be a chance that that the size of the string would be less than the
index or length.

Tom
 
J

Jason Newell

New Recommendations for Using Strings in Microsoft .NET 2.0
http://msdn.microsoft.com/en-us/library/ms973919.aspx

You also need to be careful with casting like (string)r["tagName"]).
What if r["tagName'] returns null? So you need to check for null.

You're also casting r["tagName"] 4 times in the code. I suggest that
you load the variable into local string variable and work from there.

StartsWith() is a good recommendation.

I would also suggest that you use String.Equals() for comparison rather
than != == etc.

If tagName is delimited in some way (i.e. spaces), you can also do:

string[] tokens = tagname.Split(new char[] { ' ' },
StringSplitOptions.RemoveEmptyEntries);
foreach (string token in tokens)
{
}

Jason Newell
www.jasonnewell.net
Hi,

In Your case using StartsWith could be shorter.
http://msdn.microsoft.com/en-us/library/system.string.startswith.aspx

-Zsolt

tshad said:
I am getting this error with a bunch of my substring statements where
I don't know what the size of the string will be.

So I do something like:

if ((AppSettings.formName.ToUpper() != "ERC") &&
(((((string)r["tagName"]).Length >= 3) &&
(((string)r["tagName"]).Substring(0, 3) == "RMS")) ||
(((((string)r["tagName"]).Length >= 8) &&
(((string)r["tagName"]).Substring(0, 8) == "ROOM_ABV")))))


I had to add the length test to prevent this from happening.

Is this the best way around this.

Thanks,

Tom
 
P

Pavel Minaev

You also need to be careful with casting like (string)r["tagName"]).
What if r["tagName'] returns null?  So you need to check for null.

Casting a null to a string is a valid operation, and gives a null
reference to string. Using that is another matter.
You're also casting r["tagName"] 4 times in the code.  I suggest that
you load the variable into local string variable and work from there.
Agreed.

I would also suggest that you use String.Equals() for comparison rather
than != == etc.

Er, why? It's longer, less readable, unsafe for nulls (unless you use
the static variant, which is even longer), and works exactly the same
as ==. This isn't Java...
 
J

Jason Newell

And this is why it's fun giving your opinions online. They get
challenged ;-).

Pavel said:
You also need to be careful with casting like (string)r["tagName"]).
What if r["tagName'] returns null? So you need to check for null.

Casting a null to a string is a valid operation, and gives a null
reference to string. Using that is another matter.
Agreed.
I would also suggest that you use String.Equals() for comparison rather
than != == etc.

Er, why? It's longer, less readable, unsafe for nulls (unless you use
the static variant, which is even longer), and works exactly the same
as ==. This isn't Java...

I've read over the years that .Equals is actually slightly faster than
== so I tend to use it. Now that you've made me think about it, I tend
to agree with you.

A quick google search on "C# String.Equals vs ==" found:
http://dotnetjunkies.com/WebLog/chris.taylor/archive/2004/05/18/13927.aspx

Funny though, I hadn't really put much thought into your point about it
being unsafe for nulls. I agree also that the performance gain vs.
readability is debatable.
 
M

Mythran

tshad said:
I am getting this error with a bunch of my substring statements where I
don't know what the size of the string will be.

So I do something like:

if ((AppSettings.formName.ToUpper() != "ERC") &&
(((((string)r["tagName"]).Length >= 3) &&
(((string)r["tagName"]).Substring(0, 3) == "RMS")) ||
(((((string)r["tagName"]).Length >= 8) &&
(((string)r["tagName"]).Substring(0, 8) == "ROOM_ABV")))))


I had to add the length test to prevent this from happening.

Is this the best way around this.

Thanks,

Tom

I see some recommendations about StartsWith, but this goes a little further
with an example:

if (AppSettings.formName.ToUpper() != "ERC") {
string name = r["tagName"] as string;
if (!string.IsNullOrEmpty(name) &&
(name.StartsWith("RMS") || name.StartsWith("ROOM_ABV"))) {
// Do something.
}
}

or...

const string PATTERN = @"^(RMS)|(ROOM_ABV).*";
if (AppSettings.formName.ToUpper() != "ERC" &&
Regex.IsMatch((string) r["tagName"], PATTERN)) {

// Do something.
}

Surprised nobody mentioned Regular Expressions for this...although, regular
expressions is quite slower, it may end up being easier to maintain....in
this case anyways....Both ways don't require you to check the length of the
string because both ways will return false for the checks without throwing
an exception...

Note: The above code wasn't tested and was written off the top of my
head...may be missing parens or other required syntax...

HTH,
Mythran
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top