Opposite to a Structure? - vb.net

I'm sure there is an answer to this somewhere but I'm clearly using the wrong terminology in my searches, so I apologise in advance for this inevitably being a duplicate.
Take the function CType. Clearly I can cast (or at least try) a given object to a given reference type. The function will not work if trying to cast to a structure, i.e.
CType(myObject, Integer)
...will generate a compiler error. This I'm sure most often crops up when working with generics:
Public Function GetResults(Of T)() As T
Dim instance As T
Return CType(GetData(instance), T)
End Function
Public Function GetData(ByVal param As myClass) As myClass
'do stuff
Return param
End Function
Public Function GetData(byval param As Integer) As Integer
'do stuff
Return param
End Function
Public Function GetResults(ByVal param As Object) As Object
Throw New NotImplementedException
End Function
Probably not the best of examples but hopefully shows what I mean. The following will work:
Dim result = GetResult(Of myClass)
The following will fail on the CType
Dim result = GetResult(Of Integer)
I'm not a big fan of using exceptions/Try-Catch if logic can be applied, so although I could Try-Catch the CType, I'd rather find a way to route it through different code. I know with Generics I can use
Public Function GetResults(Of T As Structure) As T
What is the opposite? I want only reference types so that CType doesn't fail... I can't overload the T As Structure with a plain T because it considers them identical signatures, so surely there's a keyword I'm missing somewhere? ^^
Long question, probably only requries a one word answer (sorry)... Thanks in advance!

Public Function GetResults(Of T As Class) As T

Related

System.StackOverflowException intersection error

I want my program to take a variable, and find letters A-Z. I have made this section of my program in a module to be shared between 2 different forms.
variables are passed from form1 and are processed by the module and then sent back again to form1. the problem is I think some sort of bug in the code but I cant identify it.
Public Function UPCASES(ByRef password1, points) As Boolean
Dim intersection As IEnumerable(Of Char)
intersection = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Intersect(password1)
'System.StackOverflowException error ^^^^^^^^^^^^^^^^^^^^^^^^^
If intersection.Count() = 1 Then
points = 5
Else
points = 0
End If
Return UPCASES(password1, points)
End Function
You are calling the method itself at the method end, that causes the StackOverflowException:
Return UPCASES(password1, points)
I guess this method should check if the password contains uppercase letters, then use:
Dim containsUpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Intersect(password1).Any()
So no need to create a method just for this one-liner, if you need a method:
Public Function ContainsUpperCaseLetter(password1 As String) As Boolean
Return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Intersect(password1).Any()
End Function
Side-note: you should change your default project settings to use Option Strict ON(Off is default unfortunately). Then you will be able to write much more safe, robust and performant code after you have learned a lot about .NET types because you have to fix the compiler errors.

String Function with No Paramaters Invoked with Int Should Fail Build

We have a VB.NET project which I am doing some refactoring in. A lot of current functions require a userId to be passed in as a parameter. For example:
Private Function Foo(userId As Integer) As String
Return "Foo"
End Function
But now, I have made this userId paramater no longer needed in much of our code.
I was thinking I would just remove all the userId parameters from all of the functions that don't need them anymore, and try re-building the project to see what calling code needs to change. To my surprise though, the code built successfully.
I learned that you can call a function which returns a string and doesn't take any parameters, but still pass in an Integer value. VB.NET builds/executes this code as if you were trying to invoke the function and then get the character from the String at the specified index. For example:
Imports System
Public Module MyModule
Private Function Foo() As String
Return "Foo"
End Function
Public Sub Main()
Console.WriteLine(Foo(0)) ' prints 'F'
Console.WriteLine(Foo(1)) ' prints 'o'
End Sub
End Module
(.NET Fiddle)
I want my build to fail in this case. I have tried using Option Strict On and Option Explicit On but neither seem to change this behaviour.
Is there anyway to make this kind of function invocation invalid in my VB.NET project?
Create an overload with no parameters which is a copy of the original function in every other respect.
Public Function Foo() As String
Return "Foo"
End Function
Now change the type of userId to something else (not Object or anything numeric etc.)
Public Function Foo(userId As DateTime) As String
Return "Foo"
End Function
Since there is an overload with a parameter, the compiler thinks you mean to call that, instead of indexing the chararray. So you have compile errors. Fix the errors
Then delete the original function.

Why can't I have two methods with the same parameters but different returns?

