This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C# dictionary type with unique keys and values
I would like to make sure that a dictionary has unique keys AND values. Is there any way to add this kind of validation outside of building my own class? That is the only way I can think of accomplishing validation for values in a dictionary. But, maybe there is some attribute I could add that I cannot seem to find via google.
I am looking to use this dictionary with WPF bindings, if that helps, also.
Dictionary keys are unique, by definition. Ensuring dictionary values are unique is done the same way you'd check every array or collection member is unique.
.NET 3.5 introduces HashSet<T> which speeds things up, assuming your TValue type implements Equals(TValue).
HashSet<TValue> seenValues = new HashSet<TValue>();
foreach(TKey key in myDictionary) {
if( seenValues .Contains( myDictionary[key] ) ) throw new Exception("Dictionary contains duplicate item.");
seenValues .Add( myDictionary[key] );
}
You could try using this two-way dictionary class:
public class Map<T1, T2>
{
private Dictionary<T1, T2> _forward = new Dictionary<T1, T2>();
private Dictionary<T2, T1> _reverse = new Dictionary<T2, T1>();
public Map()
{
this.Forward = new Indexer<T1, T2>(_forward);
this.Reverse = new Indexer<T2, T1>(_reverse);
}
public class Indexer<T3, T4>
{
private Dictionary<T3, T4> _dictionary;
public Indexer(Dictionary<T3, T4> dictionary)
{
_dictionary = dictionary;
}
public T4 this[T3 index]
{
get { return _dictionary[index]; }
set { _dictionary[index] = value; }
}
}
public void Add(T1 t1, T2 t2)
{
_forward.Add(t1, t2);
_reverse.Add(t2, t1);
}
public Indexer<T1, T2> Forward { get; private set; }
public Indexer<T2, T1> Reverse { get; private set; }
}
You can use it like this:
var map = new Map<int, string>();
map.Add(42, "Hello");
Console.WriteLine(map.Forward[42]);
// Outputs "Hello"
Console.WriteLine(map.Reverse["Hello"]);
//Outputs 42
It's a fairly simple implementation. You would probably need to expose some of the underlying dictionary functionality, but at least it is a start.
Related
Imagine this scenario: I need to manipulate (add, search and delete) items from a list of objects of type Book.
class Book{
int Id {get; set;}
string Title {get; set;}
string Author {get; set;}
int Year {get; set;}
// more properties
}
Constriants:
Id should be unique within the collection of Books
Title should be unique within the collection of Books
What I have so far, a Dictionary<int, Book> that has Id as a key and Book as a value. But in this case, If I want to add a new book to the dictionary I have to loop through all the values to check whether the Title is duplicate or not.
I start thinking about creating a HashSet only for Titles or having a second dictionary Dictionary<string, Book> that has Title as a key.
Any suggestion How to handle this scenario?
Edit:
As #David mentioned, I forgot to tell that my main concern here is performance. I want to lookup objects by Id and Title in the fastest way (O(1)).
You might use Tuple as the key:
var collection = new Dictionary<Tuple<int, string>, Book> (...);
var key = new Tuple<int, string>(1, "David"); // <<-----------
if(!collection.ContainsKey(key))
collection [key] = new Book(...);
Note that Tuple has its built in Equals() to make your life easier.
Update:
#AustinWBryan mentioned using ValueTuples (C# 7.0 feature) to replace Tuple, highly recommended. For more info about ValueTuples, refer to this link.
To ensure that both sides of the composite key are also unique a tuple won't cut it. Instead make your own key that checks for this in the equality checker.
public struct CompositeKey<T1, T2> : IEquatable<CompositeKey<T1, T2>>
{
private static readonly EqualityComparer<T1> t1Comparer = EqualityComparer<T1>.Default;
private static readonly EqualityComparer<T2> t2Comparer = EqualityComparer<T2>.Default;
public T1 Key1;
public T2 Key2;
public CompositeKey(T1 key1, T2 key2)
{
Key1 = key1;
Key2 = key2;
}
public override bool Equals(object obj) => obj is CompositeKey<T1, T2> && Equals((CompositeKey<T1, T2>)obj);
public bool Equals(CompositeKey<T1, T2> other)
{
return t1Comparer.Equals(Key1, other.Key1)
&& t2Comparer.Equals(Key2, other.Key2);
}
public override int GetHashCode() => Key1.GetHashCode();
}
So the dictionary works on buckets. It puts all the keys into buckets based on the hash code generated by GetHashCode(). Then it searches that bucket using a for loop over Equals(). The idea is that buckets should be as small as possible (ideally one item).
So we can control when a key will match, and how many buckets/items there are by controlling the hash code. If we return a constant hash code like 0, then everything is in the same bucket and it's down to the equality method to compare every item.
This comparer only returns the hash of the first key item. Assuming the first key item should be unique this is enough. Each bucket should still be one item, and when doing a lookup (that uses the full equals method) that's when the second key is also checked to ensure the type is the same value.
If you want to use ValueTuple as the key type you can pass in a custom comparer to the dictionary to achieve the same effect.
public class CompositeValueTupleComparer<T1, T2> : IEqualityComparer<(T1, T2)>
{
private static readonly EqualityComparer<T1> t1Comparer = EqualityComparer<T1>.Default;
private static readonly EqualityComparer<T2> t2Comparer = EqualityComparer<T2>.Default;
public bool Equals((T1, T2) x, (T1, T2) y) =>
t1Comparer.Equals(x.Item1, y.Item1) && t2Comparer.Equals(x.Item2, y.Item2);
public int GetHashCode((T1, T2) obj) => obj.Item1.GetHashCode();
}
new Dictionary<(int, string), Book>(new CompositeValueTupleComparer<int, string>());
It seems like both the ID and Name are going to be unique, as in, you shouldn't be able to use the same ID twice, regardless if the name has been used already. Otherwise, we'd end up with dict[3] referring to two different values.
Tuples or structs can't give that behavior, and still require you to loop. What you should instead do, is use a class similar to the one I've created:
public class TwoKeyDictionary<TKey1, TKey2, TValue>
{
public readonly List<TKey1> firstKeys = new List<TKey1>();
public readonly List<TKey2> secondKeys = new List<TKey2>();
public readonly List<TValue> values = new List<TValue>();
public void Add(TKey1 key1, TKey2 key2, TValue value)
{
if (firstKeys.Contains(key1)) throw new ArgumentException();
if (secondKeys.Contains(key2)) throw new ArgumentException();
firstKeys.Add(key1);
secondKeys.Add(key2);
values.Add(value);
}
public void Remove(TKey1 key) => RemoveAll(firstKeys.IndexOf(key));
public void Remove(TKey2 key) => RemoveAll(secondKeys.IndexOf(key));
private void RemoveAll(int index)
{
if (index < 1) return;
firstKeys.RemoveAt(index);
secondKeys.RemoveAt(index);
values.RemoveAt(index);
}
public TValue this[TKey1 key1]
{
get
{
int index = firstKeys.IndexOf(key1);
if (index < 0) throw new IndexOutOfRangeException();
return values[firstKeys.IndexOf(key1)];
}
}
public TValue this[TKey2 key2]
{
get
{
int index = secondKeys.IndexOf(key2);
if (index < 0) throw new IndexOutOfRangeException();
return values[secondKeys.IndexOf(key2)];
}
}
}
And then you can use it like this:
var twoDict = new TwoKeyDictionary<int, string, float>();
twoDict.Add(0, "a", 0.5f);
twoDict.Add(2, "b", 0.25f);
Console.WriteLine(twoDict[0]); // Prints "0.5"
Console.WriteLine(twoDict[2]); // Prints "0.25"
Console.WriteLine(twoDict["a"]); // Prints "0.5"
Console.WriteLine(twoDict["b"]); // Prints "0.25"
twoDict.Add(0, "d", 2); // Throws exception: 0 has already been added, even though "d" hasn't
twoDict.Add(1, "a", 5); // Throws exception: "a" has already been added, even though "1" hasn't
The TwoKeyDictionary would need to implement ICollection, IEnumerable, etc., to do the full behavior stuff
I'd like to create a Dictionary object, with string Keys, holding values which are of a generic type. I imagine that it would look something like this:
Dictionary<string, List<T>> d = new Dictionary<string, List<T>>();
And enable me to add the following:
d.Add("Numbers", new List<int>());
d.Add("Letters", new List<string>());
I know that I can do it for a list of strings, for example, using this syntax:
Dictionary<string, List<string>> d = new Dictionary<string, List<string>>();
d.Add("Key", new List<string>());
but I'd like to do it for a generic list if possible...
2 questions then:
Is it possible?
What's the syntax?
EDIT: Now I've reread the question...
You can't do this, but a custom collection would handle it to some extent. You'd basically have a generic Add method:
public void Add<T>(string key, List<T> list)
(The collection itself wouldn't be generic - unless you wanted to make the key type generic.)
You couldn't extract values from it in a strongly typed manner though, because the compiler won't know which type you've used for a particular key. If you make the key the type itself, you end with a slightly better situation, but one which still isn't supported by the existing collections. That's the situation my original answer was responding to.
EDIT: Original answer, when I hadn't quite read the question correctly, but which may be informative anyway...
No, you can't make one type argument depend on another, I'm afraid. It's just one of the things one might want to express in a generic type system but which .NET's constraints don't allow for. There are always going to be such problems, and the .NET designers chose to keep generics relatively simple.
However, you can write a collection to enforce it fairly easily. I have an example in a blog post which only keeps a single value, but it would be easy to extend that to use a list.
Would something like this work?
public class GenericDictionary
{
private Dictionary<string, object> _dict = new Dictionary<string, object>();
public void Add<T>(string key, T value) where T : class
{
_dict.Add(key, value);
}
public T GetValue<T>(string key) where T : class
{
return _dict[key] as T;
}
}
Basically it wraps all the casting behind the scenes for you.
How about Dictionary<string, dynamic>? (assuming you're on C# 4)
Dictionary<string, dynamic> Dict = new Dictionary<string, dynamic>();
Source: https://stackoverflow.com/a/5038029/3270733
I prefer this way of putting generic types into a collection:
interface IList
{
void Add (object item);
}
class MyList<T> : List<T>, IList
{
public void Add (object item)
{
base.Add ((T) item); // could put a type check here
}
}
class Program
{
static void Main (string [] args)
{
SortedDictionary<int, IList>
dict = new SortedDictionary<int, IList> ();
dict [0] = new MyList<int> ();
dict [1] = new MyList<float> ();
dict [0].Add (42);
dict [1].Add ("Hello"); // Fails! Type cast exception.
}
}
But you do lose the type checks at compile time.
I came to a type safe implementation using ConditionalWeakTable.
public class FieldByType
{
static class Storage<T>
where T : class
{
static readonly ConditionalWeakTable<FieldByType, T> table = new ConditionalWeakTable<FieldByType, T>();
public static T GetValue(FieldByType fieldByType)
{
table.TryGetValue(fieldByType, out var result);
return result;
}
public static void SetValue(FieldByType fieldByType, T value)
{
table.Remove(fieldByType);
table.Add(fieldByType, value);
}
}
public T GetValue<T>()
where T : class
{
return Storage<T>.GetValue(this);
}
public void SetValue<T>(T value)
where T : class
{
Storage<T>.SetValue(this, value);
}
}
It can be used like this:
/// <summary>
/// This class can be used when cloning multiple related objects to store cloned/original object relationship.
/// </summary>
public class CloningContext
{
readonly FieldByType dictionaries = new FieldByType();
public void RegisterClone<T>(T original, T clone)
{
var dictionary = dictionaries.GetValue<Dictionary<T, T>>();
if (dictionary == null)
{
dictionary = new Dictionary<T, T>();
dictionaries.SetValue(dictionary);
}
dictionary[original] = clone;
}
public bool TryGetClone<T>(T original, out T clone)
{
var dictionary = dictionaries.GetValue<Dictionary<T, T>>();
if (dictionary == null)
{
clone = default(T);
return false;
}
return dictionary.TryGetValue(original, out clone);
}
}
See also this question where the type of the values is stored in as a generic parameter of the keys.
We're using lots of reflection to create an extensible administration tool. We needed a way to register items in the global search in the module definition. Each search would return results in a consistent way, but each one had different dependencies. Here's an example of us registering search for a single module:
public void ConfigureSearch(ISearchConfiguration config)
{
config.AddGlobalSearchCallback<IEmploymentDataContext>((query, ctx) =>
{
return ctx.Positions.Where(p => p.Name.Contains(query)).ToList().Select(p =>
new SearchResult("Positions", p.Name, p.ThumbnailUrl,
new UrlContext("edit", "position", new RouteValueDictionary(new { Id = p.Id }))
));
});
}
In the background during module registration, we iterate over every module and add the Func to a SearchTable with an instance of:
public class GenericFuncCollection : IEnumerable<Tuple<Type, Type, Object>>
{
private List<Tuple<Type, Type, Object>> objects = new List<Tuple<Type, Type, Object>>();
/// <summary>
/// Stores a list of Func of T where T is unknown at compile time.
/// </summary>
/// <typeparam name="T1">Type of T</typeparam>
/// <typeparam name="T2">Type of the Func</typeparam>
/// <param name="func">Instance of the Func</param>
public void Add<T1, T2>(Object func)
{
objects.Add(new Tuple<Type, Type, Object>(typeof(T1), typeof(T2), func));
}
public IEnumerator<Tuple<Type, Type, object>> GetEnumerator()
{
return objects.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return objects.GetEnumerator();
}
}
Then when we finally call it, we do it with reflection:
var dependency = DependencyResolver.Current.GetService(search.Item1);
var methodInfo = search.Item2.GetMethod("Invoke");
return (IEnumerable<SearchResult>)methodInfo.Invoke(search.Item3, new Object[] { query, dependency });
I didn't find what I was looking for here but after reading I think it might be what is being asked for so an attempt to answer.
The problem is that when you use Dictionary it is a closed constructed type and all elements must be of the TValue type. I see this question in a number of places without a good answer.
Fact is that I want indexing but each element to have a different type and based on the value of TKey we already know the type. Not trying to get around the boxing but trying to simply get more elegant access something like DataSetExtensions Field. And don't want to use dynamic because the types are known and it is just not wanted.
A solution can be to create a non generic type that does not expose T at the class level and therefore cause the TValue part of the dictionary to be closed constructed. Then sprinkle in a fluent method to help initialization.
public class GenericObject
{
private object value;
public T GetValue<T>()
{
return (T)value;
}
public void SetValue<T>(T value)
{
this.value = value;
}
public GenericObject WithValue<T>(T value)
{
this.value = value;
return this;
}
}
class Program
{
static void Main(string[] args)
{
Dictionary<string, GenericObject> dict = new Dictionary<string, GenericObject>();
dict["mystring"] = new GenericObject().WithValue<string>("Hello World");
dict["myint"] = new GenericObject().WithValue<int>(1);
int i = dict["myint"].GetValue<int>();
string s = dict["mystring"].GetValue<string>();
}
}
Other posibility it's to use the variable dynamic.
For example:
Dictionary<string, List<dynamic>> d = new Dictionary<string, List<dynamic>>();
d.Add("Key", new List<dynamic>());
the variable dynamic resolve the type on runtime.
No, but you can use object instead of generic type.
Long answer:
The current version of C# will not allow you to make entries of generic type in a dictionary. Your options are either a) create a custom class that is the same as a dictionary except allow it to accept generic types, or b) make your Dictionary take values of type object. I find option b to be the simpler approach.
If you send lists of specific types, then when you go to process the lists you will have to test to see what kind of list it is. A better approach is to create lists of objects; this way you can enter integers, strings, or whatever data type you want and you don't necessarily have to test to see what type of object the List holds. This would (presumably) produce the effect you're looking for.
Here is a short console program that does the trick:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace dictionary
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, object> dic = new Dictionary<string, object>();
var lstIntList = new List<object>();
var lstStrings = new List<object>();
var lstObjects = new List<object>();
string s = "";
lstIntList.Add(1);
lstIntList.Add(2);
lstIntList.Add(3);
lstStrings.Add("a");
lstStrings.Add("b");
lstStrings.Add("c");
dic.Add("Numbers", lstIntList);
dic.Add("Letters", lstStrings);
foreach (KeyValuePair<string, object> kvp in dic)
{
Console.WriteLine("{0}", kvp.Key);
lstObjects = ((IEnumerable)kvp.Value).Cast<object>().ToList();
foreach (var obj in lstObjects)
{s = obj.ToString(); Console.WriteLine(s);}
Console.WriteLine("");
}
Console.WriteLine("");
Console.WriteLine("press any key to exit");
Console.ReadKey();
}//end main
}
}
One of the way is to create a Dictionary value with type "object" like:
Dictionary<string, object> d = new Dictionary<string, object>();
So, here object datatype is used as a generic datatype, you can put anything in this as a value.
Or it's possible to use generic Type like this
public static void SafeUpdateInDictionary<T, L>(T DictionaryToBeUpdated, string Key, L Value) where T : Dictionary<string, L>
{
if (DictionaryToBeUpdated != null)
{
if(Value != null)
{
if (!DictionaryToBeUpdated.ContainsKey(Key))
DictionaryToBeUpdated.Add(Key, Value);
else
DictionaryToBeUpdated[Key] = Value;
}
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to get null instead of the KeyNotFoundException accessing Dictionary value by key?
I currently have lots of Dictionary<string, T> uses in my project, and most of them look like so:
if (myDic.ContainsKey("some key"))
localVar = myDic["some key"];
It's not very effecient too, as it does two calls to the dictionary, which can be resource consuming. TryGetValue() is a cool thing, but it just doesn't do it in one line.
I just want to get null if there is no such key from var v = myDic[key]. How do I do that?
You may use an extension method with TryGetValue:
public static U GetValueByKeyOrNull<T, U>(this Dictionary<T, U> dict, T key)
where U : class
{
U value;
dict.TryGetValue(key, out value);
return value;
}
thanks to which you'll be able to write
somedict.GetValueByKeyOrNull("key1")
In the end trying to do this very thing I came up with a variant using a deriving from dictionary class with explicit interface implementation: How to get null instead of the KeyNotFoundException accessing Dictionary value by key?
That is
public interface INullValueDictionary<T, U>
where U : class
{
U this[T key] { get; }
}
public class NullValueDictionary<T, U> : Dictionary<T, U>, INullValueDictionary<T, U>
where U : class
{
U INullValueDictionary<T, U>.this[T key]
{
get
{
U val;
dict.TryGet(key, out val);
return val;
}
}
}
and use it instead of the original dictionary everywhere:
//create some dictionary
NullValueDictionary<int, string> dict = new NullValueDictionary<int, string>
{
{1,"one"}
};
//have a reference to the interface
INullValueDictionary<int, string> idict = dict;
string val = idict[2]; // null
val = idict[1]; // "one"
I don't like to deal with null so my implementation will look like this:
interface Maybe<T> {
bool HasValue {get;}
T Value {get;}
}
class Nothing<T> : Maybe<T> {
public bool HasValue { get { return false; } }
public T Value { get { throw new Exception(); } }
public static const Nothing<T> Instance = new Nothing<T>();
}
class Just<T> : Maybe<T> {
private T _value;
public bool HasValue { get { return true; } }
public T Value { get { return _value; } }
public Just(T val) {
_value = val;
}
}
Maybe is a object that can contain value or not. Note that Nothing class contains static field Instance. We can use this value instead of creating new value each time we need to return Nothing from function.
Now, we need to create our own dictionary class:
class MyDictionary<TKey, TValue>
{
private Dictionary<TKey, TValue> _dict;
...
public Maybe<TValue> this[TKey key] {
TValue val;
if (_dict.TryGetValue(key, out val)) {
return new Just<TValue>(val);
return Nothing<TValue>.Instance;
}
}
Advantage of this approach is not clear, because C# doesn't have pattern matching. But it can be emulated with dynamic:
void ProcessResult(Just<string> val) {
Console.WriteLine(val);
}
void ProcessResult(Nothing<string> n) {
Console.WriteLine("Key not found");
}
var dict = new MyDictionary<string, string>();
...
dynamic x = dict["key"];
ProcessResult(x);
I think that this is very clear way to express the fact that dictionary can't always return meaningful result. Also it is obvious for reader that function overload ProcessResult(Just<T>) will be called only for values that present in dictionary and other overload will be called in case when key is not found.
Pros:
Type serves as a specification.
Dictionary can contain both value and reference types.
Cons:
More keystrokes.
Little more complexity to deal with.
I decided to do it like this:
class MyDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
public new TValue this[TKey key]
{
get
{
TValue value;
return TryGetValue(key, out value) ? value : default(TValue);
}
set { base[key] = value; }
}
}
It lets me use it like any other dictionary, through square brackets. Since I'm not going to use this with value types as TValue, I think it's good enough a solution.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Bidirectional 1 to 1 Dictionary in C#
Im curious if a datastructure exists in the standard .net libraries that can represent a 1-1 relationship, such as the following
1-a
4-b
6-c
5-d
Where I can say:
thisstructure[1] // returns "a"
thisstructure.GetKey["d"] // return 5
I understand all keys would have to be unique, does anything similar exist?
Thanks!
Yes- it's called KeyedCollection. It is intended to be subclassed and provides indexed access as well as access by a property derived from the added item. I usually make a generic subclass:
public class GenericKeyedCollection<TKey, TValue> : KeyedCollection<TKey, TValue> {
private readonly Func<TValue, TKey> _keyGenerator;
public GenericKeyedCollection(Func<TValue, TKey> keyGenerator) {
_keyGenerator = keyGenerator;
}
protected override int GetKeyForItem(TValue item)
{
return _keyGenerator(item);
}
}
To use it:
var myCollection = new GenericKeyedCollection<String, Car>(c=>c.Model);
myCollection.Add(new Car("Ford", "Mustang"));
var byIndex = myCollection[0];
var byModel = myCollection["Mustang"];
The only caveat is that the derived property (the "key") mustn't change after the item has been added.
If your key is not a property of the value, then you can use a Tuple<T1, T2> to combine the key and value:
var myCollection = new GenericKeyedCollection<String, Tuple<String, Car>>(t=>t.Item1);
myCollection.Add(new Tuple<String, Car>("Foo", Car("Ford", "Mustang")));
var byIndexCar = myCollection[0].Item2;
var byItem1Car = myCollection["Foo"].Item2;
Could this method fit your needs?
public static class Extensions
{
public static TKey GetKey<TKey, TValue>(this Dictionary<TKey, TValue> dict, TValue value)
{
int index = dict.Values.ToList().IndexOf(value);
if (index == -1)
{
return default(TKey); //or maybe throw an exception
}
return dict.Keys.ToList()[index];
}
}
You could then use it like so:
Dictionary<int, char> dict = new Dictionary<int, char>();
dict.Add(1, 'a');
dict.Add(4, 'b');
dict.Add(6, 'c');
dict.Add(5, 'd');
Console.WriteLine(dict.GetKey('d')); //5
The Dictionary....or IDictionary interface is the closest I can think of to what you want. It doesn't have quite so simple a searching operation, in that searching on a value can return the key, but I do know you can search on a key to get a value. providing functionality for the reverse in a custom extended class wouldn't be difficult at all.
MSDN IDictionary page
I'm looking for a collection.
I need to be able to add elements as if using a 2D integer key, for example .Add(3, 4, element). If I add outside the range of the collection I need the collection to expand, this include negatively, although it can have a limit, for example the range of an Int16 would be good. Every element in the collection can have the same type as each other but I need to specify what that is, for example Set<type> s;
I also need to avoid slow operations such as searching when looking up an element, performance is less important when adding to the collection.
Does anyone have any ideas about what approach to use or best could provide the class in there answer.
If you want a compound key, you can use the Tuple<T1,T2> class in a : Dictionary<Tuple<T1,T2>, TItem>.
var coll = new Dictionary<Tuple<int,int>, AnyClass>();
coll.Add(new Tuple<int,int>(2, 3), new AnyClass("foo"));
coll.Add(new Tuple<int,int>(4, 2), new AnyClass("bar"));
var foo = coll[new Tuple<int,int>(2,3)];
var bar = coll[new Tuple<int,int>(4,2)];
If the syntax is too weird, you may wrap the class like this :
public class Dictionary2d<TKey1, TKey2, TItem> : Dictionary<Tuple<TKey1, TKey2>,TItem>
{
public void Add(TKey1 k1, TKey2, TItem item) {
this.Add(Tuple.Create(k1,k2), item);
}
public TItem this[TKey1 k1, TKey2 k2] {
get { return this[Tuple.Create(k1,k2)]; }
}
}
public class Program
{
static void Main() {
var coll = new Dictionary2d<int,int, AnyClass>();
coll.Add(2, 3, new AnyClass("foo"));
coll.Add(4, 2, new AnyClass("bar"));
var foo = coll[2,3];
var bar = coll[4,2];
}
}
The benefits of using Tuple class, is that the equality and hashcode comparison is natively handled, so even if it's a class, two differents instances of tuple with same values will be considered equals.
It sounds like you want a Dictionary<int, T>.
You can implement this Set<T> by storing its data in a private variable of type Dictionary<int, Dictionary<int, T>>.
You can then store using
public void Add(int key1, int key2, T value)
{
_storage[key1][key2] = value;
}