字符串构造函数

时间:2014-06-13 13:27:29

标签: c# string constructor

我们可以说,

string myString = "Hello";

哪个'神奇'构造一个保存该值的新字符串对象。

为什么不能对我们在代码中定义的类创建的对象使用类似的'无构造'方法? VS对string的“魔力”是什么?对于enum s?

我从来没有看到过如何运作的解释。

4 个答案:

答案 0 :(得分:25)

基本上,它是C#语言规范的一部分:字符串文字,数字文字,字符文字和布尔文字的语法,但这就是全部。

编译器使用这些文字生成IL,对于大多数,它们有一个适合“特定类型的常量”的指令,因此它直接表示。一个例外是decimal,就CLR而言不是原始类型,因此必须有额外的支持。 (例如,这就是在应用属性时无法指定decimal参数的原因。)

查看会发生什么的最简单方法是使用ildasm(或类似工具)查看为任何特定位源代码生成的IL。

在创建自己的类方面 - 可以提供从string(或其他)到您自己的类型的隐式转换,但这不会产生完全相同的效果。您可以编写以下源代码:

MyType x = "hello";

...但这不是MyType类型的“常量”...它只是一个初始化器,碰巧使用了隐式转换。

答案 1 :(得分:7)

事实上,您可以为自定义类执行此操作。它是通过从其他类型定义您自己的隐式转换来实现的。它在msdn:http://msdn.microsoft.com/en-us/library/aa288476%28v=vs.71%29.aspx

中得到了很好的报道

这是一个针对字符串修改的示例:

class Email
{
    private string user;
    private string domain;

    public Email(string user, string domain)
    {
        this.user = user;
        this.domain = domain;
    }

    static public implicit operator Email(string value) // magic goes here ;)
    {
        var parts = value.Split('@');
        if (parts.Length != 2)
            return null;

        return new Email(parts[0], parts[1]);
    }

    static public implicit operator string(Email value)
    {
        return "{ User = " + value.user + ", Domain = " + value.domain + " }";
    }
}

class Test
{
    static public void Main()
    {
        Email test = "alice@test.com"

        System.Console.WriteLine("Test: " + test);
    }
}

答案 2 :(得分:5)

C#编译器将其转换为相应的CIL指令:ldstr。您自己的复杂类型没有等效项,因此编译器必须发出newobj CIL指令,该指令调用您的类型的构造函数。您建议的语法将隐藏用户的构造函数调用。

答案 3 :(得分:1)

虽然实际的机制与我在这里描述的略有不同,但是当代码string myString = "Hello"; 执行时,实现字符串并不重要。而是在代码加载时创建字符串。

每个程序集的代码包含一大块二进制数据数据,并与代码一起读入数组。如果代码包含23个不同的字符串文字,那么所有这些文字的内容将与23个条目一起出现在数组中,每个条目列出起始索引和长度中的一个字符串。该过程在概念上类似于:

char[] RawData;  // Gets loaded by the runtime
string [] StringLiterals;

void create_strings()
{
  int numStrings = (int)RawData[0] + 65536*(int)RawData[1];
  StringLiterals= new string[numStrings];
  for (int i=0; i<numStrings; i++)
  {
    int header = i*4+2;
    int startLoc = (int)RawData[header] + 65536*(int)RawData[header+1];
    int length  = (int)RawData[header+2] + 65536*(int)RawData[header+3];
    StringsLiterals[i] = new String(RawData, startOfs, length);
  }
}

如果&#34;您好&#34;恰好是在程序集中定义的第7个字符串,然后是字符&#34; Hello&#34;将出现在条目#7定义的位置的RawData中。上述语句将被翻译为string myString = StringLiterals[7]; - 不创建新对象,而只是返回对加载类时创建的对象的引用。