I have the following code:
Public Shared Function GetAvailableManufacturers() As List(Of Manufacturer)
'first get all the live orders and extract their mfrs'
Dim sos As List(Of OrderForm) = GetFormsByStatus(StockStatus.Building)
Dim unavailableMfrs As New List(Of Manufacturer)
For Each so As StockingOrder In sos
unavailableMfrs.Add(so.Source)
Next
'then remove all mfrs with an open SO from a list of all mfrs'
Dim allMfrs As List(Of Manufacturer) = Manufacturer.GetManufacturers
Return allMfrs.Except(unavailableMfrs) <----- error here
End Function
Explanation of what the above does:
GetFormsByStatus() self-explanatory
GetManufacturers() returns a list of all manufacturers in the database
My idea to get available manufacturers was to get a list of all the manufacturers in my open forms, then get a list of all manufacturers and exclude all the manufacturers in the first list, illustrated like so (pseudo):
List A: {1,2,3,4,5,6,7,8,9,10}
List B: {5,7,10}
Result: {1,2,3,4,6,8,9}
I have set up my Manufacturer class according to this article so that it can be compared, but I'm still getting this error:
Unable to cast object of type '<ExceptIterator>d__92'1[csCore.Manufacturer]' to type 'System.Collections.Generic.List'1[csCore.Manufacturer]'.
I thought at first that because during testing GetFormsByStatus() returns 0 results maybe that was causing problems, but it doesn't make sense that Except() wouldn't work if the provided list had 0 items. Can anyone spot what I'm doing wrong?
Thanks so much!
The function expects a List(Of Manufacturer) return type, not an IEnumerable(Of Manufacturer), so adding a .ToList() to the return value should fix it:
Return allMfrs.Except(unavailableMfrs).ToList()
Your function is declared as returning List(Of Manufacturer), but your Return statement is returning only an IEnumerable(Of Manufacturer). Change the return statement to:
Return allMfrs.Except(unavailableMfrs).ToList()
If you turn Option Strict On, I believe VB will catch this kind of error at compile time, instead of blowing up at runtime.
The problem is that Enumerable.Except returns IEnumerable<T>, but your return type is List(Of T).
Change your last line to:
Return allMfrs.Except(unavailableMfrs).ToList()
Related
I have a list of strings,gObject.RotationItems I want to be able to rotate through those list of strings in a thread-safe way and start over when I reach the end. I have a dictionary object retain the order for each key, whether it's Rotation1 as seen below, or some other keys, as there will be different keys.
I'm using SyncLock to make sure threads to step on each other for a true rotation. But, do I really need to use SyncLock? Since I'm using a thread-safe collection? Does it need to be coded a little differently, if I remove the SyncLock? To ensure I rotate through the list of strings uniquely, over and over.
Look over my code, I'm not sure if this is the best way to go about it, or if someone can offer a suggestion or improvement.
The code is in vb.net, but a c# suggestion will work as well.
NotInheritable Class gObject
Public Shared RotationItems As New List(Of String)
Public Shared Rotation As New Concurrent.ConcurrentDictionary(Of String, Integer)
End Class
SyncLock gObject.BindObject
Dim iRotationOrder As Integer = 0
If gObject.Rotation.TryGetValue("Rotation1", iRotationOrder ) Then
If iRotationOrder >= gObject.RotationItems.Count - 1 Then
gObject.Rotation.TryUpdate("Rotation1", 0, iRotationOrder )
Else
gObject.Rotation.TryUpdate("Rotation1", iRotationOrder + 1, iRotationOrder )
End If
Else
iRotationOrder = 0
gObject.Rotation.TryAdd("Rotation1", 0)
End If
Return gObject.RotationItems(iRotationOrder)
End SyncLock
I am writing a Contains method for vb6 collections that hold strings.
However I cannot get the syntax right on my foreach.
What should I change?
Public Function Contains(col as Collection, key as Variant) as Boolean
Dim thing as Object '// this is the key
For Each thing in col
If CStr(key) = CStr(thing) then
Contains = True
Exit Function
End If
Next
Contains = False
End Function
I’m trying to obtain data from a dll, but I do not know how to do it.
My code is:
'Function
Public Declare Function SET_XML_PATH Lib "EbmPapstFan.dll" (ByRef ruta As String) As Long
Public Declare Function GET_PRODUCTS Lib "EbmPapstFan.dll" (ByRef ruta As String) As Long
Sub Selec()
Dim ruta As String
Dim Int_A As Long, Int_B
ruta = "C:\ebmpapst\data\AC\"
Int_A = SET_XML_PATH(ruta) 'If Int_A=0 then they aren't mistake
Int_B = GET_PRODUCTS("")
Worksheets("Selec").Range("E2").Value = Int_B 'Nº products
End sub
Results are:
Int_A= 0
Int_B= 18
This isn't a mistake with the path because Int_A is 0. In addition, GET_PRODUCTS gives me the number of products that software has. The manual say that this function also has string character output.
The primary problem is that I don’t know how obtain this other string character output.
vb dll strange output in C#
Both outputs of the declared functions are "Long" and not "String" so there's no way that they're outputting anything except that.
I'd recommend revisiting the manual you refer to, to see exactly how it is documented and what the string value's function call would be.
The 2 function declaratons show long as the return types, however, the string being passed in is going in byRef and not byVal. It is possible that the string value is being returned via that parameter being adjusted inside the call.
More details about the documentation would be helpful.
[This is a simplified example]
I have a collection ("myCollection") in which exists three entries: ("hello", "goodbye", "welcome"). I want to iterate through the collection and if in the collection there is the entry "welcome" I want to take one action, if that entry doesn't exist I want to do something else. Like this (pseudo):
For Each entry in myCollection
If entry="welcome" Then
DoSomething()
End If
Next (If Not MsgBox("Bad!"))
Suggestions?
Try this:
Dim found as Boolean = false
For Each entry in myCollection
If entry="welcome" Then
DoSomething()
found = True
Exit For ' Assumes only want to DoSomething for one "welcome" '
End If
Next
If Not found Then
MsgBox("Bad!")
End If `enter code here`
Alternatively the LINQ version may look more succinct:
If myCollection.Contains("welcome") Then
DoSomething()
Else
MsgBox("Bad!")
End If
I have a Dictionary object in VBScript. How can I copy all the objects contained in it to a new Dictionary, i.e. create a clone/duplicate of the dictionary?
Create a new Dictionary object, iterate through the keys in the original dictionary and adds these keys and the corresponding values to the new dictionary, like this:
Function CloneDictionary(Dict)
Dim newDict
Set newDict = CreateObject("Scripting.Dictionary")
For Each key in Dict.Keys
newDict.Add key, Dict(key)
Next
newDict.CompareMode = Dict.CompareMode
Set CloneDictionary = newDict
End Function
This should be enough in most cases. However, if your original dictionary holds objects, you'll have to implement deep cloning, that is, clone these objects as well.
If anyone is looking for a VBA solution, the following function performs a "deep-clone" of a dictionary, including nested dictionary objects.
' Compare mode for cloning dictionary object
' See CloneDictionary function
Public Enum eCompareMethod2
ecmBinaryCompare = 0
ecmTextCompare = 1
ecmDatabaseCompare = 2
' Added this to use original compare method
ecmSourceMethod = 3
End Enum
'---------------------------------------------------------------------------------------
' Procedure : CloneDictionary
' Author : Adam Waller
' Date : 3/30/2021
' Purpose : Recursive function to deep-clone a dictionary object, including nested
' : dictionaries.
' : NOTE: All other object types are cloned as a reference to the same object
' : referenced by the original dictionary, not a new object.
'---------------------------------------------------------------------------------------
'
Public Function CloneDictionary(dSource As Dictionary, _
Optional Compare As eCompareMethod2 = ecmSourceMethod) As Dictionary
Dim dNew As Dictionary
Dim dChild As Dictionary
Dim varKey As Variant
' No object returned if source is nothing
If dSource Is Nothing Then Exit Function
' Create new dictionary object and set compare mode
Set dNew = New Dictionary
If Compare = ecmSourceMethod Then
' Use the same compare mode as the original dictionary.
dNew.CompareMode = dSource.CompareMode
Else
dNew.CompareMode = Compare
End If
' Loop through keys
For Each varKey In dSource.Keys
If TypeOf varKey Is Dictionary Then
' Call this function recursively to add nested dictionary
Set dChild = varKey
dNew.Add varKey, CloneDictionary(dChild, Compare)
Else
' Add key to dictionary
dNew.Add varKey, dSource(varKey)
End If
Next varKey
' Return new dictionary
Set CloneDictionary = dNew
End Function
Take a look at the accepted answer in VBScript: How to utiliize a dictionary object returned from a function?. Could be a solution if a reference is all that is being looked for.
Edit As per Ekkehard.Horner's comment, I understand now that this is not cloning, but may help others who are only looking for a reference to the original object.