VB.NET difference between using multiple USING statement and using only one - vb.net

Which one is best approach out of the following? Or Both has same effect ?
Dim carrierName As String
Dim someotherName As String
Dim anotherOne As String
Using oDa As New MyCompany.DataAccess.MyModule
carrierName = oDa.GetCarrierName(itemNumber)
End Using
Using oDa As New MyCompany.DataAccess.MyModule
someotherName = oDa.GetSomeOtherName(itemNumber,1)
End Using
Using oDa As New MyCompany.DataAccess.MyModule
anotherOne = oDa.GetAnotherName("somevalue")
End Using
OR
Using oDa As New MyCompany.DataAccess.MyModule
carrierName = oDa.GetCarrierName(itemNumber)
someotherName = oDa.GetSomeOtherName(itemNumber,1)
anotherOne = oDa.GetAnotherName("somevalue")
End Using

Well, one version will create three MyModule instances, the other will only create one. We can't tell what the difference is without knowing more about MyModule.
The second approach looks cleaner to me, but without knowing the semantic differences, it's hard to say that it's definitely better.

In the first, you are creating and disposing of 3 instances of MyModule while in the second you are only creating and disposing 1 instance. So the second approach is better. It's cleaner and more straightforward too.

The two approachs are fondamentally different, but the end result depend on your MyModule implementation.
The second one seems better, as it creates and manages only one MyModule object, especially if MyModule is costly to create and to dispose.
The first one can be necessary if your MyModule doesn't allow multiple requests with the same instance. But if it's the cas. hem... it would look like a bug to me.

The latter is better in most cases. Using is just shortcut for
var oDa = new MyCompany.DataAccess.MyModule();
try {
carrierName = oDa.GetCarrierName(itemNumber)
someotherName = oDa.GetSomeOtherName(itemNumber,1)
anotherOne = oDa.GetAnotherName("somevalue")
}
finally {
oDa.Dispose();
}
First method could be used when every method allocates huge amount of memory that will need to be cleaned right away, but I don't think it is your case.
btw: you seem to have mistaken c# with visual basic

Related

How to execute Selenium ExpectedConditions based on string variables

VERY LONG story short, I'm trying to develop a MS Excel AddIn to allow an uneducated user (open to interpretation) to create Excel-based scripts that Visual Basic (yeah not C#) can essentially parse into the individual pieces and send to the browser via Selenium commands. So far, I've had quite a bit of success. Granted there is a little bit clunkiness, but this is round 1, and I've only been working with Selenium for a week.
Up to this point I have been able to use the CallByName function to call various Selenium methods where each _argument is passed from a higher level handler originating from values in spreadsheet cells.
Dim eleActionElement as Remote.RemoteWebElement = Nothing
eleActionElement = driver.FindeElement(By.Id("PresentObjectID"))
CallByName(eleActionElement, _strAction, CallType.Method, _strActionArg)
Initially I had problems with Bys:
Dim myBy As By = CallByName(By, _strBy, CallType.Method, _strByArg)
Intelisense warns that "By" is a class type and cannot be used as an expression. Fortunately, there are individual methods for each by type, so I have been able to retrieve elements effectively through:
Public Function DriverFindElementBy(_strBy As String, _strByArg As String) As Remote.RemoteWebElement
Dim strElementBy As String = "FindElementBy" & _strBy
Dim eleWebElement As Remote.RemoteWebElement = Nothing
eleWebElement = CallByName(ThisAddIn.driver, strElementBy, CallType.Method, _strByArg)
Return eleWebElement
End Function
Unfortunately, I haven't found a way to get ExpectedConditions to work. My best guess (of many) is:
Public Function WaitOnCondition(_strCondition As String, _strBy As String, _strByArg As String)
Dim myExpectedConditionObj As ExpectedConditions
CallByName(myExpectedConditionObj, _strCondition, CallType.Method)
waitDefault.Until(CallByName(myExpectedConditionObj, _strCondition, CallType.Method))
If strTestResult.Length = 0 Then
Return "Success"
Else
Return strTestResult.ToString
End If
End Function
Intelisense warns this could result in a NullReference and it does. I can see how the object is not instantiated yet, but the same approach worked with the RemoteWebElement. If studied the Selenium docs, and both are class types; so I'm left thinking the problem has to do with various methods of the ExpectedConditions and By classes take and return different numbers and types of arguments. It may be because both classes are delegates. It may be some simple error I'm making - although, I've written and rewritten these functions a dozen times with the recurring thought, "geez, this should work." One of those times you'd think I'd have blindly gotten it right.
I'm certainly not a .Net expert and advanced techniques can be baffling at times, but I do study the solutions people provide on SO and often have to go and expand my skills; so please know that nay help will be appreciate and will not go in vain.
One tiny request, if you give a C# (or Java or Python) explanation, just let me know if you KNOW / DON'T KNOW or AREN'T SURE if it will work in VB. My biggest challenge in advanced topics is that narrow segment of stuff that doesn't crossover between C# and VB.
THANKS in advance!

