views:

155

answers:

3

In Ruby, methods which change the object have a bang on the end: string.downcase!

In c# you have to do: foo = foo.ToLower()

Is there a way to make an extension method like:

foo.ConvertToLower()

that would manipulate foo?

(I think the answer is no since strings are immutable and you can't do a ref this in an extension method.)

+2  A: 

There are two ways of mutating a string instance:

  • Reflection
  • Unsafe code

I wouldn't recommend using either of them. Your fellow developers will hate you forever - particularly if the method is ever used to change a string which happens to be a literal...

Jon Skeet
Right, but I can reassign a string variable. I just want an extension method to do it for me.
brendanjerwin
You can't do that. What would you expect to happen if you called "Foo".ConvertToLower()? Even if you could, I wouldn't - it would be very non-obvious code to read.
Jon Skeet
I wish .NET team separated instance and static methods in way that static method would return a new instance while the instance methods would change the original. Like String.ToLower vs myString.ToLower()Jon, do you know why .NET team didn't follow this path?
Joan Venge
Yes: if strings were mutable, we'd be copying them all over the place as a defensive practice. It would be horribly inefficient. Immutable strings are a very good thing.
Jon Skeet
A: 

You can certainly write an extension method to re-assign the string being operated on. For example:

public static void ConvertToLower(this string s)
{
   s = s.ToLower();
}

This has nothing to do with the immutability of strings.

Jekke
I tried that, it didn't work.` string foo = "TEST"; foo.ConvertToLower();`foo still == "TEST"I guessed it was that `s` was a value type, passed on the stack, not a reference type. Therefore the reassignment did nothing outside the extension method.
brendanjerwin
-1: code doesn't work.
Juliet
I agree that it won't work, but not because the immutability of strings. It will not work because setting the value of a parameter will not change the actual variable passed in, unless the parameter is passed by reference (using the ref keyword), what you cannot use for extension methods.
csgero
@brendan: String is a reference type. The .ToLower() method returns a new string with the changes applied, it does not mutate the existing string. Also, the parameter "s" is a pointer passed by value (its a copy of a pointer), so "s = ..." reassigns the pointer to a new memory location.
Juliet
@Princess: Good explanation as to why "s=.." wouldn't work. I never thought about it, but it makes perfect sense now that a COPY of the pointer is passed. How is this achieved though? With all other objects, the actual pointer itself is passed?
BFree
@BFree: For every reference type, the reference is passed by value (unless you use ref/out). See http://pobox.com/~skeet/csharp/parameters.html
Jon Skeet
Oh man, I feel like an idiot. Duh! Thanks Jon.
BFree
A: 

No, you cannot do this in an extension method. To reassign the value of a variable passed in as a parameter you have to pass it by reference using the ref parameter modifier, what is not allowed for extension methods. Even if this would be possible, there might not be a variable to reassign, like in "foo".ConvertToLower().

csgero