Reputation: 7174
I am implementing IListSource
that requires a method GetList()
with the following signature:
IList GetList()
I am using .NET framework 2 and I'm wanting to return an object that implements IList as follows:
public System.Collections.IList GetList()
{
return this._mydata; // Implements IList<MyDataRow>
}
But I get a compile error saying: Cannot implicitly convert type MyData to System.Collections.IList
.
If I create a new list of type List<MyDataRow>
, populate it and return this list object, then it works. So in other words, this works:
public System.Collections.IList GetList()
{
List<MyDataRow> list = new List<MyDataRow>();
foreach (MyDataRow row in this._mydata)
{
list.Add(row);
}
return list;
}
But it seems very inefficient to have to recreate the list just to get it from type IList<T>
to IList
. Why is it that I can return a List<MyDataRow>' from 'GetList()
, but not an IList<MyDataRow>
? Does anyone know of a way for me to return the IList<MyDataRow>
without repopulating a new list?
UPDATE:
The _mydata
member variable is declared:
private MyData _mydata;
And MyData
is declared:
public class MyData : IList<MyDataRow>
{
....
}
Upvotes: 19
Views: 17674
Reputation: 82136
Why is it that I can return a
List<MyDataRow>
fromGetList()
, but not anIList<MyDataRow>
This is because List<T>
implements IList
, IList<T>
cannot be cast to IList
they are 2 separate interfaces. So to answer your question:
Does anyone know of a way for me to return the
IList<MyDataRow>
without repopulating a new list?
If the concrete type implements IList
(which List<T>
does) then you can explicitly cast it e.g.
return (IList)this.mydata;
Update
Based on your update, you will have to update MyData
to implement IList
otherwise you have no choice but to return a new collection which does implement it.
Alternatively, if MyData
is indeed a generic list then I would suggest you have it inherit from List<T>
, that way you get a lot more flexibility & compatibility out of the box e.g.
class MyData : List<MyDataRow>
{
}
Upvotes: 15
Reputation: 10184
If it were possible to convert an IList<T>
into an IList
directly, you could return a list that could (for example) be "contaminated" with non T
objects via its Add(object)
method.
Upvotes: 2
Reputation: 34437
Either implement IList
on your data collection class or create an adapter, which wraps IList<T>
and implements IList
:
public sealed class NonGenericList<T> : IList
{
private readonly IList<T> _wrappedList;
public NonGenericList(IList<T> wrappedList)
{
if(wrappedList == null) throw new ArgumentNullException("wrappedList");
_wrappedList = wrappedList;
}
public int Add(object value)
{
_wrappedList.Add((T)value);
return _wrappedList.Count - 1;
}
public void Clear()
{
_wrappedList.Clear();
}
public bool Contains(object value)
{
return _wrappedList.Contains((T)value);
}
public int IndexOf(object value)
{
return _wrappedList.IndexOf((T)value);
}
public void Insert(int index, object value)
{
_wrappedList.Insert(index, (T)value);
}
public bool IsFixedSize
{
get { return false; }
}
public bool IsReadOnly
{
get { return _wrappedList.IsReadOnly; }
}
public void Remove(object value)
{
_wrappedList.Remove((T)value);
}
public void RemoveAt(int index)
{
_wrappedList.RemoveAt(index);
}
public object this[int index]
{
get { return _wrappedList[index]; }
set { _wrappedList[index] = (T)value; }
}
public void CopyTo(Array array, int index)
{
_wrappedList.CopyTo((T[])array, index);
}
public int Count
{
get { return _wrappedList.Count; }
}
public bool IsSynchronized
{
get { return false; }
}
public object SyncRoot
{
get { return this; }
}
public IEnumerator GetEnumerator()
{
return _wrappedList.GetEnumerator();
}
}
Usage:
public System.Collections.IList GetList()
{
return new NonGenericList<MyDataRow>(this._mydata);
}
Upvotes: 4
Reputation: 5706
IList<T>
does not extend IList
, because it's not reasonable to expect every implementation of the generic version to offer the same contract as the non-generic one. If it did extend IList
, someone could take the value returned from GetList
and reasonably expect to call, e.g. Add(DateTime.Now)
, or Add(Thread.CurrentThread)
. That's what IList
promises.
That's the reason copying your list to a List<T>
works - List<T>
implements both interfaces, and throws when its (explicitly implemented) IList
methods are called with inappropriate parameter types.
If you can get away with returning IEnumerable
, do that instead. If you can return IList<MyDataRow>
instead, then do that. If you really need a non-generic IList
return, then implement the interface and handle non-MyDataRow
values appropriately.
Upvotes: 4
Reputation: 2733
The MyData
class need to implement the IList
along with the generic version IList<T>
.
class MyData : IList<MyDataRow>, IList
{
}
Upvotes: 4