.net allows...
Public Function One(A as Integer) As String...
Public Function One(B as String) As String...
It figures out which one to call by looking at the Type of the parameters, like...
Dim A As String = One(5)
Ok, so why can't you do this...
Public Function One(A as Integer) As String...
Public Function One(B as Integer) As Integer...
The same amount of information is available to the compiler...
Dim A As Integer = One(5) ' should know to call the second version
The specific problem I'm trying to solve is to return the Values in a Dictionary(Of Integer, MyClass) so that it is visible to COM Interop. To do that I simply return the .Values as IEnumerable. But then I lose the type inside my own code, which is a PITA. If I could have two methods I could have one that returns IEnumerable and another that returns List(Of MyClass) and the API would be the same in both places. I could have two different method names, but that kind of defeats the purpose.
I'm open to any solution that fixes the underlying problem... is there a single type I can return that avoids all the DirectCast in my own code, while still being visible to COM Interop?
Short answer : because the return type isn't included in the method's signature
the relevant part of the spec
The following are not part of a member's signature, and hence cannot be overloaded on:
Modifiers to a type member (for example, Shared or Private).
Modifiers to a parameter (for example, ByVal or ByRef).
The names of the parameters.
The return type of a method or the element type of a property.

Using TryCast to return DBNull instead of Nothing

I'm trying to create a a simple function in VB.net which will take a few parameters for use with TryCast.
My goal is to have a function I can use in place of TryCast which instead of returning Nothing when it fails it should return DbNull.
I just can't seem to get anything to work despite much searching.
Thanks.
The problem is that you have to have some specific return type for your function. So you can write a function with a signature like this:
Public Function TryCast(Of T)(ByVal item As Object) As T
But you will never be able to make it do what you want, because the type of T is never going to be DBNull (okay, maybe it could happen, but hopefully you get the idea).
Put another way, the type system blocks this. On the one hand, you want to be perfectly explicit about the return type (hence, the cast). On the other hand, you want to be able to return a completely different type. .Net does not allow this, even with dynamic typing. Either a method returns a single fixed type, or it is not declared to return a type at all.
With Option Explicit turned off, you might be able to go for something like this:
Public Function TryCast(Of T)(ByVal item As Object)
However, I don't think this will do what you want, either, because now the returned value is effectively the same as object, and you lose the benefit of any casting.
It works with the normal TryCast() for Nothing, because Nothing can be assigned to any type. DBNull is itself a fixed type, and so is not as flexible.
Simple answer - not possible, and here is why. Suppose you have the following code:
Class A
End Class
Class B : Inherits A
End Class
Class C
End Class
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim aaa As A = MyTryCast(Of A)(New B)
Dim ccc As C = MyTryCast(Of B)(New C)
End Sub
Private Function MyTryCast(Of T As Class)(obj As Object) As Object
Dim result As Object = TryCast(obj, T)
If result Is Nothing Then Return Convert.DBNull
Return result
End Function
MyTryCast does exactly what you are asking for, so aaa assignment works. Problem appears when you assign DBNull to ccc variable of type C. You would expect it to assign DBNull to C, because C cannot be converted to B (regular TryCast would return Nothing). Instead, you get System.InvalidCastException, because you cannot assign a DBNull to an instance of your custom class. Important thing to remember here - Nothing can be assigned to anything, DBNull can only be assigned to an Object. See here for DBNull inheritance hierarchy.

Byref New Object. Is it okay top pass New Object as "byref"

Below I tried to do an Example:
Public Function UserData(ByVal UserDN As String) As DataTable
Dim myTable As DataTable = UserData_Table()
Dim dr As DataRow
dr = myTable.NewRow()
SplitOU2(UserDN, dr("OUDN"), dr("Organisation"), New Object)
dr("UserDN") = UserDN
myTable.Rows.Add(dr)
Return myTable
End Function
Below is the called method:
Friend Sub SplitOU2(ByVal inDN As String, ByRef OUDN As Object, ByRef Organisation As Object, ByRef VerksamhetTyp As Object)
By doing this I can skip to declare the in this example "useless" variable
Dim VerksamhetTyp as Object = "".
Perhaps it looks a little ugly but to have to declare unused variables can also be confusing.
Summary: Check whether or not the method really needs those parameters to be ByRef. Also check that you really don't care about anything it does to the parameters. After scrupulous checking, it's okay to do this - nothing "bad" will happen in terms of the CLR, because it's just a compiler trick under the hood.
Well, VB (unlike C#) will let you do this. Behind the scenes it's effectively creating a new variable and passing it by reference - after all, it has to for the method to be called properly. However, I'd say this is usually a bad idea. The point of ByRef is that you use the value after it's been set within the method.
Do you really need all those parameters to be ByRef in the first place? If you find yourself doing this a lot for a particular method, you could always write a wrapper method which called the original one, but didn't have the ByRef parameters itself.
(I usually find that methods with a lot of ByRef parameters indicate either a lack of understanding of reference types in .NET, or that the parameters should be encapsulated in their own type.)
Having said all of this, it's not always incorrect to ignore the value of a ByRef argument after calling the method. For example, if you just want to know whether or not some text can be parsed as an integer, then using Int32.TryParse is reasonable - but only the return value is useful to you.
The reason that I consider to use this has to do with that the method has even more parameters and that different operation overloads gets the same signature ….
The fact that it works is quite fun and somthing I became awarae óff by chance ...