C#中如何证明字符串的不变性?
How to Prove Immutabiltiy of String in C#?
在我上次c#面试中,
我被要求证明C#字符串的不可变性,我知道c#字符串的不可变性是什么意思,但是是否可以通过代码证明c#字符串的不可变性?请给我一个示例代码片段。
提前致谢
是的,可以使用 ObjectIDGenerator
Class.
证明 c# 字符串的不变性
Following answer is taken from dotmob article on String Vs Stringbuilder in C#
实际上 ObjectIDGenerator 将为我们在 programs.With 中创建的实例 return 一个唯一的整数值 借助此 class 我们可以检查是否为各种创建了新实例string 和 stringbuilder 上的操作。考虑以下程序
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 : {0}\n", 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 : {0}\n", 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 : {0}\n", 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 : {0}\n", blStatus);
//Now sbr="My Favourate Programming Font is Inconsolata"
Console.ReadKey();
}
}
输出将如下所示
当 str 与“Hello World”连接时,字符串的实例 ID 从 1 变为 2。而 sbr 的实例 ID 在追加操作后也保持为 3。这说明了有关可变性和不变性的所有信息。 blStatus 变量表示实例是否是新的。
您可以从以下位置找到有关该主题的完整文章:http://dotnetmob.com/csharp-article/difference-string-stringbuilder-c/
我可以证明 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;
}
}
现在这是否应该被视为 C# 中的错误是另一回事。 :)
(答案可能是 FieldOffset
应该被认为是 unsafe
- 上面的代码据称是 safe
因此 string
不应该是可变的。)
此外,我认为您可以合理地争辩说 string
在精神上是不可变的,即使在所谓的安全代码中存在违反其不可变性的愚蠢边缘情况。
在我上次c#面试中,
我被要求证明C#字符串的不可变性,我知道c#字符串的不可变性是什么意思,但是是否可以通过代码证明c#字符串的不可变性?请给我一个示例代码片段。
提前致谢
是的,可以使用 ObjectIDGenerator
Class.
Following answer is taken from dotmob article on String Vs Stringbuilder in C#
实际上 ObjectIDGenerator 将为我们在 programs.With 中创建的实例 return 一个唯一的整数值 借助此 class 我们可以检查是否为各种创建了新实例string 和 stringbuilder 上的操作。考虑以下程序
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 : {0}\n", 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 : {0}\n", 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 : {0}\n", 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 : {0}\n", blStatus);
//Now sbr="My Favourate Programming Font is Inconsolata"
Console.ReadKey();
}
}
输出将如下所示
当 str 与“Hello World”连接时,字符串的实例 ID 从 1 变为 2。而 sbr 的实例 ID 在追加操作后也保持为 3。这说明了有关可变性和不变性的所有信息。 blStatus 变量表示实例是否是新的。
您可以从以下位置找到有关该主题的完整文章:http://dotnetmob.com/csharp-article/difference-string-stringbuilder-c/
我可以证明 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;
}
}
现在这是否应该被视为 C# 中的错误是另一回事。 :)
(答案可能是 FieldOffset
应该被认为是 unsafe
- 上面的代码据称是 safe
因此 string
不应该是可变的。)
此外,我认为您可以合理地争辩说 string
在精神上是不可变的,即使在所谓的安全代码中存在违反其不可变性的愚蠢边缘情况。