casting List<MyOject> to List<IMyInterface>

  • Thread starter Thread starter wdudek
  • Start date Start date
W

wdudek

I have a list (actually an IList) of objects that implement an interface and
need to cast the list to a list of the intercace. Is there an easy and
"clean" way to do this, I tried using a direct cast (List<IMyInterface>)
myObjectList, but it threw an exception at run time. In the past I have done
this with a foreach loop, but it seems like there would be some extension
method to do it for me. Also I'm on the 3.5 framework.

Thanks

Bill
 
You can't literally do what you're asking.  But, depending on your needs,  
the Enumerable.Cast<T>() extension method might be useful to you:

     IEnumerable<IMyInterface> rgmi = myObjectList.Cast<IMyInterface>();

Furthermore, if by "cast" one means "creating a new list" (which is
the only typesafe way to do it, when dealing with List<T>), then the
above can further be extended to:

List<IMyInterface> list = myObjectList.Cast<IMyInterface>().ToList
();

As to why a plain cast doesn't work - it's because it's not typesafe
in the presence of any non-covariant methods such as List.Add(). For
the theory underlying this, see here:

http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)

(by the way, is there some FAQ for this sort of stuff that can be
linked to from the signature?)
 
Peter, Pavel,

Thanks, I modified my code to work with the IEnumerable produced by
Peter's posting and it's much cleaner than the looping I had previously done
to achieve this.

Bill
 
To be precise, followed expression is not safe, and will raise
ArgumentNullException exception under certain circumustances:
  List<IMyInterface> list = myObjectList.Cast<IMyInterface>().ToList

when source is null:

public static IEnumerable<TResult> Cast<TResult>(this IEnumerable
source)
{
IEnumerable<TResult> enumerable = source as
IEnumerable<TResult>;
if (enumerable != null)
{
return enumerable;
}
if (source == null)
{
throw Error.ArgumentNull("source");
}
return CastIterator<TResult>(source);
}

I prefer using my SafeEnumerator<T> class:

public sealed class SafeEnumerator<T> : IEnumerable<T>,
IEnumerator<T>
{
public delegate IEnumerable<T> EnumerableAction();

private EnumerableAction _action;
private IEnumerable<T> _enumerable;
private IEnumerator<T> _enumerator;
private T _value;

public SafeEnumerator(EnumerableAction action)
{
_action = action;
}

IEnumerator<T> IEnumerable<T>.GetEnumerator() { return this; }
IEnumerator IEnumerable.GetEnumerator() { return this; }

void IDisposable.Dispose() { }

T IEnumerator<T>.Current { get { return _value; } }
object IEnumerator.Current { get { return _value; } }
bool IEnumerator.MoveNext()
{
if (_enumerable == null)
{
try
{
_enumerable = _action();
}
catch (Exception)
{
return false;
}
if (_enumerable == null) return false;
_enumerator = _enumerable.GetEnumerator();
}
if (_enumerator == null) return false;
if (_enumerator.MoveNext())
{
_value = _enumerator.Current;
return true;
}
_enumerator.Reset();
return false;
}
void IEnumerator.Reset()
{
_enumerable = null;
_value = default(T);
}
}
 
You can't literally do what you're asking.  But, depending on your needs,  
the Enumerable.Cast<T>() extension method might be useful to you:

     IEnumerable<IMyInterface> rgmi = myObjectList.Cast<IMyInterface>();

Pete

To be precise, followed expression is not safe, and will raise
ArgumentNullException exception under certain circumustances:
List<IMyInterface> list = myObjectList.Cast<IMyInterface>().ToList

when source is null:

public static IEnumerable<TResult> Cast<TResult>(this IEnumerable
source)
{
IEnumerable<TResult> enumerable = source as
IEnumerable<TResult>;
if (enumerable != null)
{
return enumerable;
}
if (source == null)
{
throw Error.ArgumentNull("source");
}
return CastIterator<TResult>(source);
}

I prefer using my SafeEnumerator<T> class:

public sealed class SafeEnumerator<T> : IEnumerable<T>,
IEnumerator<T>
{
public delegate IEnumerable<T> EnumerableAction();

private EnumerableAction _action;
private IEnumerable<T> _enumerable;
private IEnumerator<T> _enumerator;
private T _value;

public SafeEnumerator(EnumerableAction action)
{
_action = action;
}

IEnumerator<T> IEnumerable<T>.GetEnumerator() { return this; }
IEnumerator IEnumerable.GetEnumerator() { return this; }

void IDisposable.Dispose() { }

T IEnumerator<T>.Current { get { return _value; } }
object IEnumerator.Current { get { return _value; } }
bool IEnumerator.MoveNext()
{
if (_enumerable == null)
{
try
{
_enumerable = _action();
}
catch (Exception)
{
return false;
}
if (_enumerable == null) return false;
_enumerator = _enumerable.GetEnumerator();
}
if (_enumerator == null) return false;
if (_enumerator.MoveNext())
{
_value = _enumerator.Current;
return true;
}
_enumerator.Reset();
return false;
}
void IEnumerator.Reset()
{
_enumerable = null;
_value = default(T);
}
}
 
To be precise, followed expression is not safe, and will raise
ArgumentNullException exception under certain circumustances:


when source is null:

public static IEnumerable<TResult> Cast<TResult>(this IEnumerable
source)
{
        IEnumerable<TResult> enumerable = source as
IEnumerable<TResult>;
        if (enumerable != null)
        {
                return enumerable;
        }
        if (source == null)
        {
                throw Error.ArgumentNull("source");
        }
        return CastIterator<TResult>(source);

}

I prefer using my SafeEnumerator<T> class:
[...snip...]

I think you overcomplicate things for such a simple case. Accounting
for null - when needed - is easily done using the coalesce operator:

(myObjectList ?? Enumerable.Empty<MyObject>()).Cast<IMyInterface>
().ToList()
 
Back
Top