I have this code (which I expect to work but it fails).. I really have no idea why. Please help
static void Main(string[] args)
{
var x = new MyKeyedCollection();
x.Add(new MyType() { Key = 400L, Value = 0.1 });
x.Add(new MyType() { Key = 200L, Value = 0.1 });
x.Add(new MyType() { Key = 100L, Value = 0.1 });
x.Add(new MyType() { Key = 300L, Value = 0.1 });
//foreach (var item in x)
for (int i = 0; i < x.Count; i++)
{
//Debug.WriteLine(item.PriceLevel);
Debug.WriteLine(x[i].Key);
}
}
}
public class MyType
{
public long Key;
public double Value;
}
public class MyKeyedCollection : KeyedCollection<long, MyType>
{
protected override long GetKeyForItem(MyType item)
{
return item.Key;
}
}
Exception:
System.Collections.Generic.KeyNotFoundException was unhandled
Message=The given key was not present in the dictionary.
Source=mscorlib StackTrace:
at System.ThrowHelper.ThrowKeyNotFoundException()
at System.Collections.Generic.Dictionary2.get_Item(TKey key)2.get_Item(TKey
at System.Collections.ObjectModel.KeyedCollection
key)
at KeyedCollectionTest.Program.Main(String[] args) in …\Program.cs:line 25
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart() InnerException:
How come it tries to get Key instead of index? Key is clearly long and not int. I am sure I used KeyedCollection before and it worked just fine for long key and int index.
I tried to compile in ver 2, 3.5, 4, 4.5 (using VS2012)…
Dont get it.
But
intis convertible tolong, so it’s a valid candidate member.The problem is that the
this[TKey key]indexer is originally declared inKeyedCollection, whereas thethis[int index]indexer is originally declared inCollection. The rules of overload resolution specify that the most derived class is searched first, and only the members which are first declared in that type are considered to start with. Only if that search fails does the compiler move up to the next level in the type hierarchy.So if you write:
it will work – because the compile-time type of
collectionis justCollection<T>, which only has the “int index” indexer.Here’s an example which shows the same behaviour without using generics, an indexer, or abstract classes:
See my article on overloading for some more of the interesting rules involved.