Using a Dictionary TryGetValue With Multiple Conditions

I am fairly new to VB net and have been playing around with dictionaries for the past week. I have a problem however when trying to do something rather complex with my dictionary look-up.
First, I should point out that I am filling my dictionary with a class object in order to store multiple values:
Class NodeLoad
Public Property NodeName As String
Public Property NodeCase As String
Public Property NodeAxis As String
Public Property NodeDir As String
Public Property NodeValue As Double
End Class
And my problem lies in doing a dictionary look-up where my only option is to do a try catch for when the value I am looking for doesn't exist:
Try
tempnodeitem = (From load In load_dict.Values Where load.NodeName = nodenum And load.NodeCase = pattern And load.NodeDir = dirarray(d)).First
loadforce(d) = tempnodeitem.NodeValue
Catch ex As Exception
loadforce(d) = "0"
End Try
The above code runs, but it takes much longer than I would expect, and after a little research found that try/catch takes much longer than TryGetValue. The thing I would like to do (since it is a much for efficient function) is to use TryGetValue. However, as far as I know, it only works for one key and one value (TKey, TValue).
Can anyone give me an example of how to use TryGetValue with multiple conditions?
Or perhaps how to catch false dict look-ups without being resource intensive?
I am thinking a good way to approach this problem is using nested TryGetValue statements... or possibly multiple dicts or lists which can handle this problem differently.
I appreciate any input!
Thanks!
As you're using a function anyway, I would tend to use function syntax in this case rather than query syntax. Is it possible that there could be more than one match to your conditions? There are four similar methods, i.e. First, Single, FirstOrDefault and SingleOrDefault, and there is never a case where more than one is appropriate. The choice of which to use comes down to two simple questions:
Will there always be at least one match? If not then use one that ends with "OrDefault".
Will there ever be more than one match? If not then use one that starts with "Single".
The answers to those two questions will always tell you which of the four methods to call.
Now, you're using a Dictionary in this case, right? What are the keys? I would have thought NodeName would be but I guess not. Anyway, assuming that there will be zero or one matches to your conditions, you would use SingleOrDefault. The code for FirstOrDefault would look exactly the same anyway:
Dim item = myDictionary.Values.SingleOrDefault(Function(nl) nl.NodeName = nodenum AndAlso
nl.NodeCase = pattern AndAlso
nl.NodeDir = dirarray(d))
loadforce(d) = If(item Is Nothing, 0.0, item.NodeValue)
Notice two other corrections to your code: the proper use of AndAlso instead of And as well as the assignment of a Double value to loadforce(d) rather than a String if there is no match. The NodeValue property is type Double so how can you want a Double if there is a match and a String if there isn't?

With... End With vs Using in VB.NET

