|
|
 |
|
|
|
|
Visual Basic 2008 9.0 .NET Examples and Ebook
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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()
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
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()
Console.WriteLine(stringValue1)
Dim stringValue2 As String = counter1.ToString(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. |
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. |
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 |
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
Public Class Application
Public Shared Sub Main()
Dim person1 As New Administration.Person With {.Name = "John"}
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|