Collection of key-value pairs, where the key depends on the value

I have a class MyClass

 class MyClass { public string Name { get; set; } // is unique among all instances public SomeClass Data { get; set; } ... } 

from which I want to save multiple instances in the collection. I will often need to check if an instance with a specific name exists, and if that happens, retrieve that instance. Since repeating the entire collection is not an option (performance!), I thought about using a set of key-value pairs, for example. a IDictionary<string, MyClass> .

My program will also allow renaming MyClass instances (this will not allow renaming if the uniqueness of the name is violated). But if I rename a MyClass , I will also need to delete the old entry from the dictionary and add a new one (i.e. With a new name) so that the data is consistent.

The problem is that I will have several such dictionaries (which contain subsets of all instances of MyClass ) everywhere, and it will be difficult to track them and update all dictionaries sequentially after each rename.

Is there a way to automatically support key-value pairs? I think I heard about a data structure that allows this, which exists, at least in C ++ (unfortunately, I have no idea what it's called). In principle, this should be a collection in which the key is not just a simple string, but rather as a link to a string (in this case, the name property), but behaves as if it were a string. Is there such a thing in C #? Do you have other ideas on how to keep the collection consistent?

My only idea is to collect all the dictionaries at the highest level of my program and make a way to rename to update all these dictionaries after the actual renaming process. But there must be a better way!


Why this question is not a duplicate. The best way to change the dictionary key :

I already know that the dictionary does not allow changing the key. Instead, I will ask for another data structure that is somehow compatible with key changes (without loss of performance), and I also ask for other approaches. Therefore, my question is much more open to input from any direction, if it helps to solve the problem of data storage.

+5
source share
2 answers

As far as I understand you, your problem is this:

  • You have several dictionaries, each of which contains part of your data.
  • All your instances must have a unique name in all dictionaries.
  • When the name is changed:
    • First check this unique name.
    • Update it in all the dictionaries that he lives in

I think I would solve this problem a little differently.

First, add the identifier field to the class, which will be the number of Guid / running, this field should never change since the instance was created.
Then add another dictionary that will contain only the names and identifiers of the instances, it should look something like this:

 [{"FirstName": "Guid1"}, {"SecondName": "Guid2"}, {"ThirdName": "Guid3"}] 

The rest of your dictionaries will contain an identifier as their key, not a name:

 [{"Guid1": {instance1}}, {"Guid2": {instance2}}] 

Now, when you change the instance name, all the names exist in one dictionary, which will tell you if it exists. And you need to change it in only one place, since the rest of the dictionaries rely on a constant value that will never change.
So say you want to change the name "FirstName" , the name dictionary will look like this:

 [{"OtherName": "Guid1"}, {"SecondName": "Guid2"}, {"ThirdName": "Guid3"}] 

And the rest of the data does not need to be changed.

+2
source

I do not think that there is a native collection for this. However, you can easily create your own by simply adding some kind of notification to your base class.

  public class ChangingNameObject { public delegate void ObjectNameChange(string oldName, string newName); public event ObjectNameChange ObjectNameChanged; private string name; public string Name { get => name; set { ObjectNameChanged?.Invoke(name, value); name = value; } } } public class WatchingDictionary { private Dictionary<string, ChangingNameObject> content = new Dictionary<string, ChangingNameObject>(); public void Add(ChangingNameObject item) { item.ObjectNameChanged += UpdatePosition; content[item.Name] = item; } public void Remove(ChangingNameObject item) { item.ObjectNameChanged -= UpdatePosition; content.Remove(item.Name); } private void UpdatePosition(string oldname, string newname) { var o = content[oldname]; content.Remove(oldname); content.Add(newname, o); } } 

I just wrote a very simple material, and you missed all the accessors and counters, just add the one you need.

Be very careful with the listing, although changing the collection during the listing will fail (and since the collection will be hidden, you can do this without knowing)

+1
source

Source: https://habr.com/ru/post/1272325/


All Articles