I just found out that like C#, VB.NET also has the using keyword.
Until now I thought it didn't have it (stupid of me, I know...) and did stuff like this instead:
With New OleDbConnection(MyConnectionString)
' Do stuff
End With
What are the implications of this compared to doing it with a using statement like this
Using cn as New OleDBConnection(MyConnectionString)
With cn
' Do stuff with cn
End With
End using
UPDATE:
I should add that I am familiar with what the using statement does in that it disposes of the object when the construct is exited.
However, as far as I understand the With New ... construct will have the object mark the object as ready for garbage collection when it goes out of scope.
So my question really is, is the only difference the fact that with using I will release the memory right away, whereas with the With construct it will be released whenever the GC feels like it? Or am I missing something bigger here?
Are there any best practice implications? Should I go and rewrite all the code with I used With New MyDisposableObject() ... End With as Using o as New MyDisposableObject()?
With Statements/Blocks
However, as far as I understand the With New ... construct will have the object mark the object as ready for garbage collection when it goes out of scope.
This is both true and not true. It is true in the sense that all objects are "marked" (purists might quibble with this terminology, but the details are not relevant) as ready for garbage collection when they go out of scope. But then in that sense, it is also not entirely true, as there's nothing special about the With keyword with respect to this behavior. When an object goes out of scope, it is eligible for garbage collection. Period. That's true for method-level scope and it's true for block-level scope (e.g., With, For, Using, etc.).
But that's not why you use With. The reason is that it allows you to set multiple properties in sequence on a deeply-nested object. In other words, assume you have an object on which you want to set a bunch of properties, and you access it this way: MyClass.MemberClass.AnotherMemberClass.Items(0). See all those dots? It can (theoretically) become inefficient to write code that has to work through that series of dots over and over to access the exact same object each time you set a property on it. If you know anything about C or C++ (or any other language that has pointers), you can think of each of those dots as implying a pointer dereference. The With statement basically goes through all of that indirection only once, storing the resulting object in a temporary variable, and allowing you to set properties directly on that object stored in the temporary variable.
Perhaps some code would help make things clearer. Whenever you see a dot, think might be slow!
Assume that you start out with the following code, retrieving object 1 from a deeply-nested Items collection and setting multiple properties on it. See how many times we have to retrieve the object, even though it's exactly the same object every time?
MyClass.MemberClass.AnotherMemberClass.Items(0).Color = Blue
MyClass.MemberClass.AnotherMemberClass.Items(0).Width = 10
MyClass.MemberClass.AnotherMemberClass.Items(0).Height = 5
MyClass.MemberClass.AnotherMemberClass.Items(0).Shape = Circle
MyClass.MemberClass.AnotherMemberClass.Items(0).Texture = Shiny
MyClass.MemberClass.AnotherMemberClass.Items(0).Volume = Loud
Now we modify that code to use a With block:
With MyClass.MemberClass.AnotherMemberClass.Items(0)
.Color = Blue
.Width = 10
.Height = 5
.Shape = Circle
.Texture = Shiny
.Volume = Loud
End With
The effect here, however, is identical to the following code:
Dim tempObj As MyObject = MyClass.MemberClass.AnotherMemberClass.Items(0)
tempObj.Color = Blue
tempObj.Width = 10
tempObj.Height = 5
tempObj.Shape = Circle
tempObj.Texture = Shiny
tempObj.Volume = Loud
Granted, you don't introduce a new scope, so tempObj won't go out of scope (and therefore be eligible for garbage collection) until the higher level scope ends, but that's hardly ever a relevant concern. The performance gain (if any) attaches to both of the latter two code snippets.
The real win of using With blocks nowadays is not performance, but readability. For more thoughts on With, possible performance improvements, stylistic suggestions, and so on, see the answers to this question.
With New?
Adding the New keyword to a With statement has exactly the same effect that we just discussed (creating a local temporary variable to hold the object), except that it's almost an entirely pointless one. If you need to create an object with New, you might as well declare a variable to hold it. You're probably going to need to do something with that object later, like pass it to another method, and you can't do that in a With block.
It seems that the only purpose of With New is that it allows you to avoid an explicit variable declaration, instead causing the compiler to do it implicitly. Call me crazy, but I see no advantage in this.
In fact, I can say that I have honestly never seen any actual code that uses this syntax. The only thing I can find on Google is nonsense like this (and Call is a much better alternative there anyway).
Using Statements/Blocks
Unlike With, Using is incredibly useful and should appear frequently in typical VB.NET code. However, it is very limited in its applicability: it works only with objects whose type implements the IDisposable interface pattern. You can tell this by checking to see whether the object has a Dispose method that you're supposed to call whenever you're finished with it in order to release any unmanaged resources.
That is, by the way, a rule you should always follow when an object has a Dispose method: you should always call it whenever you're finished using the object. If you don't, it's not necessarily the end of the world—the garbage collector might save your bacon—but it's part of the documented contract and always good practice on your part to call Dispose for each object that provides it.
If you try to wrap the creation of an object that doesn't implement IDisposable in a Using block, the compiler will bark at you and generate an error. It doesn't make sense for any other types because its function is essentially equivalent to a Try/Finally block:
Try
' [1: Create/acquire the object]
Dim g As Graphics = myForm.CreateGraphics()
' [2: Use the object]
g.DrawLine(Pens.Blue, 10, 10, 100, 100)
' ... etc.
End Try
Finally
' [3: Ensure that the object gets disposed, no matter what!]
g.Dispose()
End Finally
But that's ugly and becomes rather unwieldy when you start nesting (like if we'd created a Pen object that needed to be disposed as well). Instead, we use Using, which has the same effect:
' [1: Create/acquire the object]
Using g As Graphics = myForm.CreateGraphics()
' [2: Use the object]
g.DrawLine(Pens.Blue, 10, 10, 100, 100)
' ...etc.
End Using ' [3: Ensure that the object gets disposed, no matter what!]
The Using statement works both with objects you are first acquiring (using the New keyword or by calling a method like CreateGraphics), and with objects that you have already created. In both cases, it ensures that the Dispose method gets called, even if an exception gets thrown somewhere inside of the block, which ensures that the object's unmanaged resources get correctly disposed.
It scares me a little bit that you have written code in VB.NET without knowing about the Using statement. You don't use it for the creation of all objects, but it is very important when you're dealing with objects that implement IDisposable. You definitely should go back and re-check your code to ensure that you're using it where appropriate!
By using With...End With, you can perform a series of statements on a specified object without specifying the name of the object multiple times.
A Using block behaves like a Try...Finally construction in which the Try block uses the resources and the Finally block disposes of them.
Managed resources are disposed by the garbage collector without any extra coding on your part.
You do not need Using or With statements.
Sometimes your code requires unmanaged resources. You are responsible for their disposal. A Using block guarantees that the Dispose method on the object is called when your code is finished with them.
The difference is the Using With...End End
Using cn as New OleDBConnection(MyConnectionString)
With cn
' Do stuff with cn
End With
End using
Calls cn.Dispose() automatically when going out of scope (End Using). But in the With New...End
With New OleDbConnection(MyConnectionString)
' Do stuff
End With
.Dispose() is not explicitly called.
Also with the named object, you can create watches and ?cn in the immediate window. With the unnamed object, you cannot.
Using connection... End Using : Be careful !!!
This statement will close your database connection !
In the middle of a module or form(s), i.e.adding or updating records, this will close the connection. When you try to do another operation in that module you will receive a database error. For connections, I no longer use it. You can use the Try... End Try wihthouth the Using statement.
I open the connection upon entry to the module and close it it upon exit. That solves the problem.

