I wrote a program in VS 2012 with default targeting for .Net 4.5, and was later asked what is the absolutely minimal .Net version required. Re-targeting for 4.0 popped no errors, although 3.5 and earlier versions seemed not so compatible at first. But I knew for sure that I didn’t use any “fundamentally” new feature, as I’m freshly from VS 2005 (well, maybe a couple of LINQ statements which could be easily transformed into loops). In other words, none of those “new” features was beyond “syntactic / runtime sugar”, which could be implemented in earlier .Net versions if only Microsoft wanted to, or which could be implemented manually.
The most frequently used features are:
I was wondering whether it is possible to extend system classes in a way that would not require rewriting of original code, and retain compatibility with the new .Net version.
Take 1. String.IsNullOrWhiteSpace
I tried to add a partial class definition:
#If DotNet < "4.0" Then
Namespace Global.System
<Serializable> _
<Runtime.InteropServices.ComVisible(True)> _
Partial Public NotInheritable Class [String]
Inherits Object
Public Shared Function IsNullOrWhiteSpace(ByVal sText As String) As Boolean
Return String.IsNullOrEmpty(sText) OrElse String.IsNullOrEmpty(sText.Trim)
End Function
End Class
End Namespace
#End If
That had absolutely no effect. I know, one can just define such a function in an arbitrary class and then refer to it as StringUtil.IsNullOrWhiteSpace(...), but still looking for an alternate solution.
Take 2. operator =(System.Type, System.Type)
As .Net prior to version 4.0 did not implement “=” operator for Type class, it was not possible to use it in Select Case (switch) constructs. So I again tried:
#If DotNet < "4.0" Then
Namespace Global.System
<Serializable> _
Partial Public MustInherit Class [Type]
Inherits Reflection.MemberInfo
Public Shared Operator =(ByVal oType1 As Type, ByVal oType2 As Type) As Boolean
Return oType1 Is oType2
End Operator
Public Shared Operator <>(ByVal oType1 As Type, ByVal oType2 As Type) As Boolean
Return oType1 IsNot oType2
End Operator
End Class
End Namespace
#End If
It didn’t help either, but did have some additional effect: when this block is hidden, only the “Operator ‘=’ is not defined for types ‘System.Type’ and ‘System.Type’” compiler errors are shown, but then it is present, then other errors appear, such as “’IsEnum’ is not a member of ‘System.Type’” and my favorite “Value of type ‘System.Type’ cannot be converted to ‘System.Type’”. How can it be that at the same time it replaces genuine System.Type with my partial definition, yet still does not see the “=” and “<>” operators definition?
Yes, I know, I could revert to old-fashioned style:
Select Case True
Case Is TypeOf obj Is t1
' ...
Case Is (TypeOf obj Is t2) OrElse (TypeOf obj is t3)
' ...
End Select
But that is really ugly, and I always hated it. Is there any way to retain the new and well-readable style with an older .Net version?
You cannot use a partial class to extend a class in a different assembly.
Partial classes are purely syntactic features.
You created a brand new class called
System.Typewhich has nothing to do with the originalSystem.Type.Don’t do that.