If we take a look at the following code, what happens
var uc1 = new UserControl();
var uc2 = new UserControl();
//We have to set the name, because one is not assigned automatically via code, only when added via Designer
uc1.Name = "notUnique";
uc2.Name = "notUnique";
//We add unique text values so that we can distinguish them uniquely for the purpose of this test
uc1.Text = "uc1";
uc2.Text = "uc2";
panel1.Controls.Add(uc1);
panel1.Controls.Add(uc2);
var control = panel1.Controls["notUnique"];
The result is that control
is uc1
.
But if we swap the addition of the controls, so that we add uc2
into the collection first
panel1.Controls.Add(uc2);
panel1.Controls.Add(uc1);
var control = panel1.Controls["notUnique"];
Then in this case control
= uc2
So then it is clear that the index returns the first item it finds which matches (or null if none match).
Interestingly, this means if you also remove the control by using the key that it will remove the first control it finds from the collection.
panel1.Controls.RemoveByKey("notUnique");
You made the assumption that a control's name must be unique. But this is in fact not the case, and in the documentation for Control the Name property is not stated as having to be unique.
Now one could argue that as in the documentation the term "key" is used that this is a bug, but that is something to discuss with Microsoft! I suspect they will state it works as designed. (And I see a lot of broken code if they change it!)
Also interestingly, if you look at the method ControlCollection.Find
public System.Windows.Forms.Control[] Find (string key, bool searchAllChildren);
then you see that this will return an array.