我们可以说,
string myString = "Hello";
哪个'神奇'构造一个保存该值的新字符串对象。
为什么不能对我们在代码中定义的类创建的对象使用类似的'无构造'方法? VS对string
的“魔力”是什么?对于enum
s?
我从来没有看到过如何运作的解释。
答案 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];
- 不创建新对象,而只是返回对加载类时创建的对象的引用。