Friday, May 26, 2006

Deep Clone function for .Net 2.0

This is an update to some code I originally found in CodeBox for .Net. The purpose of the function is to fully clone a given object. The object passed does need to be serialisable. If it is not the function returns Null.


Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary

Public Shared Function DeepClone(Of T )(ByVal source As T) As T
If Not source.GetType().IsSerializable Then
Return Nothing
End If

Dim target As T = Nothing
Using ms As New MemoryStream()
Dim bf As New BinaryFormatter()
bf.Serialize(ms, source)
ms.Position = 0
target = bf.Deserialize(ms)
End Using
Return target
End Function

Tuesday, May 02, 2006

Generics in VB.Net and List.Find()

One of the things i have fallen in love with in .Net 2.0 is generics. With the current project i am working on i have been making extensive use of generics, not just for stronlgy typed collections but also for creating more methods. As with all things there is always something you run up against which can fustrate you more than it should. In this particular it was the Find() function of List.

The problem with the Find() function of List is it requires an instance of System.Predicate() as a parameter which in turn requires the address of the function which it represents.

Dim
instance As New Predicate(Of T)(AddressOf HandlerMethod)

The HandlerMethod() would then contain the logic for determining which instance from the list to return. The BIG problem with this is that you can't pass any other parameters in to the method which means you have to either hardcode the search criteria into the function or if you are trying to match an existing object to one already in the List having to assign it to a global variable. In C# the solution to this is to use anonymous methods but that is not an option in VB.Net.

I spent a couple of hours wrestling with this and was about to resort to just looping through the list until i got a match when i found the following article:
http://blogs.sarkhouston.com/hdierking/archive/2006/03/26/3188.aspx

In this the writer provided a workaround so that an object could be passed in as a parameter. The solution is a little convaluted but it works. Anyway as i was looking at his could i saw an even simpler solution.

For this to work your class will need to implement the IEquatable(Of T) interface

public class MyClass

implements IEquatable(Of MyClass)
private _name as string
public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property

Public Function Equals1(ByVal other As Regulation_Type) As Boolean Implements System.IEquatable(Of Regulation_Type).Equals
return me._name = other._name
end function

Then in the code we can do the following:

dim myList as new List(of MyClass)
dim currentMyClass as MyClass

currentMyClass = New MyClass
currentMyClass.Name = "Bob"

if myList.contains(currentMyClass) then
currentMyClass = myList.Find(New System.Predicate(Of MyClass)(AddressOf currentMyClass.Equals1)
end if