Accessing elements in C# dictionary - c#

I am a newbie currently translating C++ code to C#. I have a map
map<string, Object*> table;
and a function
void define(const string& symbol, Object* definition)
{
map<string, Object*>::iterator iter = table.find(symbol);//returns iterator to element with key "symbol," else sets equal to map::end
if (iter != table.end())//if key is in map
{
delete (*iter).second;
table.erase(iter);
}
table.insert(pair<string, Object*>(symbol,definition->clone()));
}
and I want to create the equivalent function in C#. I've created a Dictionary:
private Dictionary<string, Object> table = new Dictionary<string, Object>();
and here is my function so far
public void define(string symbol, Object definition)
{
if (table.ContainsKey(symbol))
{
//function body
}
and now need my function body to accomplish the same thing. From my research, it doesn't seem like C# has the same iterator structure.

Your method in the end replaces an element (if present), or adds it... In C# you can simply:
public void define(string symbol, Object definition)
{
table[symbol] = definition;
}
Note that if definition can be IDisposable and you have ownership of it, then it would be better to Dispose() it, in a similar manner to the one used in C++
public void define(string symbol, Object definition)
{
object oldDefinition;
if (table.TryGetValue(symbol, out oldDefinition) && oldDefinition != null)
{
IDisposable disp = oldDefinition as IDisposable;
if (disp != null)
{
disp.Dispose();
}
}
table[symbol] = definition;
}
For the clone()
You have to choose how to handle the clone(). Being references even in C++, it is a little strange that they chosed to clone() the Object. If you want to clone() it, clearly you'll need to expose a method for your CloneableObject to clone it. Note that Object (or object) in C# isn't cloneable "out of the box". You have to write the code to clone it.

If I understand correctly, you need an iterator over dictionary in c#. You can use one of the following way to iterate over dictionary in c#
foreach(var pair in table)
{
var key = pair.Key;
var value = pair.Value;
}
or
foreach(KeyValuePair<string, Object> entry in table)
{
// do something with entry.Value or entry.Key
}
or
for (int index = 0; index < table.Count; index++) {
var item = table.ElementAt(index);
var itemKey = item.Key;
var itemValue = item.Value;
}
You can add if clause in foreach loop and process it.

Related

C# How do you loop through multiple dictionaries?

A standard dictionary would look like this:
public Dictionary<int, DictionarySetup> H = new Dictionary<int, DictionarySetup>()
{
{18000, new DictionarySetup { Some values }},
};
Ranging from A-T, all of these are in a class called DictionaryInit, right now I check the value if there's a match with this boolean:
public Boolean Dictionary_Test(Dictionary<int, DictionarySetup> AccountLexicon)
{
DictionarySetup ClassValues;
if (AccountLexicon.TryGetValue(MapKey, out ClassValues))
{
return true;
}
return false;
}
Now, I'm looking for a more efficient method to loop through each Dictionary and, if there's a match, get that particular dictionary for use in a subsequent method, this is what it looks like now in an if/else:
if(Dictionary_Test(theDictionary.C) == true)
{
Dictionary_Find(Account_String, rowindex, theBSDictionary.C, Cash_Value, txtCurrency.Text);
}
else if (Dictionary_Test(theDictionary.D) == true)
{
Dictionary_Find(Account_String, rowindex, theDictionary.D, Cash_Value, txtCurrency.Text); //Method that makes use of the dictionary values, above dictionary checks only if it exists
}
With dictionaries from A-T, that would be alot of if/else's! Is there a better way to do this? I've found one thread mentioning this same topic, by adding the dictionaries to a dictionary array[] then looping over it, but how do I get the name of the matching dictionary if a match is found or make my second method, Dictionary_Find, use the matching dictionary?
Another possible solution, you could use reflection to get each dictionary from A-T from the DictionaryInit class. Create an array that contains values A-T, loop through the array and use reflection to get the dictionary, and test that dictionary, if you find a match, return that dictionary and exit the loop. Something like:
var dicts = new[]{"A", "B", ......., "T"}
foreach (var dict in dicts)
{
var found = CheckDictionary(theDictionary, dict);
if (found != null)
{
Dictionary_Find(Account_String, rowindex, (Dictionary<int, DictionarySetup>)found, Cash_Value, txtCurrency.Text);
break;
}
}
public static object CheckDictionary(object dictClass, string dictName)
{
var theDictionary = dictClass.GetType().GetProperty(dictName).GetValue(dictClass, null);
return Dictionary_Test(theDictionary) ? theDictionary : null;
}
I've just quickly grabbed some code from a project I've done and modified it to suit but haven't tested it. Might need a few tweaks but hopefully gets you close!
// put dictionary A ~ T to a list of dictionary
List<Dictionary<int, DictionarySetup>> dictionaries = new List<Dictionary<int, DictionarySetup>>{A,B,C, ... , T}; // Replace ... with D,E,F, etc. until T
// iterate each dictionary and if found, exit the loop
foreach(var dict in dictionaries)
{
if(Dictionary_Test(dict))
{
Dictionary_Find(Account_String, rowindex, dict, Cash_Value, txtCurrency.Text);
break;
}
}

C# Populate dynamically nested Dictionary with unknown depth

I get an array of Nodes and a Value into my Method which have to be nested into a Dictionary Structure. But I really need help with the logic here.
I did a static Test which shows what I need:
public static Dictionary<string, object> CreateNestedDictionary(string[] chainNodes, string value)
{
// Testvalues:
// ["application", "deepNode", "evenDeeperNode"], "Value"
var container = new Dictionary<string, object>();
container.Add("application", new Dictionary<string, object>() { { "deepNode", new Dictionary<string, string>(){{"evenDeeperNode", "Value" } }}});
return container;
}
So basically, I have a Dictionary<string, object> variable, which can contain an infinite number of Dictionaries of the same type. At the very end, I need a Dictionary<string, string> to define the last node and the value.
By Node I mean the Key of the Dictionary. Those will later be represented in a JSON Sctructure.
The thing is, that I don't know how many Elements I get in chainNodes. Also, I may have to call this Method several times and add more Nodes. I would then have several chainNodes which have to go into the same Dictionary structure. Iwould then have to make sure that the Keys stay unique.
Is there any easy way to populate this structure dynamically? Or even a LINQ approach that deals with this?
Any advice is much appreciated. Thank you in advance
Update
After the comments I realized I did a really bad job explaining this.
Here is another example:
public static Dictionary<string, object> CreateNestedDictionary(string[] chainNodes, string value)
{
// Testvalues:
// ["application", "deepNode", "evenDeeperNode"], "Value"
var container = new Dictionary<string, object>();
for (int i = 0; i < chainNodes.Length; i++)
{
if (i != chainNodes.Length -1)
{
container.Add(chainNodes[i], new Dictionary<string, object>()); // fill this empty Dictionary
}
else
{
container.Add(chainNodes[i], value);
}
}
}
Adding the last Dictionary is easy but I don't know how to fill the Dictionaries after the first.
If I have understood this correctly: chainNodes is a list of the names, and value goes in the deepest dictionary (with name chainNodes[chainNodes.Length-1]).
Summary: you need to iterate and special case the deepest node.
Something recursive is probably easiest, starting with the pure creation case (no need to check for existing entries).
public Dictionary<string, object> CreateNestedDictionary(string[] chainNodes, object value) {
return DoCreate(chainNodes, value, 0);
}
private Dictionary<string, object> DoCreate(string[] chainNodes, object value, int index) {
var res = new Dictionary<string, object>();
if (index == chainNodes.Length - 1) {
// Bottom out the recursion
res.Add(chainNodes[index], value);
} else {
res.Add(chainNodes[index], DoCreate(chainNodes, value, index+1));
}
return res;
}
Recursion naturally allows you to special case that last string because that is the end case that recursion must have.
For the adding to an existing collection case, you need to change the recursion to:
Pass down the current node
Check if chainNodes[index] key exists and use that entry or create a new one.
Here's how I implemented infinite nesting Dictionaries.
My structure is: Dict([bool],object), ending with [bool] = true.
public void Init(bool[] boolArray)
{
BoolDict = new Dictionary<bool, object>();
Dictionary<bool, object> parent = BoolDict;
for (int index = 0; index < boolArray.Length; index++)
{
if (index < boolArray.Length - 1)
{
Dictionary<bool, object> nestedDict = new Dictionary<bool, object>();
parent.Add(boolArray[index], nestedDict);
parent = nestedDict;
}
else
{
parent.Add(boolArray[index], true);
}
}
}
It's important to save the new Dict as the parent so that you can add to the new parent which you created in the previous iteration.
You could remove the first value from the chainNodes and recursively call the method if there are any more values until you reach the end.
I'm with #Blorgbeard, though in that, this is a poor structure.
public static Dictionary<string, object> CreateNestedDictionary(string[] chainNodes, string value)
{
// Testvalues:
// ["application", "deepNode", "evenDeeperNode"], "Value"
var key = chainNodes.First();
chainNodes = chainNodes.Skip(1).ToArray();
return new Dictionary<string, object> { { key, chainNodes.Any() ? CreateNestedDictionary(chainNodes, value) : value } };
}

In C#, how do I change a Key-Value-Property's value while recursively traversing an ExpandoObject?

The Problem
Using C#, I need to traverse an object that has been cast to an ExpandoObject from XML and replace any "price" property with a new value.
This object is very unstructured and has many layers of nested nodes (nested ExpandoObjects, actually). More specifically, the hierarchy may look like this:
Product => price, quantity, accessories
Each accessory may have a price and quantity and may itself have accessories, this is why I need recursion.
What I have so far
public ExpandoObject UpdatePricing(ExpandoObject exp)
{
//Is there a price property?
var hasPrice = exp.Any(a => a.Key == "price");
if (hasPrice)
{
//update price here
exp.price = 0; //Some other price
}
//Now loop through the whole object. If any of the properties contain an expando, then call this method again
foreach (var kvp in exp)
{
if (kvp.Value is ExpandoObject)
{
//THIS CODE IS NO GOOD BECAUSE kvp.Value has no setter!!
kvp.Value = UpdatePricing(kvp.Value);
}
}
return exp;
}
The problem I run into is that the kvp.Value has no setter, so I can't run this method recursively.
Any suggestions are appreciated. Thanks!
Since ExpandoObject implements IDictionary<string, Object> things can get a bit easier. We can also change the return type to void because we don't need to reassign the result.
void UpdatePrice(ExpandoObject expando, decimal price)
{
var map = (IDictionary<string, Object>)expando;
if (map.ContainsKey("price"))
map["price"] = price;
foreach (var value in map.Values)
{
if (value is ExpandoObject)
UpdatePrice((ExpandoObject)value, price);
}
}
I don't know much about ExpandoObject. But like most dictionary implementations, I assume that in general if you want your key-value pair to be updated to have a different value, you need to go through the dictionary interface.
Note that you (probably) won't be allowed to modify the dictionary while you're enumerating its contents. So you'll need to build a list of elements to update and do that in a separate operation.
For example:
List<string> keysToUpdate = new List<string>();
foreach (var kvp in exp)
{
if (kvp.Value is ExpandoObject)
{
keysToUpdate.Add(kvp.Key);
}
}
foreach (string key in keysToUpdate)
{
exp[key] = UpdatePricing(exp[key]);
}
You could also keep the whole KeyValuePair value in your list, to avoid the second retrieval of the value, but I'm guessing that's not an important optimization here.
I just ran a little test on this and was able to get it to work by having the expando be dynamic:
public static ExpandoObject DoWork(ExpandoObject obj)
{
dynamic expando = obj;
//update price
if (obj.Any(c => c.Key == "price"))
expando.price = 354.11D;
foreach (var item in expando)
{
if (item.Value is ExpandoObject)
{
//call recursively
DoWork(item.Value);
}
}
return expando;
}
it elimitates type safety, but it looks like you don't have that luxury anyways, dynamic is the best way to interact with expandos in fact according to MSDN:
"In C#, to enable late binding for an instance of the ExpandoObject
class, you must use the dynamic keyword. For more information, see
Using Type dynamic (C# Programming Guide)."
this means that if you don't use the dynamic keyword, you are running the Expando in the CLR instead of the DLR which will have some odd consequences like not being able to set values. Hopefully this helps.

Alternatives to using property.setvalue() for efficiency purposes

What alternatives are there to property.setvalue()? I've read that it is very slow. I'm using it to map IDataReader to POCO objects.
This is a truncated version of the code. Everything here is very new to me. I know there a lot of frameworks that accomplish this task. However, we can't use them.
public class DbAutoMapper<T>
{
public IEnumerable<T> MapToList(IDataReader reader)
{
var list = new List<T>();
while (reader.Read())
{
var obj = Activator.CreateInstance<T>();
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
foreach (var attribute in prop.GetCustomAttributes(true))
{
prop.SetValue(obj, value, null);
}
}
list.Add(obj);
}
return list;
}
}
Firstly: why are you repeating the reflection for every attribute, when you don't use the attribute?
Second: assuming you intended to map this by name, column-to-property (which isn't what the code currently does), consider a tool like dapper, which does all this for you, including cached high-performance reflection-emit. It'll also handle the command itself for you. For example:
string region = "North";
var customers = conn.Query<Customer>(
#"select * from Customers where Region = #region",
new { region } // full parameterization, the easy way
).ToList();
If you need more control, consider FastMember, which provides fast member-access (again, reflection-emit), but without being specific to data access:
var accessor = TypeAccessor.Create(typeof(T));
string propName = // something known only at runtime
while( /* some loop of data */ ) {
var obj = new T();
foreach(var col in cols) {
string propName = // ...
object cellValue = // ...
accessor[obj, propName] = cellValue;
}
yield return obj;
}
A few approaches come to mind...
Skip Reflection
public class DbAutoMapper<T> where T : IInitFromReader, new()
{
public IEnumerable<T> MapToList(IDataReader reader)
{
var list = new List<T>();
while (reader.Read())
{
IInitFromReader obj = new T;
obj.InitFromReader(reader);
list.Add(obj);
}
return list;
}
}
Then you'll have to implement the InitFromReader in each of your entitiy objects. Obviously, this skips the benefits of reflection (less code).
Code Generation
Maintaining this code for (InitFromReader) is painful, so you could opt to generate it. This in many ways gives you the best of both worlds:
You don't have to maintain (by hand) a lot of code
You don't take the performance hit of reflection.

How can i cast into a ObservableCollection<object>

How can i cast
from ObservableCollection<TabItem> into ObservableCollection<object>
this doesnt work for me
(ObservableCollection<object>)myTabItemObservableCollection
you should copy like this
return new ObservableCollection<object>(myTabItemObservableCollection);
Basically, you can't. Not now, and not in .NET 4.0.
What is the context here? What do you need? LINQ has Cast<T> which can get you the data as a sequence, or there are some tricks with generic methods (i.e. Foo<T>(ObservalbleCollection<T> col) etc).
Or you can just use the non-generic IList?
IList untyped = myTypedCollection;
untyped.Add(someRandomObject); // hope it works...
you could use IEnumerable.Cast<T>()
You can't. ObservableCollection<TabItem> does not derive from ObservableCollection<object>.
If you explain why you would want to perhaps we can point out an alternative interface you can use.
thanx for all answers, but I think I have solve this problem self with a "helpermethode".
Perhaps has any a better method or a linq statement for this.
private void ConvertTabItemObservableCollection()
{
Manager manager = this.container.Resolve<Manager>();
foreach (var tabItem in manager.ObjectCollection)
{
TabItemObservableCollection.Add((TabItem)tabItem);
}
}
None of the examples I have found have worked for me, I have cobbled together the below code and it seems to work. I have a hierarchy that is created by deserializing an XML file and I am able to loop through all the objects in the hierarchy, but you can adapt this to just loop through one ObservableCollection and get the objects as objects and not strongly typed.
I want to add a PropertyChangingEventHandler to every property in the hierarchy so that I can implement undo/redo functionality.
public static class TraversalHelper
{
public static void TraverseAndExecute(object node)
{
TraverseAndExecute(node, 0);
}
public static void TraverseAndExecute(object node, int level)
{
foreach (var property in node.GetType().GetProperties())
{
var propertyValue = node.GetType().GetProperty(property.Name).GetGetMethod().Invoke(node, null); // Get the value of the property
if (null != propertyValue)
{
Console.WriteLine("Level=" + level + " : " + property.Name + " :: " + propertyValue.GetType().Name); // For debugging
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(ObservableCollection<>)) // Check if we are dealing with an observable collection
{
//var dummyvar = propertyValue.GetType().GetMethods(); // This was just used to see which methods I could find on the Collection
Int32 propertyValueCount = (Int32)propertyValue.GetType().GetMethod("get_Count").Invoke(propertyValue, null); // How many objects in the collection
level++;
for (int i = 0; i < propertyValueCount; i++) // Loop over all objects in the Collection
{
object properyValueObject = (object)propertyValue.GetType().GetMethod("get_Item").Invoke(propertyValue, new object[] { i }); // Get the specified object out of the Collection
TraverseAndExecute(properyValueObject, level); // Recursive call in case this object is a Collection too
}
}
}
}
}
}
The method is just called like this
TraversalHelper.TraverseAndExecute(object);
If you just want to create a collection of objects you just need this bit of code
ObservableCollection<Field> typedField = migration.FileDescriptions[0].Inbound[0].Tables[0].Table[0].Fields[0].Field; // This is the strongly typed decalaration, a collection of Field objects
object myObject = typedField; // Declare as object
Int32 propertyValueCount = (Int32)myObject.GetType().GetMethod("get_Count").Invoke(myObject, null); // How many objects in this Collection
for (int i = 0; i < propertyValueCount; i++) // Loop over all objects in the Collection
{
object properyValueObject = (object)myObject.GetType().GetMethod("get_Item").Invoke(myObject, new object[] { i }); // Get the specified object out of the Collection, in this case a Field object
// Add the object to a collection of objects, or whatever you want to do with object
}
You can Cast it as INotifyCollectionChanged;
Like:
if (myTabItemObservableCollection is INotifyCollectionChanged collection)
{
Do Stuff
}

Categories

Resources