I'm trying to create an extension method to simplify a small bit of code that I use a lot:
var test = "this is a test.";
var substring = test.Substring(0, 4);
test = test.Remove(0, 4).Trim();
After running the aforementioned code snippet and printing the resulting values for test
and substring
to a console window, you'll see:
this
is a test.
I'd like to simplify it with an extension method which would be an effective overload of Substring
:
public static string Substring(this string input, int startingIndex, int length, bool removeFromInput = false) {
var substring = input.Substring(startingIndex, length);
if (removeFromInput)
input = input.Remove(startingIndex, length);
return substring;
}
This would allow my code going forward to be simplified to:
var test = "this is a test.";
var firstWord = test.Substring(0, 4, removeFromInput: true).Trim();
var secondWord = test.Substring(0, 2, removeFromInput: true).Trim();
var thirdWord = test.Substring(0, 1, removeFromInput: true).Trim();
var lastWord = test.Substring(0, 4, removeFromInput: true).Trim();
Let's not get pedantic and focus on the fact that I could just split on whitespace here; this isn't a universal example, and more often than not it's not focused on words but rather particular substrings.
After looking around the web for a bit, I understand why this doesn't work for value types (here is a post on that), but string
is a reference type, though it's treated as a value type in many cases (here is a post on the topic). Is this another one of those cases? If so, why?
Why can't I update the value of a string in an extension method?
I'm not looking for alternatives, I'm trying to understand why this doesn't work since string
is a reference type. My alternative implementation is test.Substring(0, 4, removeFrom: ref test)
which I think still reads well.
The problem here is that although the string
is a reference type, when you pass a parameter to a method that reference is copied. So a new variable is created that points to the same object in memory. When you make that variable point to a new object, it doesn't affect the original object.
Here is an example to clarify what I mean:
var foo = "foo";
var bar = foo;
bar = "bar";
We create a string and store it's reference in the foo
variable. Then we create a bar
variable and store the reference of foo
in it. This is a copy of the reference, now 2 variables are pointing to the same object.
When we create a new string and assign it to bar
, it doesn't affect foo. Now the bar
just holds a reference to a different object.
There is a way to make it so that the original parameter is modified and reference is not copied, and it can be done by using ref
parameters. But as far as I know ref
modifier is not supported for the first parameter of extension methods.