Generics and conversion

R

Ralf Propach

Hi,

I have classes A1 and A2 which implement the interface IA.
Now I need a method m that works on Lists of objects of either class.
So I wrote something like

void m(List<IA> myList)
{
// do something with myList
}

and wanted to call it like this

main()
{
List<A1> list = new List<A1>();
// fill list
m(list); // <===
// more code
}

Then the compiler complains about the call m(list); with the error
CS1503: cannot convert from 'System.Collections.Generic.List<A1>'
to 'System.Collections.Generic.List<IA>'.

I can use ArrayLists instead of the List<>'s and the problem goes away,
but I have not found a solution using generic collections.
Any suggestions?

TIA

Ralf
 
V

Vadym Stetsyak

Hello, Ralf!

RP> I have classes A1 and A2 which implement the interface IA.
RP> Now I need a method m that works on Lists of objects of either class.
RP> So I wrote something like

RP> void m(List<IA> myList)
RP> {
RP> // do something with myList
RP> }

RP> and wanted to call it like this

RP> main()
RP> {
RP> List<A1> list = new List<A1>();
RP> // fill list
RP> m(list); // <===
RP> // more code
RP> }

Use List<IA>list = new List<IA>();

following code will be still valid
list.Add(new A1());
list.Add(new A2());

m(list);

The reason why compiler generated an error is that you specified different types in List<> container in class declaration and in List<> variable declaration in method main(...)

--
Regards, Vadym Stetsyak
www: http://vadmyst.blogspot.com
 
N

Nicholas Paldino [.NET/C# MVP]

Ralf,

Instead of passing in List<IA> into your method, you should do this:

void m<T>(List<T> myList) where T : IA
{

}

This way, you can pass the type of T to the method (or in your case, you
can just pass the parameter and it will be inferred).

Hope this helps.
 
Y

Yury

You should use 'where' :

static void MethodName<TItem>(List<TItem> list)
where TItem: IA
{
foreach (TItem item in list)
{
item.DoSome();
}
}
 
N

Nick Hounsome

Just to ice the cake you could consider the more general:

void m<T>(IEnumerable<T> sequence) where T: IA
{
}

Unless you really need Count or indexing or can somehow figure out a usefukl
way to add stuff to the list without an input of type T.

Nicholas Paldino said:
Ralf,

Instead of passing in List<IA> into your method, you should do this:

void m<T>(List<T> myList) where T : IA
{

}

This way, you can pass the type of T to the method (or in your case,
you can just pass the parameter and it will be inferred).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Ralf Propach said:
Hi,

I have classes A1 and A2 which implement the interface IA.
Now I need a method m that works on Lists of objects of either class.
So I wrote something like

void m(List<IA> myList)
{
// do something with myList
}

and wanted to call it like this

main()
{
List<A1> list = new List<A1>();
// fill list
m(list); // <===
// more code
}

Then the compiler complains about the call m(list); with the error
CS1503: cannot convert from 'System.Collections.Generic.List<A1>'
to 'System.Collections.Generic.List<IA>'.

I can use ArrayLists instead of the List<>'s and the problem goes away,
but I have not found a solution using generic collections.
Any suggestions?

TIA

Ralf
 
N

Nicholas Paldino [.NET/C# MVP]

I would say that this is definitely questionable, since it decreases the
amount of functionality that the OP was looking for in his first post. The
only thing I might change would be co make List<T> IList<T> instead.

IEnumerable<T> only works if you are cycling through the list, and not
making changes of any sort to it.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Nick Hounsome said:
Just to ice the cake you could consider the more general:

void m<T>(IEnumerable<T> sequence) where T: IA
{
}

Unless you really need Count or indexing or can somehow figure out a
usefukl way to add stuff to the list without an input of type T.

Nicholas Paldino said:
Ralf,

Instead of passing in List<IA> into your method, you should do this:

void m<T>(List<T> myList) where T : IA
{

}

This way, you can pass the type of T to the method (or in your case,
you can just pass the parameter and it will be inferred).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Ralf Propach said:
Hi,

I have classes A1 and A2 which implement the interface IA.
Now I need a method m that works on Lists of objects of either class.
So I wrote something like

void m(List<IA> myList)
{
// do something with myList
}

and wanted to call it like this

main()
{
List<A1> list = new List<A1>();
// fill list
m(list); // <===
// more code
}

Then the compiler complains about the call m(list); with the error
CS1503: cannot convert from 'System.Collections.Generic.List<A1>'
to 'System.Collections.Generic.List<IA>'.

I can use ArrayLists instead of the List<>'s and the problem goes away,
but I have not found a solution using generic collections.
Any suggestions?

TIA

Ralf
 
N

Nick Hounsome

If you reread my post you will see that I said:

Also there was nothing in the original post that suggested that list
functionality rather than enumerable functionality was required.

Note:
1) It is impossible for m to Add to List<T> as T is not constrained to new()
and even if it was it is not likely that he needs to add default values to
the list.
2) I assume that m does not sort the list or compare T's in any way since it
is not constrained to IComparable
3) In fact T is not constrained to anything at all which means that very
little can be efficiently done on the list.

