VB.NET: إذا قمت بتمرير سلسلة Byval في وظيفة ولكن لا تغير السلسلة ، هل لدي سلسلتين أو سلسلتين في الذاكرة؟
سؤال
أعلم أن الأوتار غير قابلة للتغيير ، لذا في اللحظة التي تقوم فيها بتغيير قيمة مرجع السلسلة. NET تجعل سلسلة جديدة على الكومة.
لكن ماذا لو لم تفعل يتغيرون قيمة مرجع السلسلة ؛ بدلا من ذلك ، يمكنك ببساطة تمريرها إلى وظيفة ByVal
- هل تقوم هذه العملية بنسخ قيمة السلسلة على الكومة أيضًا؟ ميلي هو "لا" ، لكنني أود التأكيد.
فمثلا:
Public Function IsStringHello(ByVal test As String) As Boolean
Return (String.Compare(test, "Hello") = 0)
End Function
برنامج الاتصال:
Dim myWord as String = "Blah"
Dim matchesHello as Boolean = IsStringHello(myWord)
أنا أعرف المرور myWord
بالقيمة تجعل نسخة من المرجعي إلى "بلاه" ، لكن بما أنني لم أحاول تغيير السلسلة نفسها ، فهل ستجعل نسخة أخرى من السلسلة على الكومة؟
المحلول
بالمناسبة ، لا علاقة لها بالتداخل تمامًا. قاعدة تمرير المعلمات إلى الوظائف هي نفسها بالنسبة لجميع أنواع المرجع (وحقا ، جميع الأنواع) ، بغض النظر عن كيفية إدارتها داخليًا.
القاعدة بسيطة وقد ذكرت ذلك بشكل صحيح: تمرير بنسخ القيمة المرجعي, ، ليس استهداف. لا يتم نسخ مساحة كومة هنا.
نصائح أخرى
لا. لا يزال يستخدم نسخة من المرجع إلى "بلاه".
ما الذي يجعلك تفكر ، سوف؟
على ملاحظة جانبية ، يتم تدريب السلسلة.
string s = "hello";
string t = "hello";
يشير S&T إلى نفس السلسلة (لأنه يتم تدريبه). إذا قمت بتعديل S أو T ، فسيقوم بإنشاء سلسلة جديدة ، ثم.
تمرير الكائنات Byval إنشاء نسخة من مؤشر, وليس الكائن نفسه. هذه مظاهرة:
Module Module1
Dim original As String = "Hello world"
Sub PassByReferenceTest(ByVal other As String)
Console.WriteLine("object.ReferenceEquals(original, other): {0}", _
Object.ReferenceEquals(original, other))
End Sub
Sub Main()
PassByReferenceTest(original)
Console.ReadKey(True)
End Sub
End Module
يخرج هذا البرنامج ما يلي:
object.ReferenceEquals(original, other): True
لذلك ، توجد السلسلة الأصلية والسلسلة التي مررنا بها حسب القيمة في نفس العنوان في عنوان الذاكرة. أنت لا تصنع نسخة من السلسلة نفسها.
قصير ، لا. يمرر المرجع إلى السلسلة. مثيل واحد فقط من السلسلة نفسها.
السلسلة هي نوع مرجعي. إذا قمت بتمريرها بالقيمة ، فإن ما تمر به هو قيمة المرجع.
الطريقة الوحيدة التي ستحصل على نسخة أخرى على الكومة هي تغيير قيمة المتغير.
متغير من النوع System.String
يحمل بشكل فعال "معرف الكائن". لنفترض أن Object #1934
هي سلسلة مع الأحرف "Blah"
, ، وأنت تقول Dim myWord As String = "Blah"
. سيتم تخزين المترجم بعد ذلك Object #1934
داخل myWord
. الدعوة IsStringHello(myWord)
ثم يتسبب في استدعاء هذه الوظيفة مع test
المعلمة تساوي Object #1934
. في مثالك ، سيكون هناك متغيران من النوع System.String
في الذاكرة--myWord
و test
, وكلاهما سيحمل المحتوى Object #1934
.