How to Prove Immutabiltiy of String in C#?
Clash Royale CLAN TAG#URR8PPP
How to Prove Immutabiltiy of String in C#?
In my last c# interview,
I was asked to prove immutability of C# string,I know what is meant by immutability of c# string,But is it possible to prove immutability of c# string through code ? can i have a sample code snippet please.
Thanks in advance
Write a loop that concatenate strings then watch the GC go mad and your application burn through memory like crazy?
– Nasreddine
May 16 '16 at 11:54
You cannot - in fact you can indeed prove that you can mutate a string using unsafe code. The best you can do is point to the specification that promises that strings are immutable (in the context of CLR safe code). If your job is programming, you have to get used to trusting the language spec - if the language doesn't do what the spec says, it's a bug for the compiler team to fix. You can demonstrate an example where the string is not mutated, but it doesn't prove anything. There may be constructs where this fails. Until you find one, you have to simply trust the spec.
– J...
May 16 '16 at 11:57
Probably they just wanted to listen how you would approach the problem, your thoughts, discussions and so on. Not really expecting you to prove strings are immutable. Otherwise it was just not very good interview question :)
– Evk
May 16 '16 at 12:00
@M.kazemAkhgary Yes, but this can be done within the confines of C# itself. It's not like we're using a debugger or disassembler or code injection or anything else - just perfectly valid C# code. If the interviewers wanted a more specific answer they should ask a more coherent and specific question.
– J...
May 16 '16 at 12:20
3 Answers
3
I can prove that a string
is not immutable. All I need to do is to show some code which mutates a string
, like so:
string
string
using System;
using System.Runtime.InteropServices;
namespace Demo
class Program
static void Main(string args)
const string test = "ABCDEF"; // Strings are immutable, right?
char chars = new StringToChar str = test.chr;
chars[0] = 'X';
// On an x32 release or debug build or on an x64 debug build,
// the following prints "XBCDEF".
// On an x64 release build, it prints "ABXDEF".
// In both cases, we have changed the contents of 'test' without using
// any 'unsafe' code...
Console.WriteLine(test);
// The following line is even more disturbing, since the constant
// string "ABCDEF" has been mutated too (because the interned 'constant' string was mutated).
Console.WriteLine("ABCDEF");
[StructLayout(LayoutKind.Explicit)]
public struct StringToChar
[FieldOffset(0)] public string str;
[FieldOffset(0)] public char chr;
Now whether this should be considered a bug in C# is a different matter. :)
(The answer is probably that FieldOffset
should be considered to be unsafe
- the code above is purportedly safe
and therefore the string
should not be mutatable.)
FieldOffset
unsafe
safe
string
Also, I think you could legitimately argue that string
is immutable in spirit, even if there are silly edge cases which violate its immutability in supposedly safe code.
string
@samurai I think you may need to consider the logic of the situation more carefully. A string cannot be both immutable and mutable at the same time. Since the former is a proof of a negative, the latter immediately invalidates any supposed proof thereof. The answer to the question of "How can you prove c# strings are immutable" is that you cannot because they are not immutable. Just because they are not mutated in some cases does not prove that they cannot be mutated.
– J...
May 16 '16 at 12:30
@samurai Simple logic, if you can directly prove that
string
is mutable by showing a case where it can be mutated, it means that it cannot be immutable.– Matthew Watson
May 16 '16 at 12:33
string
@Sylverac Also try the code with my latest edit where I added
Console.WriteLine("ABCDEF");
- which doesn't even print "ABCDEF" any more!– Matthew Watson
May 16 '16 at 13:42
Console.WriteLine("ABCDEF");
@Sylverac No, it's not the same at all. The compiler isn't creating the new strings directly itself when you concatenate them - it's the implementation of the concatenation methods inside
String
that does that (have a look at the implementation in the ReferenceSource). These create and return references to new strings. Also note that a str += "XXX"
string concatenation gets turned into a call to str = string.Concat(str, "XXX")
. New strings are created for +=
, but my code does NOT create them.– Matthew Watson
May 16 '16 at 14:30
String
str += "XXX"
str = string.Concat(str, "XXX")
+=
@Sylverac What happens is: Firstly an instance of the
StringToChar
struct is created, with a reference to the string test
assigned to the struct's str
field (note: A reference is assigned, not a copy of the string). Then the chr
field in the struct is used to access the contents of the string as if it was an array of chars (i.e. providing direct access to the string contents). It does this by using FieldOffset(0)
to make the struct act like a C++ union. Finally the code changes the first element of the char array (which changes the underlying string).– Matthew Watson
May 16 '16 at 14:58
StringToChar
test
str
chr
FieldOffset(0)
Yes, It is possible to prove immutability of c# string using ObjectIDGenerator
Class.
ObjectIDGenerator
Following answer is taken from dotmob article on String Vs Stringbuilder in C#
Actually ObjectIDGenerator will return an unique integer value for instances that we created in our programs.With the help of this class we can check whether new instance is created or not for various operations on string and stringbuilder .Consider following program
using System;
using System.Text;
using System.Runtime.Serialization;
class Program
static void Main(string args)
ObjectIDGenerator idGenerator = new ObjectIDGenerator();
bool blStatus = new bool();
//just ignore this blStatus Now.
String str = "My first string was ";
Console.WriteLine("str = 0", str);
Console.WriteLine("Instance Id : 0", idGenerator.GetId(str, out blStatus));
//here blStatus get True for new instace otherwise it will be false
Console.WriteLine("this instance is new : 0n", blStatus);
str += "Hello World";
Console.WriteLine("str = 0", str);
Console.WriteLine("Instance Id : 0", idGenerator.GetId(str, out blStatus));
Console.WriteLine("this instance is new : 0n", blStatus);
//Now str="My first string was Hello World"
StringBuilder sbr = new StringBuilder("My Favourate Programming Font is ");
Console.WriteLine("sbr = 0", sbr);
Console.WriteLine("Instance Id : 0", idGenerator.GetId(sbr, out blStatus));
Console.WriteLine("this instance is new : 0n", blStatus);
sbr.Append("Inconsolata");
Console.WriteLine("sbr = 0", sbr);
Console.WriteLine("Instance Id : 0", idGenerator.GetId(sbr, out blStatus));
Console.WriteLine("this instance is new : 0n", blStatus);
//Now sbr="My Favourate Programming Font is Inconsolata"
Console.ReadKey();
Output Will look like this
Instance id for string get changed from 1 to 2 when str concatenated with “Hello World”.while instance id of sbr remains same as 3 after append operation also. This tells all about mutability and immutability. blStatus variable indicate whether the instance is new or not.
You can find complete article on the topic from : http://dotnetmob.com/csharp-article/difference-string-stringbuilder-c/
let me check it first, if it is correct i will accept your answer
– BinaryOf Sam
May 16 '16 at 12:03
This only proves that the operators and methods you are testing create new string instances. It does not prove that strings are always immutable. See J's comment below the question why it's not possible to prove in a mathematical/scientific meaning of prove.
– René Vogt
May 16 '16 at 12:08
thanks for the article
– samurai
May 16 '16 at 12:22
‒1 for the verifably false statement
It is possible to prove immutability of c# string
, will switch to upvote if you edit your answer to remove this assertion and incorporate information provided by @RenéVogt– Chris Marisic
May 1 '17 at 22:11
It is possible to prove immutability of c# string
A simple example:
string str = "test";string str2 = str;Console.WriteLine(str2);
string str = "test";string str2 = str;Console.WriteLine(str2);
//output: test
str = "DDD";Console.WriteLine(str2);
str = "DDD";Console.WriteLine(str2);
//output: test
Try this code, if string is mutable, "str2" should be "DDD".
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Check the object references of both the string objects, they would be same.
– Marshal
May 16 '16 at 11:54