You can try use IReadOnlyList<T>
, which is implemented by List<T>
.
Note that I've added one instance of NullValueDictionary<string, string>
to List
, so that you won't get ArgumentOutOfRangeException
at elist[index]
line.
IReadOnlyList<NullValueDictionary<string, string>> elist = new List<NullValueDictionary<string, string>>
{
new NullValueDictionary<string, string>()
};
IReadOnlyList<INullValueDictionary<string, string>> ielist = elist;
int index = 0;
//...
elist[index]["somekey"] = "somevalue";
string value = elist[index]["somekey"];
Edit: I've searched for covariant interfaces and collections with indexes prior to .NET 4.5, but found none. Still I think there are a little bit easier solution, than to create separate interface - just to cast one collection to another.
List<INullValueDictionary<string, string>> ielist = elist.Cast<INullValueDictionary<string, string>>().ToList();
Or use covariance gained from arrays
INullValueDictionary<string, string>[] ielist = elist.ToArray()
LINQ has some optimization that work on whole type compatibility, so you won't iterate over sequence if those types are compatible.
Cast implementation taken from MONO Linq
public static IEnumerable<TResult> Cast<TResult> (this IEnumerable source)
{
var actual = source as IEnumerable<TResult>;
if (actual != null)
return actual;
return CreateCastIterator<TResult> (source);
}
Note that I have changed INullValueDictionary<T, U>
interface to contain set
in the property so that ielist[index]["somekey"] = "somevalue";
will work.
public interface INullValueDictionary<T, U> where U : class
{
U this[T key] { get; set; }
}
But again - if creating a new Interface and class is ok for you and you don't want to mess around with casts everywhere - I think it is a good solution, if you have considered at the constraints, it gives.
In search of covariance in mscorlib
This probably won't be interesting to you, but I've just wanted to find out what Types are covariant in mscorlib assembly. By running next script I received only 17 types are covariant, 9 of which are Func
s. I have omitted IsCovariant
implementation, because this answer is too long even without it
typeof(int).Assembly.GetTypes()
.Where(type => type.IsGenericType)
.Where(type=>type.GetGenericArguments().Any(IsCovariant))
.Select(type => type.Name)
.Dump();
//Converter`2
//IEnumerator`1
//IEnumerable`1
//IReadOnlyCollection`1
//IReadOnlyList`1
//IObservable`1
//Indexer_Get_Delegate`1
//GetEnumerator_Delegate`1