views:

200

answers:

6

In C#, strings are reference type but behaves like value type. e.g.

string str = "I am a string";
str.Replace("am", "was");  //str still contains same value, 
//i want it to make "I was a string"

I know i can do this by

str = str.Replace("am", "was");

But i don't want to re-assign it. Is there anyway to make them behave like Reference type?

Additional:

i am having a key-value pair collection(not dictionary) and i want to prefix some text to its key(string), right now i am removing the key-value pair and then creating a new using the same value and adding that in to the collection. i don't want to do this as this doesn't seem to be a right way. I want to update the Key directly.

Edit:

I might get two collection from Model with the same keys having different values in each collection. so inside View-Model i want to alter the keys by prefixing them with a value for first and second collection separately. And will make all keys unique.

+2  A: 

Not directly. You'll need to create your own class that in turn contains a string and that has your own methods to handle Replace and suchlike.

The inevitable question is - why? In what situations are you concerned that string does not behave as it does?

Jeremy McGee
i am having a key-value pair collection(not dictionary) and i want to prefix some text to its key(string), right now i am removing the key-value pair and then creating a new using the same value and adding that in to the collection. idon't want to do this as this doesn't seem to be a right way. I want to update the Key directly.
viky
+8  A: 

Use System.Text.StringBuilder.

If you can't use StringBuilder try to read here http://www.codeproject.com/KB/dotnet/strings.aspx

See "Direct Modifications of Strings".

Unholy
i can't use StringBuilder in my case
viky
@Henk Holterman: StringBuilder only exposes some of the methods that string does. Replace IS present both in string and StringBuilder, but what about, for example - Substring? You would have to hack StringBuilder with two Remove calls to achieve same result.
maciejkow
sb.ToString().Substring() ?
kenny
@Kenny: this won't modify StringBuilder's content
maciejkow
StringBuilder is only useful for speeding up operations on (very) large strings. It has no benefit here over `s = s.Replace()`.
Henk Holterman
+3  A: 

No, strings are immutable (once created, you cannot change them). However, if you really (I can't imagine a situation where this would be acceptable for me) need this, you can create your own class (let's name it MutableString), which would expose similar public API to string, but will handle those reassignments internaly, and will implicitly cast from/to string.

EDIT: Remember to override GetHashCode() and Equals(), otherwise your collection will not work. However - it's recommended that hash code remained constant - so basically, all you can resonably do is to return 0 for every MutableString. This WILL be a performance issue if you use this as a key in collections that rely on hashcode (like Dictionary) - be aware of that.

maciejkow
... or just use a `StringBuilder` ...
Joe
@Joe see comment on @Unholys answer.
James
@Joe: StringBuilder only exposes part of the string api.
maciejkow
that seems to be a working, let me try!
viky
+3  A: 

Your options are basically:

  • leave well alone (highly recommended)
  • create your own string class (why? hilarity will ensue if other developers downstream don't know your intentions)
  • use the StringBuilder to concatenate strings together in a memory light fashion (probable solution to most your issues)
bakasan
+3  A: 

No, strings are meant to be immutable (unchange-able). If you need to constantly append to a string, use System.Text.StringBuilder (MSDN) and use the Append method.

var sb = new StringBuilder();
sb.Append("I");
sb.Append(" am");
sb.Append(" still");
sb.Append(" a string");
Console.WriteLine(sb.ToString());
Daniel May
+1. As far as i can get OP expects a way of trying to change "contents" of string. That's pretty much impossible( unless there is "unsafe" way of doing it). StringBuilder is only option i guess.
PRR
PRR: not really, a StringBuilder only lets you mutate a __copy__ of the string. And then you have to put it back...
Henk Holterman
yes, if you were to change value of string few times, you would use Stringbuilder as it allows appending to the same reference (as long as the capacity is not reached)
PRR
You don't have to specify a capacity - a `StringBuilder` without a capacity will automatically resize to the necessary length. Initialising with a specified capacity has been proven to be faster, but only slightly.
Daniel May
@Daniel May: i meant as long as the capacity is not "reached", the same reference is returned. If the capacity exceeds i guess a new reference is returned. So you can make changes to the same reference (is faster) as compared to string which is immutable.
PRR
+2  A: 

You could just create a helper method that updates the string for you e.g.

public static class StringHelper
{
    public static void Replace(ref string originalStr, string strToReplace, string replaceStr)
    {
         originalStr = originalStr.Replace(strToReplace, replaceStr);
    }
}

Usage

var str = "I am a string";
StringHelper.Replace(ref str, "am", "was");
James
I hadn't thought of that, very intuitive
Daniel May
Henk, check first what collection you are using. Does it support mutable keys? Most don't as they rely on constant hashcode and equals / compareTo results!
Florian Doyon
doesn't originalStr = originalStr.Replace(strToReplace, replaceStr); creates a new string? strings are immutable, so this returns a new string(even though you used "ref"). The original string "I am a string" is discarded and a new string "I was a string" is referenced..
PRR