JOB REFERRALS
    ON THIS PAGE
    ARCHIVES
    CATEGORIES
    BLOGROLL
    LINKS
    SEARCH
    MY BOOKS
    DISCLAIMER
 
 Monday, November 21, 2005
The immutable string

Mark Michaelis posted a challenge: modify a string such that the following would print "Smile":

class Program
{
  static void Main()
  {
      string text;
      // ...
      // Place code here
      // ...
      text = "S5280ft";
      System.Console.WriteLine(text);
  }
}

His solution?

class Program
{
  static void Main()
  {
      string text;
      unsafe {
          fixed (char* pText = text) {
              pText[1] = 'm';
              pText[2] = 'i';
              pText[3] = 'l';
              pText[4] = 'e';
          }
      }
      text = "S5280ft";
      System.Console.WriteLine(text);
  }
}

My answer; note that I believe mine to be cleaner, more elegant, and far far more dangerous, since it never uses any sort of unsafe code:

class Program
{
  static void Main()
  {
      string text;

      string internedText = "S5280ft";
      String.Intern(internedText);
      MethodInfo mi = typeof(string).GetMethod("InsertInPlace", 
        BindingFlags.NonPublic | BindingFlags.Instance, null,
        new Type[] { typeof(Int32), typeof(string), typeof(Int32), typeof(Int32), typeof(Int32) }, null);
      mi.Invoke(internedText, new object[] {0, "Smile", 1, 7, 5});      

      text = "S5280ft";
      System.Console.WriteLine(text);
  }
}

The point? Playing with Reflection can be dangerous... oh, and it helps to know that strings are only as immutable as the platform forces them to be. In this case, my little hack would only be possible because under the covers, .NET doesn't really have immutable strings--it just doesn't let YOU modify them. :-)

(By the way, same trick is available in Java, using the same approach. Or you could write JNI code to sort of duplicate Mark's trick, but who'd want to do that? Brrr.)


Monday, November 21, 2005 6:52:27 AM (Pacific Standard Time, UTC-08:00)
In Java, you can prevent this using a security manager. What's the .NET equivalent?
Monday, November 21, 2005 8:50:04 AM (Pacific Standard Time, UTC-08:00)
One the topic of unsafe and dangerous...In the java world, with sun's VM, the class sun.misc.Unsafe can be loads of fun. My favorite is being able to manipulate monitorEnter/monitorExit across method boundaries

By the way, how does the code snippet for Mark's solution not throw a NPE? Furthermore, I would guess it would print "Smileft" as opposed to "Smile". (maybe it's now obvious I'm not a C# programmer)
Tim Eck
Monday, November 21, 2005 11:04:57 AM (Pacific Standard Time, UTC-08:00)
Nice,

Nothing is sacred. Reminds me of: Java 5 - "final" is not final anymore (http://www.javaspecialists.co.za/archive/Issue096.html)

Dion

http://ajaxian.com - Clean up the web with Ajax
Monday, November 21, 2005 11:53:04 AM (Pacific Standard Time, UTC-08:00)
I get the compile error (after having set /unsafe switch):
Class1.cs(32): Use of unassigned local variable 'text'

When trying to compile Mark's solution.

Initializing 'text' to an empty string clears that problem. Now, Mark's example outputs 'S5280ft' and not 'Smile' Unless I'm missing something (likely) how was Mark's version ever supposed to work?

Ted's version works BTW.

My conclusion: Ted has waaaaaaay too much time on his hands.

Confused in Kitchener.

Monday, November 21, 2005 12:27:19 PM (Pacific Standard Time, UTC-08:00)
Found the problem. Ted didn't copy over Mark's example fully. If I initialize the 'text' variable to 'S5280ft' and add the code for pText[5] and pText[6] as in Mark's example then it works as advertised.

Funny that when initialized to an empty string that it didn't error and printed the original string. In an empty string, pText[1-6] would not exist.

WTF?

Dave
Monday, November 21, 2005 5:11:09 PM (Pacific Standard Time, UTC-08:00)
// ...
// Place code here
// ...
Console.Out.NewLine = "\x0008\x0008\x0008\x0008\x0008\x0008\x0008Smile \n";
Dan
Thursday, December 01, 2005 12:11:28 PM (Pacific Standard Time, UTC-08:00)
Ted, do you waste your time over figuring out these sort of useless things? Don't you have better things to take care of? And that moron DION. tiring, you both are....
Wednesday, December 28, 2005 9:32:32 PM (Pacific Standard Time, UTC-08:00)
I am not a C# developer but I tried and the C# version works. The same code written in Java doesn't.
text = "s5280ft";;
String internedText = text.intern();

Method method = String.class.getMethod( "replace",
CharSequence.class,
CharSequence.class);

method.invoke( internedText, internedText.substring(1,7), "mile " );
text = "s5280ft";
System.out.println( text );
Mohan Radhakrishnan
Monday, August 28, 2006 6:15:01 AM (Pacific Daylight Time, UTC-07:00)
thanks
Comments are closed.