Using Generics Judiciously

Generics is one of the important features C# offers. It was one of biggest changes when C#2.0. was announced. As it name suggests, It helps developers write generic code using generic (unknown) types that are replaced with actual types at JIT time.

Generic types and functions, of course, offer many advantages e.g. they enhance performance, make code more expressive, move a lot of safety from execution time to compile time etc. One of the advantages which I like most is that it avoids casting and duplicate code, something which we used to do before Generics were introduced. I have used Object type in the past in order to make the code generic when the actual (specific) types were not known in advance.

The thing which I learnt today is the fact that by just looking at the function signatures one can’t decide whether these functions should be converted into Generic. They may share the same name but not the same implementation. For example consider below functions I encountered:



Public Shared Function GetXSLTTransformedXML(ByVal xmlLocation As String, ByVal xsltLocation As String, ByVal args As XsltArgumentList) As String

Dim document As New Linq.XDocument()
Dim xsltTransformer As Xsl.XslCompiledTransform = New Xsl.XslCompiledTransform()
Dim transformedXML As String = String.Empty

Try
document = Linq.XDocument.Load(xmlLocation)
xsltTransformer.Load(xsltLocation, New Xsl.XsltSettings(False, True), New XmlUrlResolver())
transformedXML = GetXSLTTransformedXML(document, xsltTransformer, args)

Catch ex As Exception
Throw ex

End Try

Return transformedXML

End Function

Public Shared Function GetXSLTTransformedXML(ByVal document As Linq.XDocument, ByVal xslt As XslCompiledTransform, ByVal args As XsltArgumentList) As String

Dim memStream As New System.IO.MemoryStream()
Dim writer As XmlTextWriter
Dim streamReader As StreamReader
Dim transformedXML As String = String.Empty

Try
writer = New XmlTextWriter(memStream, System.Text.Encoding.UTF8)
xslt.Transform(document.CreateReader(), args, writer)
writer.Flush()
memStream.Position = 0
streamReader = New StreamReader(memStream)
transformedXML = streamReader.ReadToEnd()

Catch ex As Exception
Throw ex

Finally
memStream.Close()
writer.Close()
End Try

Return transformedXML

End Function

I got excited when I looked at them and thought let’s convert them into one generic function because both share the same signature and differ in parameters. Later, I realized that I will not get the advantage Generics bring to the code if both the functions do not share the same implementation as well.

For example in the above functions, I want to execute a different branch of code based upon the first parameter. Knowing this, If I go on converting them into one Generic function, I will end up type casting the first parameter to decide which code to execute. If I have to type cast it then it kills the whole purpose of using Generics. Not only that, it also kills the intuitiveness of the code also. My fellow developer can easily identify what function to call if he has an XML document location leaving the other implementation for those who have XML document loaded in the cache. If it were Generic, It would be difficult for people.

I don’t mean that Generics is bad in anyway. I believe it is just not best for this kind of situation. If I have a MakeList<T> kind of function, I would not think twice.


Public Function MakeList(of T)(ByVal first As T, ByVal second As T) As List
'Builds the same list containing parameters irrespective of their types.
End Function

HTH,

0 comments:

Post a Comment