This makes it rather hard to imagine what the method might be that would
require list rather than enumerable functionality.

In my experience people are always requesting more of their parameters than
is actually required.

Nicholas Paldino said:
I would say that this is definitely questionable, since it decreases
the amount of functionality that the OP was looking for in his first post.
The only thing I might change would be co make List<T> IList<T> instead.

IEnumerable<T> only works if you are cycling through the list, and not
making changes of any sort to it.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Nick Hounsome said:
Just to ice the cake you could consider the more general:

void m<T>(IEnumerable<T> sequence) where T: IA
{
}

Unless you really need Count or indexing or can somehow figure out a
usefukl way to add stuff to the list without an input of type T.

Nicholas Paldino said:
Ralf,

Instead of passing in List<IA> into your method, you should do this:

void m<T>(List<T> myList) where T : IA
{

}

This way, you can pass the type of T to the method (or in your case,
you can just pass the parameter and it will be inferred).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Hi,

I have classes A1 and A2 which implement the interface IA.
Now I need a method m that works on Lists of objects of either class.
So I wrote something like

void m(List<IA> myList)
{
// do something with myList
}

and wanted to call it like this

main()
{
List<A1> list = new List<A1>();
// fill list
m(list); // <===
// more code
}

Then the compiler complains about the call m(list); with the error
CS1503: cannot convert from 'System.Collections.Generic.List<A1>'
to 'System.Collections.Generic.List<IA>'.

I can use ArrayLists instead of the List<>'s and the problem goes away,
but I have not found a solution using generic collections.
Any suggestions?

TIA

Ralf
 
R

Ralf Propach

Nicholas said:
Ralf,

Instead of passing in List<IA> into your method, you should do this:

void m<T>(List<T> myList) where T : IA
{

}

This way, you can pass the type of T to the method (or in your case, you
can just pass the parameter and it will be inferred).

Hope this helps.

Yes, thanks, this "trick" with the where clause was exactly what I was looking for.

Ralf
 
J

James Curran

Nick Hounsome said:
If you reread my post you will see that I said:
3) In fact T is not constrained to anything at all which means that very
little can be efficiently done on the list.

In the original message, T was constraint to (actually, was) the
interface IA, which could have any number of requirements that we do not
know about.
1) It is impossible for m to Add to List<T> as T is not constrained to new()
and even if it was it is not likely that he needs to add default values to
the list.

Nor is there any requirement that items added to the list by m() be
default constructed:

void m<T>(List<T> myList) where T : IA
{
IA a = CreateANewA1orA2();
myList.Add(a);
}

class A1 : IA {}
class A2 : IA {}

IA CreateANewA1orA2()
{
if (DateTime.Now.Millisecond < 500)
return new A1();
else
return new A2();
}


--
Truth,
James Curran
[erstwhile VC++ MVP]

Home: www.noveltheory.com Work: www.njtheater.com
Blog: www.honestillusion.com Day Job: www.partsearch.com
 

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