Why does Replace return Nothing???

  • Thread starter Thread starter Joe HM
  • Start date Start date
J

Joe HM

Hello -

I have the following very simple code ...

Dim lStringA As String = ""
Dim lStringB As String = ""

....

lStringB = Replace(lStringA, "DUMMY", "", Compare:=CompareMethod.Text)
lStringB.TrimEnd("\"c)

According to the documenation, Replace will return a zero-length string
("") if lStringA is zero-length. So why is lStringB Nothing and causes
an exception when calling the TrimEnd() function?

Do I have to check whether lStringA is <> "" before I call Replace()?

Thanks,
Joe
 
It does seem the documentation is wrong (a Nothing return is never
mentioned,

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vblr7/html/vafctreplace.asp

unless one interprets "Copy of Expression with no occurrences of Find"
as a possible Nothing, which anyway does not apply because Nothing is
returned even with a non zero-length "Replace" ).

I never noticed that (I usually manage to use stringbuilders when doing
replacements ... )

-tom
 
This is how the Replace function in the Microsoft.VisualBasic namespace is
implemented:

Public Shared Function Replace(ByVal Expression As String, ByVal Find As
String, ByVal Replacement As String, ByVal Start As Integer = 1, ByVal Count
As Integer = -1, <OptionCompare> ByVal [Compare] As CompareMethod = 0) As
String
Dim text1 As String
Try
If (Count < -1) Then
Throw New
ArgumentException(Utils.GetResourceString("Argument_GEMinusOne1", "Count"))
End If
If (Start <= 0) Then
Throw New
ArgumentException(Utils.GetResourceString("Argument_GTZero1", "Start"))
End If
If ((Expression Is Nothing) OrElse (Start > Expression.Length)) Then
Return Nothing
End If
If (Start <> 1) Then
Expression = Expression.Substring((Start - 1))
End If
If (((Find Is Nothing) OrElse (Find.Length = 0)) OrElse (Count = 0))
Then
Return Expression
End If
If (Count = -1) Then
Count = Expression.Length
End If
text1 = Strings.Join(Strings.Split(Expression, Find, (Count + 1),
Compare), Replacement)
Catch exception1 As Exception
Throw exception1
End Try
Return text1
End Function

Note that the Expression parameter is defined as string and that the Start
parameter defaults to 1.

In your example, the test:

If ((Expression Is Nothing) OrElse (Start > Expression.Length)) Then

will be true and Nothing will be returned. If an empty string is interpreted
as Nothing then the first part will be true otherwise the second part will
be true because 1 is greater than the length of an empty string.

So we are left with 2 scenarios:

1 - the documentation is incorrect

or

2 - whoever wrote the Replace function expects that
Nothing will be marshalled back as an empty string

Either way, the behaviour is at odds with the documentation and, yes, you
should either check to see if the result is Nothing before continuing.

If you were to use the String.Replace method instead you would avoid this
issue.
 
Hi Stephany , interesting... where did you get that ? :)

-tom


PS
"If an empty string is interpreted as Nothing"
that does not correspond to my experience (string.empty is not nothing)
 
I had a look at it in Lutz Roeder's Reflector.

http://www.aisto.com/roeder/dotnet/

It is excellent for delving into the Framwork and seeing how things are
implemented.

Yes. You're right. I was wondering out loud if there might or might not be
some mechanism in the framework that somehow modified the values that are
marshalled to and from the methods (functions) in Microsoft.VisualBasic
namespace, so that an empty string got interpreted as Nothing an/or vice
versa. You may or may not recall that back in VB6 an number of the string
functions returned variant containg strings rather than true strings. It was
probably a spurious thought but it did cross my mind.
 
Sephany,

Very interesting and really odd what you found. I hope on a comment from
Herfried, who loves the VB replace and methods like that.

Cor


Stephany Young said:
This is how the Replace function in the Microsoft.VisualBasic namespace is
implemented:

