List<T> casting question

J

JDC

Hi all,

Say I have a couple of classes which implement an interface

public interface IDataItem
{
int ID { get; set; }
string Name { get; set; }
}

public class Foo : IDataItem
{
private int id;
public int ID
{
get { return id; }
set { id = value; }
}

private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}

public class Bar: IDataItem
{
private int id;
public int ID
{
get { return id; }
set { id = value; }
}

private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}

And I have a method that I want to use for Lists of both classes:

public void DoSomething(List<IDataItem> items)
{
foreach (IDataItem item in items)

}
 
J

JDC

Hi all,

Say I have a couple of classes which implement an interface

public interface IDataItem
{
int ID { get; set; }
string Name { get; set; }
}

public class Foo : IDataItem
{
private int id;
public int ID
{
get { return id; }
set { id = value; }
}

private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}

public class Bar: IDataItem
{
private int id;
public int ID
{
get { return id; }
set { id = value; }
}

private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}

And I have a method that I want to use for Lists of both classes:

public void DoSomething(List<IDataItem> items)
{
foreach (IDataItem item in items)

}

Oops, Google keyboard shortcuts posted that too soon!

The rest of the question is: is it possible to cast a list to pass to
the "DoDomething" method?

e.g.

List<Foo> fooList = Someclass.GetListOfFoos();
DoSomething(fooList as List<IDataItem>);

It seems like I should be able to do something like that last line
above, but I'm struggling to figure out how.

Thanks!
 
A

Adam Benson

Hi,

I think I know what you're driving at so I'll try to cast (no pun intended)
a little light.

List<Foo> is not the same type as List<IDataItem> in the same way that
char[10] and int[10] are not the same type. Don't get confused because Foo
implements IDataItem.

A method that takes List<IDataItem> as a parameter will not accept a
List<Foo> just because Foo implements IDataItem.

It is true that if you had void Method(IDataItem i) and you passed a Foo
object as a parameter that would be OK because the compiler would cast it to
the interface and pass that the method.

But if you had a List<Foo> and wanted to pass all those objects to a method
that required List<IDataItem> you would need to build yourself a
List<IDataItem> from your original List<Foo> and pass the newly-created
List<IDataItem> to your method.

Hope this clears things up a little,

Adam.
==========
 
J

JDC

Hi,

I think I know what you're driving at so I'll try to cast (no pun intended)
a little light.

List<Foo> is not the same type as List<IDataItem> in the same way that
char[10] and int[10] are not the same type. Don't get confused because Foo
implements IDataItem.

A method that takes List<IDataItem> as a parameter will not accept a
List<Foo> just because Foo implements IDataItem.

It is true that if you had void Method(IDataItem i) and you passed a Foo
object as a parameter that would be OK because the compiler would cast it to
the interface and pass that the method.

But if you had a List<Foo> and wanted to pass all those objects to a method
that required List<IDataItem> you would need to build yourself a
List<IDataItem> from your original List<Foo> and pass the newly-created
List<IDataItem> to your method.

Hope this clears things up a little,

Adam.
==========

Yep, thanks. It's the answer I was expecting, I think, and it makes
sense when I think clearly about generics.

I might end up implementing converter functions to pass to
List<T>.ConvertAll, but as I was hoping to refactor some code, I don't
want the refactored version to be more complicated :)

Cheers,
 
M

Mattias Sjögren

And I have a method that I want to use for Lists of both classes:
public void DoSomething(List<IDataItem> items)
{
foreach (IDataItem item in items)

}

Make the method generic too:

public void DoSomething<T>(List<T> items) where T : IDataItem


Mattias
 
N

Niels Ull

Hi,

I think I know what you're driving at so I'll try to cast (no pun
intended) a little light.

List<Foo> is not the same type as List<IDataItem> in the same way
that char[10] and int[10] are not the same type. Don't get confused
because Foo implements IDataItem.

A method that takes List<IDataItem> as a parameter will not accept a
List<Foo> just because Foo implements IDataItem.

It is true that if you had void Method(IDataItem i) and you passed a
Foo object as a parameter that would be OK because the compiler would
cast it to the interface and pass that the method.

But if you had a List<Foo> and wanted to pass all those objects to a
method that required List<IDataItem> you would need to build yourself
a List<IDataItem> from your original List<Foo> and pass the
newly-created List<IDataItem> to your method.

Hope this clears things up a little,

Adam.
==========
Yep, thanks. It's the answer I was expecting, I think, and it makes
sense when I think clearly about generics.

I might end up implementing converter functions to pass to
List<T>.ConvertAll, but as I was hoping to refactor some code, I don't
want the refactored version to be more complicated :)


As you know, you cannot cast a List<Foo> to List<IDataItem>, since this would
allow you to do myList.Add(new Bar()).

However, if all you need is to enumerate a list, you can implement a utility
class with

static IEnumerator<XBase> GetBaseEnumerator<X,XBase>(IEnumerable<X> xEnum)
where X : XBase
{
for (X x in xEnum) yield return X;
}

Then your DoSomething method could be declared as

DoSomething(IEnumerator<IDataItem> items)

and call it as
DoSomething(Util.GetBaseEnumerator<Foo, IDataItem>(myFooList));
or
DoSomething(Util.GetBaseEnumerator<Bar, IDataItem>(myBarList));


If you need more functionality than IEnumerable, you could implement

static ReadOnlyList<XBase> GetBaseReadOnlyList<X,XBase>(IList<X> baseList)
where X : XBase

- unfortunately the collections framework does not define ReadOnlyList, so
you'll have to write this yourself.


Alternatively, it might be an option to change DoSomething to be a generic
method,
DoSomething<X>(List<X> items) where X : IDataItem
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top