Will statements or expressions execute after a return statement in VB.net?

Ok, I was rooting around in one of our company apps which is done in VB.net. I'm not familiar with VB.net (I do stuff in C#) so I'm asking this question: Does the code after the clean up comment execute?
Public Function DoesUserHavePermission(ByVal UserID As Integer, ByVal ActionID As Integer) As Boolean
' some extra code re: getting data
Return UserHasPermission
'-Clean Up-
MySqlCommand.Dispose()
MySqlConnection.Dispose()
RowCount = Nothing
End Function
It is my understanding once you say return, you give the calling function control again. Is this a VB.Net oddity which I have to accept or a giant WTF?
The statements after the Clean up comment will not execute. This is a candidate for enclosure within Try/Catch/Finally.
Not unless there's some control logic you omitted in your example
The code should be (the clean up that is) wrapped inside of a finally statement by using a try catch exception:
pseudo:
try
'make conn
catch exception
finally
mysqlCmd.Dispose
....
end try
Is it possible it will still run..possibly...I used to write VB.net and it has been quite some time but I do remember oddities like that. I can't give you a sure answer as this is / was very bad practice. What you can do is clean it up and set some break points in y our code and debug. See if the code comes back to it...
Short answer: The code below the return will never execute.
That looks like translated code. Like someone took a C# snippet from the web and tried to write it in VB for VS 2003 (before VB supported the USING statement, but while C# did).
where the MySqlConnection and MySqlCommand are new'd up should be put in USING blocks and the Dispose() lines turned into END USING.
Where possible, use USING over TRY/FINALLY to ensure cleanup of IDisposable objects.
using mySqlConnection as New SqlConnection(connectionString)
mySqlConnection.Open
using mySqlCommand as New SqlCommand(commandString, mySqlConnection)
'do something that may fail'
return UserHasPermission
end using 'disposes mySqlCommand'
end using 'closes/disposes mySqlConnection'
You can use this pattern for SqlTransactions too. (Place after mySqlConnection.Open)
using myTerribleVariableName as SqlTransaction = mySqlConnection.BeginTransaction
'do something that may fail - multiple SqlCommands maybe'
'be sure to reference the transaction context in the SqlCommand'
myTerribleVariableName.Commit
end using 'disposes. rollsback if not commited'
Oh, and you can delete the RowCount = Nothing statement.
That to me is a giant WTF and a very difficult thing to miss, normally peer code review can catch that, I do not understand why a return from the function is placed earlier on prior to the cleanup. That could have been done during the testing of the code where the programmer was wanting to test the function first and decided to ignore the cleanup code by returning from it quickly enough, I suspect the cleanup code could be lengthy, ie. maybe it is throwing an exception that is not properly caught and wanted to ignore it hence a need to return immediately...That is an (un) intentional side effect of introducing a leak as the resource is not cleaned up properly thereby masking the real problem...that's my take on it.
Hope this helps,
Best regards,
Tom.
The code as presented will not do anything after the return statement. VB.NET and C# are similar in that fashion.
Its possible that this code was written by a VB6 programmer, trusting in old paradigms, or possibly this was the work of the upgrade tool, porting code from VB6 to VB.NET.