Public Shared Function Replace(ByVal Expression As String, ByVal Find As
String, ByVal Replacement As String, ByVal Start As Integer = 1, ByVal
Count As Integer = -1, <OptionCompare> ByVal [Compare] As CompareMethod =
0) As String
Dim text1 As String
Try
If (Count < -1) Then
Throw New
ArgumentException(Utils.GetResourceString("Argument_GEMinusOne1",
"Count"))
End If
If (Start <= 0) Then
Throw New
ArgumentException(Utils.GetResourceString("Argument_GTZero1", "Start"))
End If
If ((Expression Is Nothing) OrElse (Start > Expression.Length)) Then
Return Nothing
End If
If (Start <> 1) Then
Expression = Expression.Substring((Start - 1))
End If
If (((Find Is Nothing) OrElse (Find.Length = 0)) OrElse (Count = 0))
Then
Return Expression
End If
If (Count = -1) Then
Count = Expression.Length
End If
text1 = Strings.Join(Strings.Split(Expression, Find, (Count + 1),
Compare), Replacement)
Catch exception1 As Exception
Throw exception1
End Try
Return text1
End Function

Note that the Expression parameter is defined as string and that the Start
parameter defaults to 1.

In your example, the test:

If ((Expression Is Nothing) OrElse (Start > Expression.Length)) Then

will be true and Nothing will be returned. If an empty string is
interpreted as Nothing then the first part will be true otherwise the
second part will be true because 1 is greater than the length of an empty
string.

So we are left with 2 scenarios:

1 - the documentation is incorrect

or

2 - whoever wrote the Replace function expects that
Nothing will be marshalled back as an empty string

Either way, the behaviour is at odds with the documentation and, yes, you
should either check to see if the result is Nothing before continuing.

If you were to use the String.Replace method instead you would avoid this
issue.



Joe HM said:
Hello -

I have the following very simple code ...

Dim lStringA As String = ""
Dim lStringB As String = ""

...

lStringB = Replace(lStringA, "DUMMY", "", Compare:=CompareMethod.Text)
lStringB.TrimEnd("\"c)

According to the documenation, Replace will return a zero-length string
("") if lStringA is zero-length. So why is lStringB Nothing and causes
an exception when calling the TrimEnd() function?

Do I have to check whether lStringA is <> "" before I call Replace()?

Thanks,
Joe
 
Hello -

Wow ... thanks for all the feedback! I have looked into using the
String.Replace function but I cannot set the
Compare:=CompareMethod.Text (case-insensitive) that way ... can I?

Thanks,
Joe
 
Cor Ligthert said:
Very interesting and really odd what you found. I hope on a comment from
Herfried, who loves the VB replace and methods like that.

The documentation for 'Microsoft.VisualBasic.Strings.Replace' in .NET 2.0
states:

| *Return Value*
| [...]
| 'Nothing' Expression is zero-length or 'Nothing', or 'Start' is
| greater than length of 'Expression'.
 
You are so right Herfried.

The link a poster gave earlier in the thread actually refers to .Net 1.0/1.1
so this is a change in .NET 2.0.


Herfried K. Wagner said:
Cor Ligthert said:
Very interesting and really odd what you found. I hope on a comment from
Herfried, who loves the VB replace and methods like that.

The documentation for 'Microsoft.VisualBasic.Strings.Replace' in .NET 2.0
states:

| *Return Value*
| [...]
| 'Nothing' Expression is zero-length or 'Nothing', or 'Start' is
| greater than length of 'Expression'.
 
Stephany,

Stephany Young said:
You are so right Herfried.

The link a poster gave earlier in the thread actually refers to .Net
1.0/1.1 so this is a change in .NET 2.0.

You are right, the documentation on .NET 1.0/1.1's 'Replace' function
doesn't state this case. Maybe it was a bug in the implementation and
Microsoft decided to change the documentation to solve the problem.
Personally I would have changed the implementation of the method to return
an empty string instead of a 'Nothing' reference, because it would seem more
intuitive to me, but I didn't spend time on thinking about the implications
of such a change.
 
I agree Herfried. Returning an empty string would certainly be more
intuitive from my point of view. Also, IIRC, the empty string has been the
return value since Replace was introduced to VB (can't remember whether it
was VB5 or VB6).
 
Back
Top