0

I am trying to make something like

string s = "Hello";
s.Clear();

And I created the extension method like this:

public static void Clear(this string s)
{
    s = string.Empty;
}

But, when I see the value, it does not change:

enter image description here

I can't use ref or out because these can't be used with the keyword this. Any ideas?

Exel Gamboa
  • 936
  • 1
  • 14
  • 25
  • 15
    Here is it: `s = String.Empty;`. Do you really need an extension for this task? – Tim Schmelter Oct 04 '16 at 15:17
  • 1
    You're getting a copy of the reference to your string and setting that copy to a reference to `String.Empty`. For this to work the method would have to take a `ref` argument, but then it could not be an extension method. – juharr Oct 04 '16 at 15:19
  • 1
    @ExelGamboa what are you trying to do? You can't modify a string. Are you trying to clear a property perhaps? What is the *actual* problem you are trying to solve? – Panagiotis Kanavos Oct 04 '16 at 15:20
  • 1
    This is another case of the [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). You want to clear something (X) and think that the solution is an extension method that reassigns an input string (Y). When that doesn't work, you ask for Y, not the actual problem X. What is your *actual* problem? – Panagiotis Kanavos Oct 04 '16 at 15:22
  • Yes, I know string.Empty works awesome. I was just doing this just for the sake of expanding my knowledge and understanding of Extension Methods. I know that in VB, you can do this: Public Sub Clear(ByRef str As String) str = String.Empty End Sub ... but reading your comments, now I know that in C# this is not possible. – Exel Gamboa Oct 04 '16 at 15:23
  • You can't, even in VB.NET. This method does something completely different. It changes the *pointer* to something else. – Panagiotis Kanavos Oct 04 '16 at 15:24
  • 3
    So my follow-up question would be: why does such an extension method work in VB but not in C#, although both share the same CLR? Shouldn't CLR bytecode always be decompileable into both C# and VB? – Alexander Oct 04 '16 at 15:25
  • 1
    Each language works differently. VB.NET tries to allow as many things as possible. C# avoids unfortunate ideas like vampiric extension methods that turn their target into something else. – Panagiotis Kanavos Oct 04 '16 at 15:29
  • In VB.NET you can have extensions with ByRef parameters whereas C# doesn't alllow it. If you make a method `static void Clear(ref string str){str="";}` and you call it `Clear(s)` you would set it `String.Empty` too. Related: [Doesn't C# Extension Methods allow passing parameters by reference?](http://stackoverflow.com/questions/1259103/doesnt-c-sharp-extension-methods-allow-passing-parameters-by-reference) – Tim Schmelter Oct 04 '16 at 15:33
  • To put it another way, an extension is just another static method. It could have a `ref` first argument in both languages. *Developers* though expect the method to be an *extension* to an object. Swapping the object with another breaks that expectation. C# designer don't want such surprises. – Panagiotis Kanavos Oct 04 '16 at 15:33

3 Answers3

11

This is not possible. From the documentation:

Strings are immutable--the contents of a string object cannot be changed after the object is created, although the syntax makes it appear as if you can do this. For example, when you write this code, the compiler actually creates a new string object to hold the new sequence of characters, and that new object is assigned to b. The string "h" is then eligible for garbage collection.

Cristian Lupascu
  • 39,078
  • 16
  • 100
  • 137
  • I guess Reflection could be able to find the calling object and make it point to `string.Empty`. – Alexander Oct 04 '16 at 15:18
  • 8
    @Alexander Even if that's possible, I would stay away from such magic and use `s = string.Empty` instead of calling an extension method on it. – Cristian Lupascu Oct 04 '16 at 15:20
  • 4
    This is less about mutability and more about how extension methods are limited to value passing versus passing by reference. The OP isn't trying to mutate the sting, but instead reassign the variable to a different reference. – juharr Oct 04 '16 at 15:24
  • @Alexander In certain specific instances, maybe, although it'd be super evil to write such code. But even then there'd be tons of code you could write such that even reflection wouldn't be able to change the variable (and plenty of instances where there is no variable to change). You'd need to do straight `unsafe` code with arbitrary memory tinkering to handle all of the cases where there even is a value to change. – Servy Oct 04 '16 at 15:28
  • With the exception of the opening blurb about "This is not possible", I'm not at all certain how this actually answers the question. – David L Oct 04 '16 at 16:31
2

If you're looking for a kind of mutable version of String you can try using StringBuilder:

   StringBuilder s = new StringBuilder("Hello");
   s.Clear();

   ...

   String myFinalString = s.ToString(); 
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • 3
    I think the OP asks why `this ref` isn't allowed in C# although it's allowed in VB.NET. Which means that one can write an extension method that swaps your object when you aren't looking – Panagiotis Kanavos Oct 04 '16 at 15:31
0

If the extension method checks a condition, you could pass an Action as a parameter (caller passes lambda expression) so that the action is performed only if the condition is met. That way, you avoid doing anything to the variable (even setting it to itself) unless the condition is satisfied.

Nickadoo
  • 104
  • 2
  • 7