Visual Basic 2008 9.0 .NET Examples and Ebook

New in Visual Basic 2008 - 9.0

Introduction to Visual Basic

Volgend Onderwerp

Extension Methods

Vorig Onderwerp

Argument Passing

|

Relaxed Delegates

Volgend Onderwerp
Extension Method Precedence

Extension Method Precedence

Extension Methods in Interfaces

Extension Methods in Interfaces

Multiple Inheritance through Interfaces and Extension Methods

Multiple Inheritance through Interfaces and Extension Methods

When to Use Extension Methods

When to Use Extension Methods



In Visual Basic 9.0 ( 2008 ) types can be extended with extra methods ( Subs or Functions ). This can be done without the creating a derived type to define the extensions in.

Classes, structures, delegates and interfaces can be extended with extra methods.

These extra methods are called "extension methods".

Extension methods are not defined within the type they extend, but are always defined in an "extension module". Such a module can define extension methods when these methods are marked with the System.Runtime.CompilerServices.Extension attribute.

The first argument of the extension method needs to be of the type being extended.
When a call is made to this ( instance ) extension method, on an object of the type being extended, no argumentvalue has to be provided. The implemenation of the extension method is then executed on that object.

In the following example type Person is extended with a Print method.
This method can now be called on an object of that type (1).


Public Module PersonExtension
    <System.Runtime.CompilerServices.Extension()> _
    Public Sub Print(ByVal aPerson As Person)
        If aPerson IsNot Nothing Then
            Console.WriteLine("Istance of Person : " & aPerson.ToString())
        Else
            Console.WriteLine("No instance of Person.")
        End If
    End Sub
End Module
Public Class Person
    Private m_Name As String
    Public Property Name() As String
        Get
            Name = m_Name
        End Get
        Set(ByVal value As String)
            m_Name = value
        End Set
    End Property
    Public Overrides Function ToString() As String
        ToString = Name
    End Function
End Class
Public Class Student : Inherits Person
    Private m_ClassGroup As String
    Public Property ClassGroup() As String
        Get
            ClassGroup = m_ClassGroup
        End Get
        Set(ByVal value As String)
            m_ClassGroup = value
        End Set
    End Property
    Public Overrides Function ToString() As String
        ToString = Name & " (" & ClassGroup & ")"
    End Function
End Class
Public Class Example1
    Public Shared Sub Main()
        Dim person1 As Person = New Person With {.Name = "John"}
        Dim person2 As Person = New Student _
                                With {.Name = "Jane", _
                                      .ClassGroup = "Visual Basic .NET"}
        Dim person3 As Person
        '
        person1.Print()                                                    ' (1)
        person2.Print()
        person3.Print()
        '
        Console.ReadLine()
    End Sub
End Class
Download Broncode

Output :

 Istance of Person : John
 Istance of Person : Jane (Visual Basic .NET)
 No instance of Person.

Besides the argument specifying the type being extended, other arguments can be used.

In next example CounterExtension defines a extension method ToString with two arguments (1). The second argument is the paddingLenght used when converting the Counter to a String.
The call to this extension method (3) only provides a value for that argument.

Type Counter is extended with three methods to convert Counter objects to Integers or to Strings.


Public Class Counter
    Private m_Value As Integer
    Public ReadOnly Property Value() As Integer
        Get
            Value = m_Value
        End Get
    End Property
    Public Sub Raise()
        m_Value += 1
    End Sub
    Public Sub Lower()
        m_Value -= 1
    End Sub
    Public Overrides Function ToString() As String
        ToString = "Counter.Value : " & Value.ToString()
    End Function
End Class
Public Module CounterExtension
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToInt32(ByVal aCounter As Counter) As Integer
        ToInt32 = aCounter.Value
    End Function
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToString(ByVal aCounter As Counter) As String
        ToString = aCounter.Value.ToString()
    End Function
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToString(ByVal aCounter As Counter, _
                             ByVal paddingLength As Integer) As String     ' (1)
        ToString = aCounter.Value.ToString().PadLeft(paddingLength)
    End Function
End Module
Public Class Example2
    Public Shared Sub Main()
        Dim counter1 As New Counter
        counter1.Raise()
        counter1.Raise()
        '
        Dim integerValue1 As Integer = counter1.ToInt32()
        Console.WriteLine(integerValue1)
        '
        Dim stringValue1 As String = counter1.ToString()                   ' (2)
        Console.WriteLine(stringValue1)
        '
        Dim stringValue2 As String = counter1.ToString(3)                  ' (3)
        Console.WriteLine(stringValue2)
        '
        Console.ReadLine()
    End Sub
End Class
Download Broncode

Output :

 2
 Counter.Value : 2
   2

Extension Method Precedence


The call made on line (2) will not call the extension method, but calls the normal ( from Object inherited ) ToString method.
The extension method ToString is not accessible because the normal method has a higher priority, and therefore precedes that extension method.

Several extension methods, with identical signatures ( and a certain name ), can be loaded. In that case calls to methods with that certain name are ambiguous. The closest method always has priority.

For instance extension methods defined in namespace imports of the current sourcecodedocument will precede the extension methods defined in the namespace imports made in the project/assembly.


Klik hier om terug naar boven te gaan.  Up



Extension Methods in Interfaces


Extension methods can be defined for Interfaces.

