Open ghost opened 6 years ago
@MohammadHamdyGhanem If the strong dictionary is being compiled at compile-time,
Public Class CityTemperaturesDic
Public NewYork = 12
Public London = 10
Public Cairo = 15
End Class
Oh! Based on this issue as well as #234, I think I figured out what @MohammadHamdyGhanem wants.
We can already define a sealed list of values using a simple class:
Public Class CityTemperaturesDict
Public NewYork As Integer = 12
Public London As Integer = 10
Public Cairo As Integer = 15
End Class
...but then new members can't be added at run-time.
To solve this problem, we can instead use a Dictionary, and add its members at run-time:
Public cityTemperaturesDict As New Dictionary
cityTemperaturesDict.Add("NewYork", 12)
cityTemperaturesDict.Add("London", 10)
cityTemperaturesDict.Add("Cairo", 5)
...BUT now we don't have Intellisense to ensure that we are typing the keys correctly. So we might attempt to access an item and misspell the key:
MsgBox(cityTemperaturesDict("Cair")) 'oops! error!
cityTemperaturesDict("Cair") = 12 'even worse -- we have not updated the desired item, and we've created a new item!
SO... what @MohammadHamdyGhanem is suggesting is something in between the two approaches above: a class that
Dictionary(Of String, T)
,Dictionary
methods,It's a hybrid between an enum/anonymous type and a preinitialized dictionary:
Public cityTemperaturesDict As New Dictionary With {!NewYork = 12, !London = 10, !Cairo = 5}
cityTemperaturesDict.Cairo = 9 'Works, and I get full Intellisense.
cityTemperaturesDict.Cair = 9 'Compiler warns me that there is no such property.
cityTemperaturesDict.Add("Boston", 13) 'Adding an entry using the regular Dictionary methods.
cityTemperaturesDict("Boston") = 13 'Setting an entry using the regular Dictionary methods.
@MohammadHamdyGhanem If this is correct, kindly demonstrate to the VB team the practical scenarios in which this has value. The only one I could think of is a logging class of mine where I add metadata to the log entry, and some are standard for every log entry (request path, time/date, etc.), but I often want to add custom metadata (account being logged into, etc.). However, this can be worked around by using regular properties for the standard ones, and a Dictionary for the custom ones, as I will detail below.
Public wellKnownCities As New With {.NewYork = 12, .London = 10, .Cairo = 5}
Public customCities As New Dictionary(Of String, Integer)
wellKnownCities.Cairo = 9 'Works, and I get full Intellisense.
wellKnownCities.Cair = 9 'Compiler warns me that there is no such property.
customCities.Add("Boston", 13) 'Adding an entry using the regular Dictionary methods.
customCities("Boston") = 13 'Setting an entry using the regular Dictionary methods.
...OR via the custom CityTemperaturesDic
class example in the opening comment.
Now that we understand the suggestion, does it have value?
I doubt it. It doesn't seem like a common use case (though feel free to prove me wrong), and as shown in the opening comment, you can already do this manually by defining a class that inherits from Dictionary(Of String, Integer)
without any real difficulty.
@bandleader: I wouldn't add any more keys like this in design-time, instead any new key I discover I need, I will go back and add it to the definition of the Typed Dictionary, and the compiler will regenerate the new members for it in the hidden class. But I can still add keys at run time, based on user entries or some system events... etc. So. the Typed Dictionary will serve as: 1- a dictionary with predefind keys without having to write a lot of constants and static readonly fields to hold the names of the keys in well-written code. 2- some sort of Enum that can have non-numeric values 3- a Tuple that can be extended in runtime. 4- a hard-typed ExpandoObject which is also a dictionay but typed dictionary has strong types not all objects. In fact my suggession can be used to improve the implemntation of the ExpandoObject in cases we define its members not getting them from an external API. 5- a record class that can be extended in runtime. The Typed Dictionary is a semi-static semi-dynamic type.
By the way, I have another suggestion for VB to give us the ability to define our code blocks and tell the compiler how to generate classes for then. This is not a designer code generation. This is a syntax that converted to a generated classes in runtime. If this happens, we call expand the language beyong our imagination, and share Code blocks definitions say as NuGets. I suggest the user-defined syntax stasts with some sympole like @:
@Dictionary CityTemperaturesDic
NewYork = 12
London = 10
Cairo = 15
End Dictionary
@Flag Color
red
Green
Blue
End Flag
etc
@MohammadHamdyGhanem
When you use the phrase "code blocks," do you have the Clipper S87+ code blocks in mind?
I hope VB.NET can add this new syntax:
The compiler can use this to create a calss CityTemperaturesDic like this:
Now you can use this Typed Dictionary anywhere in you project or even expose it outside the project:
This will prevent misspelled key names, which lead to unexpected results. For example, if you use this code:
In design time, VB.NET can't detect the misspelled Key "Cair", and in runtime, the "Cair" key will be added to the Dictionary with value 5 without raising any exception, so the condition will always be false, because it deals with another key! This Can't happen in Typed dictionary, because a syntax error will happen in then line:
Cities.Cair = 5
And Intellisense with prevent that sort of mistakes.Note: we can make this part
shorter, if we agreed that the keys will always be strings. I suggest:
Dictionary CityTemperaturesDic (Of Integer)