注意:这是一个假设的讨论。我实际上并不想实现struct String。
.Net String类可以是值类型(结构),因为它是不可变的并且成员很少。但String不是值类型。可能是因为String是在引入可空类型之前设计的,或者可能是为了匹配Java字符串的行为。
将String更改为值类型或实现String的值类型变体是否有益?它将删除一个间接级别并匹配常见的非可空案例。
答案 0 :(得分:7)
简答
字符串具有以具有引用类型成员(例如,char[]
)以便具有可变大小。因此,任何struct String
类型实际上只是伪装成值类型的引用类型。
中等答案
我更深入地讨论了这个问题here。但我的想法的基本要点是:是的,你可能有一个字符串“值类型”,大概是这样的:
public struct String
{
char[] m_characters;
public String(IEnumerable<char> characters)
{
m_characters = characters.ToArray();
}
public char this[int index]
{
get { return m_characters[index]; }
}
// All those other string functions... IndexOf, Substring, etc.
}
......但实在没有意义。上面的内容实际上只是一个嵌套在shell中的引用类型(围绕char[]
的包装器),看起来像一个值类型。此外,当您以这种方式设计类型时,您会遇到使用值类型(例如,拳击的潜力)而没有任何好处的缺点(上述String
类型的实例具有与以下相同的内存分配要求它包装的参考类型,所以它从GC的角度来看也没有任何东西。)
答案 1 :(得分:3)
没有。 .Net中的值类型必须在编译时具有已知的大小。 string
的大小通常仅在运行时确定,因此不能作为值类型进行建模。
另外,.Net中的类型是Value类型,只能有1个大小。或者更简单地说,不同大小的相同值类型的不同实例。这意味着您需要将不同长度的字符串表示为不同类型。例如,"dog"
和"zebra"
将是不同的不兼容类型
注意
似乎这个问题可以用两种方式解释
string
成为没有备用存储空间的值类型string
成为值类型并允许在数组中进行备用存储我的答案是针对情景#1。看起来场景#2似乎没有很多价值,因为它只是用具有嵌入式引用类型的值类型替换引用类型。
答案 2 :(得分:2)
这确实是一种有效的实施方式。
非常天真,它看起来像这样:
struct String {
readonly char[] _buffer;
// Methods etc. …
}
与string
类相比,有一个特点(除了它不能是null
之外):零大小的字符串不是以空值终止的!据我所知,.NET字符串 以空值终止,以便与旧版C API(WinAPI)进行交互。
有一点,字符串类有一个优点:实习可以更容易实现:String.Intern
是一种构建器函数,给定相同的字符串值,总是返回相同的string
实例。这样,两个实习字符串a
和b
的比较可以大大加快:现在足以测试它们的地址。
但是,当然,通过比较字符串结构是否共享相同的地址,可以为字符串结构实现类似的字符串实习。
答案 3 :(得分:0)
没有。任何给定类型的结构总是具有相同的长度。字符串的不同实例不会。