PC Review


Reply
Thread Tools Rate Thread

casting List<MyOject> to List<IMyInterface>

 
 
wdudek
Guest
Posts: n/a
 
      16th Mar 2009
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
 
Reply With Quote
 
 
 
 
Pavel Minaev
Guest
Posts: n/a
 
      16th Mar 2009
On Mar 16, 9:37*am, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
> On Mon, 16 Mar 2009 08:24:11 -0700, wdudek <wdu...@newsgroup.nospam> wrote:
> > 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.

>
> 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?)
 
Reply With Quote
 
wdudek
Guest
Posts: n/a
 
      16th Mar 2009
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

"Pavel Minaev" wrote:

> On Mar 16, 9:37 am, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
> wrote:
> > On Mon, 16 Mar 2009 08:24:11 -0700, wdudek <wdu...@newsgroup.nospam> wrote:
> > > 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.

> >
> > 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?)
>

 
Reply With Quote
 
hack2root@gmail.com
Guest
Posts: n/a
 
      17th Mar 2009
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);
}
}




 
Reply With Quote
 
hack2root@gmail.com
Guest
Posts: n/a
 
      17th Mar 2009
On Mar 16, 9:37*pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
> On Mon, 16 Mar 2009 08:24:11 -0700, wdudek <wdu...@newsgroup.nospam> wrote:
> > 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.

>
> 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);
}
}




 
Reply With Quote
 
Pavel Minaev
Guest
Posts: n/a
 
      17th Mar 2009
On Mar 17, 7:18*am, hack2r...@gmail.com wrote:
> 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:

[...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()

 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
List casting question Leon Mayne Microsoft Dot NET 2 26th Mar 2008 10:28 AM
List<T> casting question JDC Microsoft Dot NET Framework 5 21st May 2007 07:58 AM
Custom List casting Goran Djuranovic Microsoft VB .NET 4 15th May 2006 02:49 AM
Casting List<> of derived class to List<> of base class? matty.hall@gmail.com Microsoft C# .NET 4 12th Sep 2005 04:46 AM
Array List Type Casting C# to VC++ =?Utf-8?B?Qm9iVGhlSGFja2Vy?= Microsoft VC .NET 0 20th May 2004 01:06 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 06:36 AM.