GOTCHA 3 Returning value types from a methodproperty is risky


GOTCHA #3 Returning value types from a method/property is risky

Value 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 type

C# (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 property

C# (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. 

If you replace struct/structure with class you get the intuitive result of 4 instead of 0.


IN A NUTSHELL

If 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 ALSO

Gotcha #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."



    .NET Gotachas
    .NET Gotachas
    ISBN: N/A
    EAN: N/A
    Year: 2005
    Pages: 126

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net