我知道 .NET (因此也包括 VB.NET) 字符串是不可变的。然而,我正在使用 Excel 2010 中的 VBA 7.0。那里的字符串是不可变的吗?我正在进行大量字符串处理,对于小数量的字符串直接操作还可以,但我担心它无法扩展 - 因为从一个字符串移动到另一个字符造成的每个额外字符可能会创建另一个字符串实例。
它们是不可变的,除非它们表现出可变行为,那么它们就不是不可变的。
例如,通过mid$()
进行的赋值比普通的新字符串赋值要快得多。
Dim s As String
s = "ABC"
Debug.Print s, StrPtr(s)
'// -> ABC 122899836
Mid$(s, 1, 1) = "Z"
Debug.Print s, StrPtr(s)
'// -> ZBC 122899836
s = "??" & Right$(s, 1)
Debug.Print s, StrPtr(s)
'// -> ??C 196635748
虽然 VB.NET 字符串是不可变的,正如 System.String 所要求的那样,但 VBA(包括 VB6?)字符串可以被改变(例如使用 Mid$
)。请参见 Alex K's answer 并注意操作后的 StrPtr
结果。
原始答案; 支持文档,反对反例。
VBA字符串是不可变的。
就像VB.NET一样,没有办法在不创建新字符串的情况下“替换部分”或“追加到”字符串。这是否重要 - 因为现代计算机非常快 - 取决于实际算法、数据和环境。
单个数据值是不可变的。这意味着在VBA环境中没有定义机制可以将一个数据值更改为另一个数据值。
其中字符串表示“单个数据值”。
VBA字符串是可变的。Alex K的答案是错误的,但他在Microsoft的VB.Net中关于Mid()=
的欺骗是正确的,后者正确地声称它们是不可变的--https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/strings/string-basics--尽管支持Mid()=
。
因此,在所有VB6、VBA、VB.Net中,您可以使用(例如)Mid(a$,1,2)="hi"
,如Alex的回复所述,来覆盖字符串的部分。然而,正如user2864740指出的那样,只有VB6和VBA能够非常快速地执行此操作。这是VB6(VBA)和VB.Net中经过测试的代码。
Dim n1&, start!, bigstring$
bigstring$ = Space(10 ^ 6)
start = timer() ' in vb.Net this is function with "timer = (DateTime.Now.Ticks - Today.Ticks) / 10000000.0#"
For n1 = 1 To 5000
Mid(bigstring, n1, 1) = "1"
Next
Debug.Print("Elapsed millisecs: " & (timer() - start!) * 1000.0! & " over cycle count of " & n1 - 1)
在超过1兆字节的大字符串上,这种技术对于速度至关重要,因此可扩展。在VBA中,它可以在不到一毫秒的时间内完成。但是,在VB.Net中,效率非常低下--同样的测试在3GHz CPU上需要7秒,每次迭代约为1毫秒。从5000次迭代增加到100万次迭代后,VBA仍然只需要40毫秒。VB.Net需要30分钟。提示:在VB.Net中,您可以使用Dim BigByte() as byte
,然后BigByte = System.Text.Encoding.UTF8.GetBytes(bigstring)
,以便您使用一个字节数组。如何使其灵活和支持Unicode超出了本主题。
Dim a$ = "Hello!" ; Dim b$ = a$ ; Console.WriteLine(ReferenceEquals(a$, b$)) ; MID(a$, 1) = "Goodbye" ; Console.WriteLine(ReferenceEquals(a$, b$))
。这会显示“True, False”(因为使用MID函数会将a$
重新分配到一个_新的_字符串上,同时保留原始字符串不变)。无论使用哪种语言,.NET中的System.String类型都是不可变的。我没有在VB6/VBA中确认这一点。 - user2864740Mid()=
来提高速度的VB6 Web服务器迁移到VB.Net。我需要做比最初预想的更大的改变。 - www-0av-Com
Dim str As String: str = "this string": Debug.Print VarPtr(str), StrPtr(str): Mid(str, 3, 2) = "at": Debug.Print VarPtr(str), StrPtr(str)
- user2140173