How to access the object itself in With ... End With

Some code to illustrate my question:
With Test.AnObject
.Something = 1337
.AnotherThing = "Hello"
''// why can't I do this to pass the object itself:
Test2.Subroutine(.)
''// ... and is there an equivalent, other than repeating the object in With?
End With
There is no way to refer to the object referenced in the With statement, other than repeating the name of the object itself.
EDIT
If you really want to, you could modify your an object to return a reference to itself
Public Function Self() as TypeOfAnObject
Return Me
End Get
Then you could use the following code
With Test.AnObject
Test2.Subroutine(.Self())
End With
Finally, if you cannot modify the code for an object, you could (but not necessarily should) accomplish the same thing via an extension method. One generic solution is:
' Define in a Module
<Extension()>
Public Function Self(Of T)(target As T) As T
Return target
End Function
called like so:
Test2.Subroutine(.Self())
or
With 1
a = .Self() + 2 ' a now equals 3
End With
I suspect you'll have to repeat yourself. If the expression (to get the object) is expensive, then perhaps drop it into a variable first, and either use that variable in the With, or drop the With completely:
tmp = Test.AnObject;
tmp.Something = 1337;
...
Test2.Subroutine(tmp);
As others have said, you're going to have to write
Test2.Subroutine(Test.AnObject)
This is a good example of why it's worth being a little careful with the With construct in VB.Net. My view is that to make it worth using at all, you really need to be setting more than one or two properties, and/or calling more than one or two methods on the object in the With statement.
When there are lots, and you're not interspersing the .SomeProperty = , or .DoSomething, with other things, it's a terrific aid to readability.
Conversely, a few dots sprinkled amongst a load of other stuff is actually a lot harder to read than not using With at all.
In this case, . characters on their own could easily get lost visually, although of course, it would be syntactically consistent.
I guess they just chose not to implement it. VB isn't really the sort of language where they want to encourage single character language elements, and as a heavy user of VB.Net, I broadly agree with that.
Bottom line: if you're using a With clause with many contained elements, having to refer to the object itself isn't that big a deal. If you're using it with just one or two, maybe better not to use a With clause in the first place.
I'm not sure this is an "answer", per se, but it does illustrate another reason to want a short-hand reference to the parent in a With.
Here's a code sample using a "bare With" (that's what I call it, anyway):
With New frmMySubForm
.lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = .lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
...
End With
But you actually can't code that because in the term .Start = .lblLinkLabel.Text.IndexOf("link") the compiler expects anything starting with . to be a member of LinkLabel.Link, which .lblLinkLabel isn't.
What would be good, I think, is to be able to write something like:
With New frmMySubForm
.lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = Me.lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
...
End With
where Me in this scope is taken to be New frmMySubForm.
Yes, I realize that I'm being picky and I could easily assign a variable, etc. But the example form is something I use a lot simply out of preference.