GOTCHA #3 Returning value types from a method/property is riskyValue types are either stored on the stack or embedded within objects on the heap. What happens when a property or a method of a class returns a member which is a struct/Structure (i.e., a value type)? It makes a copy of the object. While value types may be passed by reference as method parameters, C# and VB.NET (unlike C++) do not provide any mechanism to return them by reference. Consider Example 1-4. Example 1-4. Example of returning a value typeC# (ReturningValueType) using System; namespace ValTypeProp { struct A { public int val; } class Test { private A theA; public Test() { theA = new A(); } public A MyValue { get { return theA; } set { theA = value; } } [STAThread] static void Main(string[] args) { Test obj = new Test(); A myValue = obj.MyValue; myValue.val = 4; Console.WriteLine(obj.MyValue.val); } } } VB.NET (ReturningValueType) Structure A Public val As Integer End Structure Class Test Private theA As A Public Sub New() theA = New A End Sub Public Property MyValue() As A Get Return theA End Get Set(ByVal Value As A) theA = Value End Set End Property Public Shared Sub Main() Dim obj As New Test Dim myValue As A = obj.MyValue myValue.val = 4 Console.WriteLine(obj.MyValue.val) End Sub End Class In the above example, the MyValue property of the Test class returns the object theA of type A. In Main, you get this property and set its val field to 4. Then you again fetch the property from the Test object (obj) and print its val field. The output from the above program is 0 and not 4. Why? Well, when the property MyValue returns theA, it returns a copy of the structure, not a reference to it. The assignment statement myValue.val = 4 has no effect on obj.MyValue.val. In fact, you will get an error if you try to modify the obj.MyValue property directly. Consider this small change shown in Example 1-5. Example 1-5. Modifying value type returned from a propertyC# (ReturningValueType) //... [STAThread] static void Main(string[] args) { Test obj = new Test(); obj.MyValue.val = 4; Console.WriteLine(obj.MyValue.val); } VB.NET (ReturningValueType) '... Public Shared Sub Main() Dim obj As New Test obj.MyValue.val = 4 Console.WriteLine(obj.MyValue.val) End Sub Now you get a compilation error. In C#, you get the message: error CS1612: Cannot modify the return value of 'ValTypeProp.Test.MyValue' because it is not a variable. In VB.NET, you get: error BC30068: Expression is a value and therefore cannot be the target of an assignment.
IN A NUTSHELLIf you call a method or access a property that returns a value-type object, do not modify it or call mutators (methods that modify its state or data) on it. You are dealing with a copy and any change you make does not affect the real instance. SEE ALSOGotcha #2, "struct and class differ in behavior, Gotcha #4, "You can't force calls to your value-type constructors," and Gotcha #9, "Typeless ArrayList isn't type-safe." |