Make immutable objects mutable

In .Net the String object is an immutable object, which means that it’s basically constant and can’t be changed. You can’t change a string, you can only create new strings. The various methods that the String class have never directly change the string they operate on, instead they return a new string.

Dim myString As String = "Hello World"
Dim mySecondString As String = myString.Substring(0, 5)
Console.WriteLine(myString) 'Hello World
Console.WriteLine(mySecondString) 'Hello

Even though we developers modify strings all the time, which can make them look mutable, they aren’t. What happens is that a new string is created and the reference variable we use simply points to the new string on the heap.

Make the string mutable

OK, the title of this article isn’t really true since you can’t make a string mutable, however because of a strange behavior in the VB implementation of extension methods, you can make it appear as if it was. Note that this is only possible in VB, to the best of my knowledge, C# does not have this behavior. This little known fact is that the argument of the extension method, the first parameter, can be passed by reference. Have a look at this example code:

<Extension()> _
Public Sub MutableInsert(ByRef str As String, _
                         ByVal position As Integer, _
                         ByVal text As String)
  If position >= str.Length Then
    str = str & text
  ElseIf position <= 0 Then
    str = text & str
  Else
    str = str.Substring(0, position) & text & str.Substring(position)
  End If
End Sub

Public Sub Main()
  Dim myString As String = "Hello world"
  myString.MutableInsert(5, " cruel")
  Console.WriteLine(myString) 'Hello cruel world
End Sub

Being a .Net developer for many years, this behavior looks weird to me. The fact that something that appears as an instance method actually can change the instance itself. But in some occasions it could actually be pretty useful. Take the following code as an example:

<Extension()> _
Public Sub EnsureNotNull(ByRef str As String)
  If str Is Nothing Then
    str = String.Empty
  End If
End Sub

Public Sub ChangeString(ByVal str As String)
  str.EnsureNotNull()
  Console.WriteLine("str Is Nothing = {0}", str Is Nothing) 'False
End Sub

Public Sub Main()
  ChangeString(Nothing)
End Sub

Personally I’m not sure that this feature is a good thing. If I can change a string from Nothing (or null) to String.Empty what stops me from doing the opposite? Well, absolutely nothing (no pun intended).

<Extension()> _
Public Sub EvilMethod(ByRef str As String)
  str = Nothing
End Sub

Public Sub Main()
  Dim msg As String = "Hello world"
  msg.EvilMethod()
  Dim newMsg As String = msg.Substring(0, 5) 'throws a NullReferenceException
  Console.WriteLine(newMsg)
End Sub

There you have it, the evil programmer have struck again.

Have fun.

Published Thu, Sep 3 2009 20:48 by Joacim Andersson

Comments

Thursday, September 03, 2009 1:51 PM by PimpThisBlog.com

# Make immutable objects mutable - Joacim's view on stuff

Thank you for submitting this cool story - Trackback from PimpThisBlog.com

Thursday, September 03, 2009 1:53 PM by DotNetKicks.com

# Make immutable object mutable

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Friday, September 04, 2009 1:21 AM by Sani Huttunen

# re: Make immutable objects mutable

You're right about that C# doesn't have this behaviour.

What's more important is that if you define a VB class library with a ByRef extension method you cannot use it in C#!!

Friday, September 04, 2009 7:43 AM by Joacim Andersson

# re: Make immutable objects mutable

Hello Sani,

You are correct that you can't call the extension method from C#. Or at least you can't use it as an extension method but you can still call it as if it was a regular static method.

string s = null;

MyNamespace.EnsureNotNull(ref s);

Friday, September 04, 2009 10:25 AM by Sani Huttunen

# re: Make immutable objects mutable

Yes you can use it as a static method but that defies the whole purpose of Extension Methods.

I.m.o: Never EVER use ByRef Extension Methods. They do more harm than good.

Friday, September 04, 2009 11:06 AM by Joacim Andersson

# re: Make immutable objects mutable

Well, as I have stated in the article, I'm not sure this feature is a good thing. However there might be times when this actually could be quite nifty, especially when you're dealing with mutable objects. In Dev10 there is a new System.Threading.SpinLock structure that provides a mutual exclusion lock primitive where a thread trying to acquire the lock waits in a loop repeatedly checking until the lock becomes available. It could be valuable to add the following extesion method to a SpinLock.

Public Sub Execute(ByRef lock As Threading.ThreadLock, ByVal action As Action)

 Dim locked As Boolean

 Try

   lock.Enter(locked)

   action()

 Finally

   If locked Then lock.Exit()

 End Try

End Sub

Friday, September 04, 2009 11:52 AM by Sani Huttunen

# re: Make immutable objects mutable

I understand your point.

However I'm not so keen on adding an Execute Extension Method on SpinLock.

To me it seems like SpinLock is executing the Action, which it isn't.

The above example doesn't execute the action on the SpinLock object.

I would differentiate objects and behaviour.

I see Extension Methods as methods extending the objects behaviour. Not the behaviour of the application.

But that's just me. I can't speak for others. :)

All in all I don't see the necessity to use ByRef Extension Methods at all.

Monday, September 07, 2009 9:27 AM by DotNetShoutout

# Make immutable objects mutable - Joacim's view on stuff

Thank you for submitting this cool story - Trackback from DotNetShoutout

Leave a Comment

(required) 
(required) 
(optional)
(required) 
If you can't read this number refresh your screen
Enter the numbers above: