GOTCHA 25 Access to staticShared members isn t enforced consistently


GOTCHA #25 Access to static/Shared members isn't enforced consistently

A static/Shared method belongs to a class and not to any specific instance. Furthermore, it is never polymorphic. C# has taken the high road of disallowing the call to static members using an object reference. Unfortunately, VB.NET does not impose the same restriction. The downside to calling Shared members on a reference is that it may lead to confusion at times. Consider Example 3-17.

Example 3-17. Invoking Shared member using a reference

C# (Shared)

C# does not allow the call to static members using an object reference. So this is not an issue for C# programmers. It only concerns VB.NET, C++, and Java programmers.

C# (VB.NET (Shared))

 'Base.vb Public Class Base  Public Overridable Sub Method1() Console.WriteLine("Base.Method1")  End Sub  Public Shared Sub Method2()  Console.WriteLine("Base Method2")  End Sub End Class 'Derived.vbPublic Class Derived  Inherits Base  Public Overrides Sub Method1()  Console.WriteLine("Derived.Method1")  End Sub  Public Shared Sub Method2() "Derived Method2")  End Sub End Class 'Test.vb Public Class Test  Public Shared Sub Run(ByVal b As Base)  b.Method1()  b.Method2()  End Sub  Public Shared Sub Main()  Dim object1 As New Derived  Console.WriteLine("--------- Using object of Derived")  object1.Method1()  object1.Method2()  Run(object1)  End Sub End Class 

In the VB.NET version of Example 3-17, there is a class named Base and a class named Derived that inherits from Base. Base has an overridable method named Method1() and a Shared method named Method2(). The Derived class overrides Method1() and also provides a Shared method named Method2().

In the Test code, you create a Derived object, then call Method1() and Method2() on it using the object reference object1. Next you pass the reference object1 to a method Run(), which treats it as a Base type. Within the Run() method you are still dealing with an object of Derived. When the Run() method invokes the two methods using the Base type reference, the method invoked for the call to Method1() is on Derived due to polymorphism. However, the method invoked for the call to Method2() is on Base, not on Derived, even though the object being pointed to by the reference is of type Derived. When the program executes, you get the output shown in Figure 3-12.

Figure 3-12. Output from Example 3-17


Note that when the code is compiled a warning is generated for Method2() of Derived. It recommends that you mark Method2() with the Shadows keyword. Marking it Shadows will not change the output of the program, however. The call to Method1() using the Base reference is polymorphic and goes to the Derived class's Method2(). However, the call to Method2() is not polymorphic. Within the Run() method, it is statically bound to the method of Base at compile time. As a result, Method2() of Base is invoked rather than Method2() of Derived. In fact, when a Shared method is accessed using an object reference, the compiler replaces the object reference with the class name at the time of compilation. In this example, b.Method2() is replaced by Base.Method2(). While the call b.Method1() results in a polymorphic callvirt instruction in MSIL, the call to b.Method2() simply becomes a static call. Figure 3-13 shows the MSIL generated from the above code.

Figure 3-13. MSIL for Run() method in Example 3-17


Given that static/shared methods are not polymorphic, it is easy to get confused if they are invoked using an object reference, especially if the static/Shared methods are part of the derived class as well. As a good coding practice, you should refrain from calling Shared members using an object reference in VB.NET (and C++ and Java as well). Instead, use the class to access them. Instead of calling b.Method2(), write Base.Method2().

How does this differ in .NET 2.0 Beta 1? The VB.NET compiler issues a warning (not an error) if you access a Shared member using an object reference. The warning generated is:

     warning BC42025: Access of shared member through an instance; qualifying expression     will not be evaluated. 

If you configure Visual Studio to treat warnings as errors (see Gotcha #12, "Compiler warnings may not be benign"), you will avoid this gotcha.

IN A NUTSHELL

Refrain from accessing Shared members of a class through an object reference. Use the class to access them.

SEE ALSO

Gotcha #12, "Compiler warnings may not be benign, Gotcha #27, "Object initialization sequence isn't consistent," and Gotcha #28, "Polymorphism kicks in prematurely."



    .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