Back in a previous job, we had technical interviews for prospective employees. I went through one myself and it was tough. I was sure I bombed it, because one guy found a weak spot in my knowledge and kept drilling into it. As it turns out, I did ok and they hired me.
In a year's time I had climbed the ranks and suddenly found myself doing technical interviews on the other side of the desk. One of the things that I was tasked with was writing better technical questions for .NET programmers and analysts. I and the coder types I gathered with at work all pitched in make a great tech interview to be given over the phone before bringing in the candidate for a face-to-face.
Once I started doing the interviews, I discovered just how poor the pool of available talent was. I guess it might have been more a reflection on the headhunters sending us the candidates. But sometimes I thought I was asking a little much with some of the questions. I'm not going to divulge the questions, but I want to discuss one of them because it is pretty interesting. It's also the most devious. I only found one person who could answer it correctly. And to be fair, I couldn't have answered it myself.
And by the way, if you have the opportunity to cheat on a phone interview. For example, someone you know inside the company finds the document containing all the questions and answers and distributes it to your consulting company or just to friends. Don't be an idiot. We know when you are cheating. I had one case of blatant cheating where the answers given back to me were nearly word for word what was in my Q&A spreadsheet. The sad part was, we brought the person in for a face-to-face interview and asked questions from an alternate question pool (one that wasn't in a document on the network) and her skills were fine. She didn't even need to cheat.
But anyways, the trick question. The question was asking the difference between ByVal and ByRef and how they apply to classes and structures. There is a difference and those that didn't know it but tried to be confident when giving their answers were completely demoralized when asked to describe the difference.
If you've done any MCSA/MCSD certification training, you may recall this topic is discussed. I remember it from my training, but I also remember thinking at the time "who cares?" It can have consequences if you don't pay attention to it. It'd probably be one of those bugs that after days of research you'd share with your peers: "Hey, did you know..."
So here's the trick: There is no ByVal when you are passing a class to a method. There is only ByRef. So if you pass a class to a method using ByVal, you are working on the original class, not a copy. If you pass a structure to a class ByVal, you are working on a copy. You can pass a structure ByRef and you will work on the original.
Why? Because of the way .NET allocates memory. There is the Stack and the Heap. The Stack is small and efficient, the Heap is big and disorganized. but the Heap can hold lots of stuff. The stack is reserved for value types - small data structures like Booleans and Integers - while the Heap holds big things like Strings and Classes. A Structure is a value type even though it can have properties and methods like a class. A class is an Object type, and all objects go on the heap.
Since classes are big, when you pass a class to a method, it only sends a pointer to the class of where the instance of the class is on the heap, AKA, a reference, By Reference, ByRef, even though it says ByVal, it's not true.
But, but, what if a class has a structure as a property? And what if a structure has a class as a property? When does it reference it and when does it copy it? Well, let's see.
Make a class and a structure with the opposite inside each:
Public Class WithStruct
Public struct As InsideStructure
Public text As String
Public number As Integer
Public Structure InsideStructure
Public text As String
Public number As Integer
End Structure
End Class
Structure WithClass
Public cl As WithStruct
Public text As String
Public number As Integer
End Structure
Make some methods to modify the guts:
Private Sub ModifyInternals(ByVal obj As WithStruct)
obj.text = "Modified"
obj.number = -1
obj.struct.text = "Inner modified"
obj.struct.number = -10
End Sub
Private Sub ModifyInternals(ByVal obj As WithClass)
obj.text = "Modified"
obj.number = -1
obj.cl.text = "Inner modified"
obj.cl.number = -10
End Sub
Make the objects and call them and look at the results:
Structure (before and after):
Text:The text, Number:1, InnerText:Inside text, InnerNumber:10
Text:The text, Number:1, InnerText:Inner modified, InnerNumber:-10
Class (before and after):
Text:The TEXT, Number:2, InnerText:Inside TEXT, InnerNumber:20
Text:Modified, Number:-1, InnerText:Inner modified, InnerNumber:-10
Summary: The structure maintained its original values, but the class inside the structure was modified. The class was modified and so was its internal structure.
Is your head spinning yet? Good.