C# associative array - c#

I've been using a Hashtable, but by nature, hashtables are not ordered, and I need to keep everything in order as I add them (because I want to pull them out in the same order). Forexample if I do:
pages["date"] = new FreeDateControl("Date:", false, true, false);
pages["plaintiff"] = new FreeTextboxControl("Primary Plaintiff:", true, true, false);
pages["loaned"] = new FreeTextboxControl("Amount Loaned:", true, true, false);
pages["witness"] = new FreeTextboxControl("EKFG Witness:", true, true, false);
And when I do a foreach I want to be able to get it in the order of:
pages["date"]
pages["plaintiff"]
pages["loaned"]
pages["witness"]
How can I do this?

I believe that .NET has the OrderedDictionary class to deal with this. It is not generic, but it can serve as a decent Hashtable substitute - if you don't care about strict type safety.
I've written a generic wrapper around this class, which I would be willing to share.
http://msdn.microsoft.com/en-us/library/system.collections.specialized.ordereddictionary.aspx

EDIT: LBushkin is right - OrderedDictionary looks like it does the trick, albeit in a non-generic way. It's funny how many specialized collections there are which don't have generic equivalents :( (It would make sense for Malfist to change the accepted answer to LBushkin's.)
(I thought that...) .NET doesn't have anything built-in to do this.
Basically you'll need to keep a List<string> as well as a Dictionary<string,FreeTextboxControl>. When you add to the dictionary, add the key to the list. Then you can iterate through the list and find the keys in insertion order. You'll need to be careful when you remove or replace items though.

use sorted list i think it will solve your problem
becuase SortedList object internally maintains two arrays to store the elements of the list; that is, one array for the keys and another array for the associated values. Each element is a key/value pair that can be accessed as a DictionaryEntry object
SortedList sl = new SortedList();
foreach(DictionaryEntry x in sl)
{}

Use the KeyedCollection
Its underlying base is a List but provides a dictionary lookup based on key. In this case your key is the strings. So as long as you aren't adding the same key twice you are fine.
http://msdn.microsoft.com/en-us/library/ms132438.aspx

There's no perfect solution before .NET 4.0. In < 3.5 You can:
Use a generic SortedList with integer key-type, and value type of the most-derived common type of your items. Define an integer value (i, let's say) and as you add each item to the SortedList, make the key i++, incrementing it's value as you go. Later, iterate over the GetValueList property of the sorted list. This IList property will yield your objects in the order you put them in, because they will be sorted by the key you used.
This is not lightening-fast, but pretty good, and generic. If you want to also access by key, you need to do something else, but I don't see that in your requirements. If you don't new to retrieve by key, and you add items in key order so the collection doesn't actually have to do its sorting, this is it.
In .NET 4.0 you'll have the generic SortedSet Of T, which will be absolutely perfect for you. No tradeoffs.

The best way is to use the C# indexers. It is configurable to anything we like. We can pass an int, enum, long, double or anything we like.
Just have to create a class and give it indexers and configure input and output parameters. It is a little more work but I think this is the only right way.
Please see this MSDN link for more information how to use it.

See Indexers: http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx

One alternative is to keep your ordered key values in an ordered structure like a List, the rest being still stored in a dictionnary.
Then, when you need to access your data, just go through your sorted List and query your dictionnary along the way.

look at sorted list
http://msdn.microsoft.com/en-us/library/system.collections.sortedlist.aspx

As Haxelit suggests, you might derive from KeyedCollection<TKey, TValue>. It actually uses a List underneath until you hit a certain threshold value, and then it maintains both a List and a Dictionary. If you can use a function to derive one of your keys from one of your values, then this is an easy solution. If not, then it gets pretty messy.

Related

A two way KeyValuePair collection in C#

By creating a Dictionary<int,int> or List<KeyValuePair<int,int>> I can create a list of related ids.
By calling collection[key] I can return the corresponding value stored against it.
I also want to be able to return the key by passing in a value - which I know is possible using some LINQ, however it doesn't seem very efficient.
In my case along with each key being unique, each value is too. Does this fact make it possible to use another approach which will provide better performance?
It sounds like you need a bi-directional dictionary. There are no framework classes that support this, but you can implement your own:
Bidirectional 1 to 1 Dictionary in C#
You could encapsulate two dictionaries, one with your "keys" storing your values and the other keyed with your "values" storing your keys.
Then manage access to them through a few methods. Fast and the added memory overhead shouldn't make a huge difference.
Edit: just noticed this is essentially the same as the previous answer :-/

Where to use string [] vs list <string> in C#

String[] is light weight compared to list<string>. So if I don't have any need to manipulate my collection, should I use string[] or is it always advisable to go for list<string>?
In case of list<string>, do we need to perform null check or not required?
Use string[] when you need to work with static arrays: you don't need to add and remove elements -> only access elements by index. If you need to modify the collection use List<string>. And if you intend to only loop through the contents and never access by index use IEnumerable<string>.
If the collection should not be modified, use string[] or even better, IEnumerable<string>. This indicates that the collection of strings should be treated as a read-only collection of strings.
Using IEnumerable<string> in your API also opens up for the underlying implementation to be changed without breaking client code. You can easily use a string array as the underlying implementation and expose it as IEnumerable<string>. If the implementation at a later stage is better suited using a list or other structure, you can change it as long as it supports IEnumerable<string>.
I'd say you've summed it up well yourself.
If the size of your list won't change, and you don't need any of the advanced List functions like sorting, then String[] is preferable because as you say it's lightweight.
But consider potential future requirements - is it possible that you might one day want to use List for something? If so, consider using List now.
You need to check for null, both in String[] and also List. Both types can have a null value.
I would say it depends what you're trying to accomplish. Generally, however, my opinion is that you have access to a great framework that does a lot of hard work for you so use it (ie. use List<> instead of array).
Have a look at the members on offer to you by a class like List<> and you'll see what I mean: in addition to not having to worry as much about array capacity and index out of bounds exceptions, List and other ICollection/IList classes give you methods like Add, Remove, Clear, Insert, Find, etc that are infinitely helpful. I also believe
myList.Add (myWidg);
is a lot nicer to read and maintain than
myArr [i] = myWidg;
I would definitely vote for List. Apart from various member functions that a list supports, it provides 'no element' concept. There can be a list which have no elements but there cannot be an array with no elements. So, if we adhere to best practices of not returning null from a function, then we can safely check for the count of the element without doing a null check. In case of array, we have to check the null. Moreover, I seldom use a loop to search an element, either in array or list. LINQ just makes it neat and we can use it with List not array. Array has to be converted to list to make use of LINQ.
This really really depends on the situation. Anything really performance related should probably be done with arrays. Anything else would go with lists.

IList<KeyValuePair> vs IDictionary to serve as [DataMember] in WCF

I have a dictionary data structure that must be passed around using WCF. To do that I created a member property with get and set methods. I can basicly achieve the same functionality, with this property being either a:
IDictionary<keyType, valueType>
or a
IList<KeyValuePair<keyType, valueType>>
I can see no strong reason for choosing one over the other. One mild reaons I could think of is:
IDictionary - People reading the code will think that IDictionary makes more sense, since the data structure is a dictionary, but in terms of what is passed through WCF they are all the same.
Can anyone think of a reason to choose IList? If there is none I'll just go with IDictionary.
Design your interfaces based on use, not on implementation.
If the consumer of a class needs to iterate through the entire set, use IEnumerable. If they should be able to modify the result, and need index-based access, return IList. If they want specific items, and there is a single useful key value, return IDictionary.
Write your internal code this way, too :)
It depends on your consumers. I would cater for the most likely use case and make their API as simple as possible. Edge cases can always iterate the dictionary via the Values collection.
Don't make them think about it. If the the term dictionary is what they'd think about as the result of the operation and then the type with name is a very useful thing to use.
If the collection of keyValuePairs expects unique key, you can use dictionary.
If the same key can appear in more than one keyValuePair, use Ilist/ ienumerable.

How to get a partilcular item from a Dictionary object with index?

How to retrive an item from an dictionary object using an Index? eg i have a dicitiory object of 10 items and i have to get the 5th keypairvalue from the dictionary?
Dictionaries are unordered. If you mean "the 5th item added to the dictionary" - they don't provide this functionality.
One thing to be careful of is that in many cases Dictionary<TKey, TValue> appears to be ordered - if you just add a bunch of entries and then iterate, then under the current implementation I believe you will at least usually get back the pairs in the same order. However, it's not guaranteed, it's not meant to happen particularly - it's just a quirk of the implementation. If you delete entries and then add more, then the whole thing goes pear-shaped.
Fundamentally, if you want ordering as well as key lookups, you need to store a list as well as a dictionary.
If you are using .NET 3.5 or greater:
var keyValuePair = d.ElementAt(4);
However, this is using an enumerator behind the scenes and the ordering of enumerated items from a dictionary is not guaranteed:
The IDictionary interface allows the contained keys and values to be enumerated, but it does not imply any particular sort order (From IDictionary reference on MSDN).
This means that the element you get back might not correspond to the order you inserted it in and thus is probably not what you expect.
There is an OrderedDictionary class in System.Collections.Specialized that enforces the ordering and allows you to access by index through the Item indexer. However, this is from the pre-generics days so it only accepts object key-values and thus isn't quite as friendly to work with as the generic collections.
I just found this article on CodeProject that implements a generic OrderedDictionary. I have never used this but it might be useful for you.
Ignoring the fundamental abuse of a dictionary that this question presents:
int counter = 0;
foreach (var pair in yourDictionary)
{
if (++counter == 5)
{
// pair contains your fifth item
}
}
If you're using a generic dictionary like this:
Dicionary<int,string> myDict = new Dictionary<int,string>();
You could pull the 5th value from the dictionary by converting the output to a list:
string SomeString = myDict.Values.ToList()[4];
But typically you'd use a dictionary when you're more concerned about retrieving a value based on a pre-determined key rather than it's position in the list.
The 5th according to which ordering? The Dictionary class does not guarantee any specific ordering. If you want it in some specific ordering, retrieve the pairs from the collection (for example as John suggests) and sort them, then get the KeyValuePair at the index you need. If you need it ordered by insertion order, try using the System.Collections.Specialized.OrderedDictionary instead, then you can access the KeyValuePair directly by index.
Use System.Linq
string item=dicOBj.Keys.ElementAt(index);
you can get both key and value in the same way specifying index
.NET Framework has 8 dictionary classes: Dictionary, Hastable, ListDictionary, OrderedDictionary, SortedDictionary , SortedList, SortedList Generic. In all these classes items can be retrieved by key, but items can be retrieved by index only in OrderedDictionary, SortedList, SortedList Generic. If you need to retrieve from you dictionary items by key or by index you must use one of these classes: OrderedDictionary, SortedList, SortedList Generic.
How to use these classes you can find: OrderedDictionary Class , SortedList Class

Strange C# struct in collection behaviour

Any ideas as to why this
public Collection<Point> data = new Collection<Point>(){
new Point{X=10,Y=20},
new Point{X=20,Y=30},
new Point{X=40,Y=20},
new Point{X=10,Y=20}
};
(notice the identical first and last elements)
gives the error
An item with the same key has already been added.
If you change the last element to Y=20.1 or anything that makes it different then it works.
Also you can add the elements anyway you like and get the same result.
The problem is obviously due to Point being a value type because it goes away if you define and use a point class and I know that there are problems with using structs in other collection types but this has to do with the difference between value and ref return types. What mystifies me is that this works if the all the structs have different field values.
The reason is because equality of a value type is based on its values - for struct it is equality across all its fields.
Reference type equality is based on the reference itself and thus works. Changing the struct values to be all different also works.
If you just want a list of stuff, just use List<Point>, I think that will accept duplicates.
Update: it looks like your collection class is detecting duplicate entries and you are trying to add duplicates. If you want to add duplicates, I would say you cannot use this class.
Have you tried using a List instead? I think it should work!
Hope that helps!
I'm not familiar with this collection class you're using but apparently it doesn't allow multiple items to be in it. As it is with a SET collection. So I guess the Collection you're using is equivalent to:
Dictionary<String, Point>
but since you you dont have a key it's more like
HashSet<Point>
Just like your collection class a HashSet requires all keys to be unique. Like Kieren mentions a List would be more suitable for you. A list allows multiple entries to be the same.
Indeed if Point was a class it would allow duplicates since Objec1 != Object2 to even if their values are the same.
I'm really not sure on this, but I have a feeling that because the compiler generates a strong Collections item that doesn't require to box/unbox value types, the key check is done on the explicit value type itself, which produces the duplicate key exception?
That's really just a shot in the dark!
What is Collection class. It's not .NET Framework library class. Look docs or sources of this class, it would explain the problem.

Categories