How to solve call ambiguity between Generic.IList<T>.this[] and IList.this[]?
Question
I've got a collection that implements an interface that extends both IList<T> and List.
public Interface IMySpecialCollection : IList<MyObject>, IList { ... }
That means I have two versions of the indexer.
I wish the generic implementation to be used, so I implement that one normally:
public MyObject this[int index] { .... }
I only need the IList version for serialization, so I implement it explicitly, to keep it hidden:
object IList.this[int index] { ... }
However, in my unit tests, the following
MyObject foo = target[0];
results in a compiler error
The call is ambiguous between the following methods or properties
I'm a bit surprised at this; I believe I've done it before and it works fine. What am I missing here? How can I get IList<T> and IList to coexist within the same interface?
Edit IList<T> does not implement IList, and I must implement IList for serialization. I'm not interested in workarounds, I want to know what I'm missing.
Edit again: I've had to drop IList from the interface and move it on my class. I don't want to do this, as classes that implement the interface are eventually going to be serialized to Xaml, which requires collections to implement IDictionary or IList...
Solution
You can't do this with
public interface IMySpecialCollection : IList<MyObject>, IList { ... }
But you can do what you want with a class, you will need to make the implementations for one of the interfaces explicit. In my example I made IList explicit.
public class MySpecialCollection : IList<MyObject>, IList { ... }
IList<object> myspecialcollection = new MySpecialCollection();
IList list = (IList)myspecialcollection;
Have you considered having IMySpecialCollection implement ISerializable for serialization? Supporting multiple collection types seems a bit wrong to me. You may also want to look at casting yout IList to IEnumerable for serialization since IList just wraps IEnumerable and ICollection.
OTHER TIPS
This is a dupe of my question here
To summarise, if you do this, it solves the problem:
public Interface IMySpecialCollection : IList<MyObject>, IList
{
new MyObject this[int index];
...
}
Unfortunately you can't declare two indexers with the same parameter list. The following paragraph is taken from here C# Programming Guide - Using Indexers "Remarks" section:
The signature of an indexer consists of the number and types of its formal parameters. It does not include the indexer type or the names of the formal parameters. If you declare more than one indexer in the same class, they must have different signatures.
You will have to declare a different set of parameters if you wish to use the second indexer.
Change your generic implementation to...
T IList<T>.this[int index] { get; set; }
This explicitly says which 'this' is which.
List<T> implies IList, so it's a bad idea to use both in the same class.