What exactly is the difference between an object and a dictionary in Actionscript?
var obj:Object = new Object();
obj.something = "something";
var dict:Dictionary = new Dictionary();
dict.something = "something";
trace(obj.something, dict.something);
The trace statement seems identical...
I think the example here highlights at least one of the most significant differences, which is strict equality in comparing keys.
In summary, dictionary[key] does NOT necessarily return the same value as dictionary["key"], even if key.toString() equals "key".
However, object[key] will return the same value as object["key"], if key.toString() equals "key".
Object() uses strings as keys, while Dictionary() uses objects as keys.
See http://gskinner.com/blog/archives/2006/07/as3_dictionary_.html
Related
I'm trying to convert this map {[string1,string2]}
in to an array like this
[string1, string2]
in dart
A declaration of that kind in Dart is a Set(which is like a list but cannot have duplicates) of Lists, given that to get the first value you should just use
obj.first
(Sets are declared like maps but without any key)
This is a Set.
So you can do this for convert it to list:
Set<List<String>> map = {['string1','string2']};
List list = [];
map.forEach((k) {
k.forEach((item) => list.add(item));
});
as already mentioned in other answers this is a Set
you can easy convert it to List like this
var mySet = {['string1', 'string2']};
var list = mySet.expand((e) => e).toList();
print(list); // [string1, string2]
The 'map' you gave has one key (list of strings), which seems to be missing a value.
If your map looked something like this:
Map<List<String>, int> map = {[string1,string2]: 0};
Then you could get an Iterable of your keys (or values if you wish) with:
dynamic temp = map.keys //for the keys or
//or temp = map.values //for the values
You can further convert that Iterable into a List by calling the function toList() on it:
List<String> myList = temp.toList();
I hope this answered your question.
And if you are not sure what the type of your object is, use:
print(yourObject.runTimeType);
According to the documentation, it needs to follows the Form Post rules at: https://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4. When looking at that information it did not give me much to work with in terms of complex objects or maps.
Right now, If I have a list for example: Each item in the list needs to be stringified.
var params = {"list": [1,2,3]};
// needs to be stringed.
params["list"] = params["list"].map((item)=>item.toString()).toList();
Simple. Also all base items need to be a string as well
var params = {"number": 1, "boolean": true};
params = params.forEach((k,v)=> params[k].toString());
But how do we handle maps?
var params = {"map": {"a":1,"b":"foo","c":false,"d":[]}};
// ??
It seems that after testing in my app and in dart pad, you need to make sure everything is strings, so i am trying to come up with a way to effectively cover lists, maps, and maybe more complex objects for encoding.
var params = {};
params["list"] = [1,2,3];
params["number"] = 1;
params["boolean"] = true;
params["map"] = {"a":1,"b":"foo","c":false,"d":[]};
params.forEach((String key, dynamic value){
if(value is List){
params[key] = value.map((v)=>v.toString()).toList();
}else if(value is Map){
// ????
}else{
params[key] = value.toString();
}
//maybe have an additional one for custom classes, but if they are being passed around they should already have their own JSON Parsing implementations.
}
Ideally, the result of this would be passed into:
Uri myUri = new Uri(queryParameters: params);
and right now, while i solved the list issue, it doesn't like receiving maps. Part of me just wanted to stringify the map as a whole, but i wasn't not sure if there was a better way. I know that when someone accidentally stringified the array, it was not giving me: ?id=1&id=2 but instead ?id=%5B1%2C2%5D which was not correct.
I don't think there is any special support for maps. Query parameters itself is a map from string to string or string to list-of-strings.
Everything else need to be brought into this format first before you can pass it as query parameter.
A simple approach would be to JSON encode the map and pass the resulting string as a single query parameter.
Is there a generic way to retrieve PropertyInfo based on a string value alone, when deeper than one level.
I assume this is probably simple enough, but my search results are only as good as my search criteria, and I think I am having an issue articulating the proper keywords to get search results for what I am after.
I would like to be able to do something like the following (which works perfect if the key is for a direct property / one level - ie key = 'firstName'):
public static PropertyInfo (this HtmlHelper htmlHelper, string key) {
PropertyInfo pInfo = htmlHelper.ViewData.Model.GetType().GetProperty(key);
return pInfo;
}
But is there a way for me to return the PropertyInfo based on a string alone
when Key equals something more complex, such as nested classes, objects, lists, etc...:
key = "somelist[0].myproperty"
key = "Items[0].someotherlist[1].someproperty" (where Items is defined as List<Item> Items {get; set;}, someotherlist is defined similarly)
Can the method be generic enough to essentially drill down as many levels as needed (defined)?
So here is what I came up with... this is about to get wordy, and mostly 'stream of thought'
I have custom HtmlHelperExtension, and within it :
PropertyInfo[] pInfoArray = htmlHelper.ViewData.Model.GetType().GetProperties();
PropertyInfo pInfo = GetPropertyInfo(pInfoArray, key);
This GetPropertyInfo() method takes the key, and the PropertyInfo array, cycles through the properties, until the keypart (using regex to remove any indication of an array from the string, so I am left with only the property) matches the property name. On Match, determine if this is the first cycle in the loop, and if so assign the matched property to my Temp Type and PropertyInfo variables. If keyParts are remaining to loop through, subsequent loops now use previously set temp variables and the for loop index [i] to iterate / drill down the class structure. Each time setting the pInfoTemp variable, and then pTypeTemp so the next loop can use where it left off.
private static PropertyInfo GetPropertyInfo(PropertyInfo[] pInfoArray, string key)
{
PropertyInfo pInfo = null;
string[] keyParts = key.Split('.');
Regex arrayRgx = new Regex("\\[\\d*\\]");
PropertyInfo pInfoTemp = null;
Type pTypeTemp = null;
foreach (PropertyInfo prop in pInfoArray)
{
string keyPartsTrimmed = arrayRgx.Replace(keyParts[0], ""); // removes '[#]' from string
if (keyPartsTrimmed == prop.Name) // match property name
{
for (int i = 0; i < keyParts.Count(); i++)
{
if (i == 0) // initial item [0]
{
pTypeTemp = prop.PropertyType; // gets [0]'s type
pInfoTemp = prop; // assigns [0]'s property info
}
else
{
pInfoTemp = GetNestedPropertyInfo(pTypeTemp, arrayRgx.Replace(keyParts[i], "")); // gets [i]'s property info for return or next iteration
pTypeTemp = pInfoTemp.PropertyType; // gets [i]'s type for next iteration
}
}
pInfo = pInfoTemp;
break;
}
}
return pInfo;
}
This next method is invoked by the previous for grabbing nested property info, more importantly for detecting whether the passedItemType is a List (without this, it fails to work correctly as it is unable to find the property asked for in a List<> Type. I need to know what the List item Type is.
private static PropertyInfo GetNestedPropertyInfo(Type passedItemType, string passedProperty)
{
PropertyInfo pInfoOut = null;
if (passedItemType.IsGenericType && passedItemType.GetGenericTypeDefinition() == typeof(List<>))
{
Type itemType = passedItemType.GetGenericArguments()[0];
pInfoOut = itemType.GetProperty(passedProperty);
}
else
{
pInfoOut = passedItemType.GetProperty(passedProperty);
}
return pInfoOut;
}
This currently suits my requirements as they are today, and I have tested it with the following properties, lists, subclasses, subclasses with lists, etc.. to 4 levels deep, but should function properly no matter the depth:
firstName
lastName
Items[1].sprocket
subClass.subClassInt
subClass.mySubClassObj.sprocketObj
subClass.ItemsInMySubClass[1].sprocket
subClass.ItemsInMySubClass[0].mySubClassObj.widgetObj
subClass.ItemsInMySubClass[2].mySubClassObj.sprocketObj
If anyone has a better solution, or see any potential issues with what I have, I welcome the feedback.
The best way in your case is to make a parser that split that expression.
Does it imply that whenever I am passed an array of a non nullable type, I should still check if it is null? Actually it is not even possible to check <> null but have to use operator.unchecked .How is it better than C#?
type test=
{
value: int
}
let solution = Array.zeroCreate 10
solution.[0] <- {value = 1}
solution.[1].value // System.NullReferenceException: Object reference not set to an instance of an object
type test =
{value: int;}
val solution : test [] =
[|{value = 1;}; null; null; null; null; null; null; null; null; null|]
val it : unit = ()
It depends where the array is being passed from.
If the array is created and used only within F#, then no, you don't need to check for null; in fact, you shouldn't check for null (using Unchecked.defaultOf) because the F# compiler optimizes some special values like [] (and None, in certain cases) by representing them as null in the compiled IL.
If you're consuming an array being passed in by code written in another language (such as C#), then yes, you should still check for null. If the calling code just creates the array and doesn't mutate it any further, then you'll only need to perform the null checks once.
EDIT : Here's a previous discussion about how the F# compiler optimizes the representation of certain values using null: Why is None represented as null?
As the documentation for Array.zeroCreate indicates, it initializes the elements to Unchecked.defaultof<_>. This therefore carries with it all of the same caveats that direct use of Unchecked.defaultof does. Generally, my advice would be to use Array.create/Array.init whenever possible, and to treat Array.zeroCreate as a possible performance optimization (requiring care whenever dealing with non-nullable types).
You're creating a record type, which is implemented as a class, which is indeed nullable. If you intended to create a struct, your code should look something like this:
type test =
struct
val value: int
new(v) = { value = v }
override x.ToString() = x.value.ToString()
end
let solution = Array.zeroCreate 10
solution.[0] <- test(1)
This outputs: val solution : test [] = [|1; 0; 0; 0; 0; 0; 0; 0; 0; 0|]
You could also write the type using the Struct attribute, saving you a level of indentation.
[<Struct>]
type test =
val value: int
new(v) = { value = v }
override x.ToString() = x.value.ToString()
I just discovered a very strange behaviour. I have a class with a string property. In the setter of this property I compare the old value with the new value first and only change property if the values differ:
set
{
if ((object.ReferenceEquals(this.Identifier, value) != true))
{
this.Identifier = value;
this.RaisePropertyChanged("Identifier");
}
}
But this ReferenceEquals almost always returns false! Even if I call object.ReferenceEquals("test", "test") in Quick Watch I get false.
How is this possible?
That's because strings are immutable in C#:
The contents of a string object cannot
be changed after the object is
created, although the syntax makes it
appear as if you can do this.
Since you can't modify an existing string reference, there's no benefit in reusing them. The value passed to your property setter will always be a new string reference, except maybe if you do this.Identifier = this.Identifier;.
I'll try to clarify with an example:
string s = "Hello, "; // s contains a new string reference.
s += "world!"; // s now contains another string reference.