In next example extension method SomeSecondMethod is added to SomeInterface.


Public Interface SomeInterface
    Sub SomeFirstMethod()
End Interface
Public Module SomeInterfaceExtension
    <System.Runtime.CompilerServices.Extension()> _
    Public Sub SomeSecondMethod(ByVal aSomeInterface As SomeInterface)
        Console.WriteLine("SomeInterface.SomeSecondMethod() implementation.")
    End Sub
End Module
Public Class SomeClass : Implements SomeInterface
    Public Sub SomeFirstMethod() Implements SomeInterface.SomeFirstMethod
        Console.WriteLine("SomeClass.SomeFirstMethod() implementation.")
    End Sub
End Class
Public Class Example3
    Public Shared Sub Main()
        Dim object1 As New SomeClass
        object1.SomeFirstMethod()
        object1.SomeSecondMethod()
        '
        Console.ReadLine()
    End Sub
End Class
Download Broncode

Output :

 SomeClass.SomeFirstMethod() implementation.
 SomeInterface.SomeSecondMethod() implementation.

Normally interfaces only hold abstract members, members without an implemenation. An interface is used to define which members an implementing type should have, and is not used to define what needs to happen when those members are called on an object of that implementing type.

Still when interfaces are extended, only concrete methods, with an implementaion, can be added. Extensions are defined in modules, which can only define concrete members.


Klik hier om terug naar boven te gaan.  Up



Multiple Inheritance through Interfaces and Extension Methods


When SomeInterfaceExtension ( from the above example ) is loaded, all types implementing SomeInterface will contain SomeSecondMethod and its implementation.

This is a little strange. So far implementing an interface was a form of "contextual inheritance", making sure the implementing type could be used in a certain context. But when an extended interface is implemented, a implementation is inherited ( "implemenational inheritance" ).

Visual Basic uses single ( implementational ) inheritance, but when several extended interfaces are implemented, a form of "multiple implemenational inheritance" is used.


Public Interface Interface1
End Interface
Public Interface Interface2
End Interface
Public Module InterfaceExtensions
    <System.Runtime.CompilerServices.Extension()> _
    Public Sub Method1(ByVal aInterface1 As Interface1)
        Console.WriteLine("Interface1.Method1")
    End Sub
    <System.Runtime.CompilerServices.Extension()> _
    Public Sub Method2(ByVal aInterface2 As Interface2)
        Console.WriteLine("Interface2.Method2")
    End Sub
End Module
Public Class Class1 : Implements Interface1, Interface2
End Class
Public Class Example4
    Public Shared Sub Main()
        Dim object1 As New Class1
        object1.Method1()
        object1.Method2()
        '
        Console.ReadLine()
    End Sub
End Class
Download Broncode

Output :

 Interface1.Method1
 Interface2.Method2

Klik hier om terug naar boven te gaan.  Up


When to Use Extension Methods


Extension methods are usually suitable to extend types of which you are not the owner.

You should consider using inheritance when an inheritable class needs to be extended. This should still be the preferable technique to extend types.

When a type needs to be extended in a specific context, for instance the context of a console application, and not in other contexts, extension methods are appropriate.
The first example of this topic defined a Person type, that could be extended in the context of a console application with the Print method.
This extension was only usefull in console applications, so should not be permanently added to Person, and is merely usefull when Person is used in that context.

The implementation defined in an extension method is limited to using the public members of the type being extended. Encapsulated members can not be used. Therefore extension methods have limited implemenational capabilities.

Usually extension methods are defined in a child namespace of the classlibrary. This way clients can chose whether or not tho load those extensions.

Next example simulates the library AdministrationClassLibrary. This library holds a Administration namespace with a Person classdefinition.


Namespace Administration
    Public Class Person
        Private m_Name As String
        Public Property Name() As String
            Get
                Name = m_Name
            End Get
            Set(ByVal value As String)
                m_Name = value
            End Set
        End Property
        Public Overrides Function ToString() As String
            ToString = Name
        End Function
    End Class
End Namespace
Download Broncode

A child-namespace could define some ConsoleExtensions which are suitable in case the Administration types are used within a console application.


Namespace Administration
    Namespace ConsoleExtensions
        Public Module PersonExtension
            <System.Runtime.CompilerServices.Extension()> _
            Public Sub Print(ByVal aPerson As Person)
                System.Console.WriteLine(aPerson.ToString())
            End Sub
        End Module
    End Namespace
End Namespace
Download Broncode

An other assembly, like AdministrationConsoleApplication can now decide to load those ConsoleExtensions by importing that namespace.


Imports Administration.ConsoleExtensions               ' or on project-level (1)
Public Class Application
    Public Shared Sub Main()
        Dim person1 As New Administration.Person With {.Name = "John"}
        'person1.Print()                                                   ' (1)
        '
        Console.ReadLine()
    End Sub
End Class
Download Broncode

A window application would not load these extension.





This version ( published on 2008-06-24 ) is printed from http://www.studyvb.com, visit the website for more recent information.

Updated On : 2008-04-11

Download Broncode

Published On : 2008-06-24

Extension Methods

Vorig Onderwerp

Argument Passing

|

Relaxed Delegates

Volgend Onderwerp

New in Visual Basic 2008 - 9.0

Introduction to Visual Basic

Volgend Onderwerp
Nederlands  Nederlands

Add to favorites (IE).