473,396 Members | 2,020 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

generic interface conversion question

Hi all,

I'm having trouble with a project that I've distilled down to the following
code. Unfortunately it won't compile and gives the following

error (caused by the call to GetHorses() in HorseFarm's GetAnimals() method):
Cannot implicitly convert type 'MyCollection<Horse>' to
'MyCollection<IAnimal>'
I tried creating an implicit conversion operator in the Horse class but the
compiler informed me that it was illegal to do so when the conversion was to
or from an interface.
I can't quite see why the the conversion doesn't occur automatically as the
Horse class implements IAnimal so you'd think a collection of

horses would be a collection of animals (I can after all return a single
Horse whenever an IAnimal is expected).

That being said, my real implementation is much more complex and I really
need to leverage the equivalent of a GetHorses() method within a HorseFarm's
GetAnimals() method.

Is there some type of design pattern for generics that can solve this?

Thanks,

Dave
--------- CODE START ---------------

public class MyCollection<T>
{
}

public interface IAnimal
{
}

public interface IFarm
{
MyCollection<IAnimalGetAnimals();
}

public class Horse : IAnimal
{
}

public class HorseFarm : IFarm
{
MyCollection<Horsehorses = new MyCollection<Horse>();

public MyCollection<HorseGetHorses()
{
return horses;
}

public MyCollection<IAnimalGetAnimals()
{
return GetHorses();
}
}

--------- CODE END ---------------

Nov 14 '07 #1
13 1784
Dave Weeden wrote:
Hi all,

I'm having trouble with a project that I've distilled down to the following
code. Unfortunately it won't compile and gives the following

error (caused by the call to GetHorses() in HorseFarm's GetAnimals() method):
Cannot implicitly convert type 'MyCollection<Horse>' to
'MyCollection<IAnimal>'

<...>
Google c# covariance.
..Net (c#?) does not* support covariance and contravariance.

You should be able to define it as IAnimal[] GetAnimals() and call
ToArray() on MyCollection (presuming you're inheriting List<T>).

JB
*Except in some cases. Delegate return types, Array conversion...
Nov 14 '07 #2
I can't quite see why the the conversion doesn't occur automatically as
the
Horse class implements IAnimal so you'd think a collection of

horses would be a collection of animals (I can after all return a single
Horse whenever an IAnimal is expected).
No, because if it was a collection of animals you could add a pig...
Nov 14 '07 #3
Thank John, I am now digging through the following:

http://blogs.msdn.com/ericlippert/ar...e/default.aspx

"John B" wrote:
Dave Weeden wrote:
Hi all,

I'm having trouble with a project that I've distilled down to the following
code. Unfortunately it won't compile and gives the following

error (caused by the call to GetHorses() in HorseFarm's GetAnimals() method):
Cannot implicitly convert type 'MyCollection<Horse>' to
'MyCollection<IAnimal>'
<...>
Google c# covariance.
..Net (c#?) does not* support covariance and contravariance.

You should be able to define it as IAnimal[] GetAnimals() and call
ToArray() on MyCollection (presuming you're inheriting List<T>).

JB
*Except in some cases. Delegate return types, Array conversion...
Nov 14 '07 #4
Hi Ben,

I understand that a collection of animals might contain pigs and other
animals but a collection of horses is definitely comprised solely of horses;
it therefore seems strange that a horse collection can not be used where an
animal collection is expected.

I've adapted my sample code a little (see below) to more closely model what
I'm trying to achieve with my collection that's based on WPF's
ObservableCollection<(namely a way to reference the object which "contains"
the collection so I can navigate my way back up the logical object hierarchy
without tightly coupling myself to the presentation layer).

Also in the sample is how what I'm trying to does work with plain old arrays
but breaks as soon as generics are introduced.

Dave

using System.Collections.ObjectModel;

public class MyCollection<TContainer, TMember: ObservableCollection<TMember>
{
public MyCollection(TContainer container)
{
Container = container;
}

TContainer Container { get; set; } // C# 3.0 automatic property
}

public interface IAnimal
{
}

public interface IFarm
{
IAnimal[] GetAnimalAray();
MyCollection<IFarm, IAnimalGetAnimalCollection();
}

public class Horse : IAnimal
{
}

public class HorseFarm : IFarm
{
IAnimal[] horseArray;
MyCollection<IFarm, HorsehorseCollection;

public HorseFarm()
{
horseArray = new IAnimal[] { };
horseCollection = new MyCollection<IFarm, Horse>(this);
}

public IAnimal[] GetAnimalAray()
{
return horseArray;
}

public MyCollection<IFarm, IAnimalGetAnimalCollection()
{
return horseCollection; // causes compilation error
}
}
"Ben Voigt [C++ MVP]" wrote:
I can't quite see why the the conversion doesn't occur automatically as
the
Horse class implements IAnimal so you'd think a collection of

horses would be a collection of animals (I can after all return a single
Horse whenever an IAnimal is expected).

No, because if it was a collection of animals you could add a pig...
Nov 14 '07 #5
Dave Weeden <dw*****@newsgroup.nospamwrote:
I understand that a collection of animals might contain pigs and other
animals but a collection of horses is definitely comprised solely of horses;
it therefore seems strange that a horse collection can not be used where an
animal collection is expected.
You should really read Eric Lippert's series of posts on variance:

http://blogs.msdn.com/ericlippert/ar...+and+Contravar
iance/default.aspx

Also Rick Byers:

http://blogs.msdn.com/rmbyers/archiv...16/375079.aspx

Consider what you can do with a collection of animals: you can *add*
any animal to it. What would you expect to happen when you add a tiger
to your collection of horses? What about the other pieces of code which
still had a reference to it as a collection of horses?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 14 '07 #6
Thanks, that's definite food for thought and is very likely the root of why
my model isn't quite right.

IIRC, the array returned by GetAnimalArray() is a copy so the replacing one
of the horse elements in that copy with a tiger would not cause a problem.

John B's post from above had also pointed me down the road towards Eric's
posts.

I'll definitely be checking them out :)

Thanks!

"Jon Skeet [C# MVP]" wrote:
Dave Weeden <dw*****@newsgroup.nospamwrote:
I understand that a collection of animals might contain pigs and other
animals but a collection of horses is definitely comprised solely of horses;
it therefore seems strange that a horse collection can not be used where an
animal collection is expected.

You should really read Eric Lippert's series of posts on variance:

http://blogs.msdn.com/ericlippert/ar...+and+Contravar
iance/default.aspx

Also Rick Byers:

http://blogs.msdn.com/rmbyers/archiv...16/375079.aspx

Consider what you can do with a collection of animals: you can *add*
any animal to it. What would you expect to happen when you add a tiger
to your collection of horses? What about the other pieces of code which
still had a reference to it as a collection of horses?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 14 '07 #7
Jon Skeet [C# MVP] wrote:
<....>
Consider what you can do with a collection of animals: you can *add*
any animal to it. What would you expect to happen when you add a tiger
to your collection of horses?
string[] strings = new string[] { "a", "b", "c", "d", "e", "f", "g" };
object[] objs = (object[])strings;
objs[0] = new object(); //oops

Ideally, not what happens when you do the above :)

<...>

JB
Nov 15 '07 #8
John B <jb******@yahoo.comwrote:
Jon Skeet [C# MVP] wrote:
<....>
Consider what you can do with a collection of animals: you can *add*
any animal to it. What would you expect to happen when you add a tiger
to your collection of horses?

string[] strings = new string[] { "a", "b", "c", "d", "e", "f", "g" };
object[] objs = (object[])strings;
objs[0] = new object(); //oops

Ideally, not what happens when you do the above :)
Exactly. Generics is meant to give compile-time type safety. Array
variance punts the type safety to execution time :(

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 15 '07 #9

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
John B <jb******@yahoo.comwrote:
>Jon Skeet [C# MVP] wrote:
<....>
Consider what you can do with a collection of animals: you can *add*
any animal to it. What would you expect to happen when you add a tiger
to your collection of horses?

string[] strings = new string[] { "a", "b", "c", "d", "e", "f", "g" };
object[] objs = (object[])strings;
objs[0] = new object(); //oops

Ideally, not what happens when you do the above :)

Exactly. Generics is meant to give compile-time type safety. Array
variance punts the type safety to execution time :(
I think array variance ought to require the /unsafe compiler switch.
>
--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Nov 15 '07 #10
On Nov 15, 3:48 pm, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
Exactly. Generics is meant to give compile-time type safety. Array
variance punts the type safety to execution time :(

I think array variance ought to require the /unsafe compiler switch.
Hmm... it's a slightly different type of safety, I think - a separate
switch, perhaps. Or perhaps it should just have been disallowed in the
first place. Apparently it was included mostly to be compatible with
Java, bizarrely enough.

Jon
Nov 15 '07 #11

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:92**********************************@e1g2000h sh.googlegroups.com...
On Nov 15, 3:48 pm, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
Exactly. Generics is meant to give compile-time type safety. Array
variance punts the type safety to execution time :(

I think array variance ought to require the /unsafe compiler switch.

Hmm... it's a slightly different type of safety, I think - a separate
switch, perhaps. Or perhaps it should just have been disallowed in the
first place. Apparently it was included mostly to be compatible with
Java, bizarrely enough.

Jon
No, there's advantages of overloading the "/unsafe" switch such as running
afoul of all the code style guides out there that say "no /unsafe". Because
the people who can't get unsafe code right are not going to get array
variance right either.

Yes, I realize that array variance is permissible in a partial-trust
environment, because of the extra runtime type-checking inserted by the
compiler.

I guess we could use the "/theoreticallyincorrect" switch instead?
Nov 15 '07 #12
Thanks all of you guys for pointing me down the right road, I get it now.

It's nice to dive back into theory sometimes :)

"Dave Weeden" wrote:
Thanks, that's definite food for thought and is very likely the root of why
my model isn't quite right.

IIRC, the array returned by GetAnimalArray() is a copy so the replacing one
of the horse elements in that copy with a tiger would not cause a problem.

John B's post from above had also pointed me down the road towards Eric's
posts.

I'll definitely be checking them out :)

Thanks!

"Jon Skeet [C# MVP]" wrote:
Dave Weeden <dw*****@newsgroup.nospamwrote:
I understand that a collection of animals might contain pigs and other
animals but a collection of horses is definitely comprised solely of horses;
it therefore seems strange that a horse collection can not be used where an
animal collection is expected.
You should really read Eric Lippert's series of posts on variance:

http://blogs.msdn.com/ericlippert/ar...+and+Contravar
iance/default.aspx

Also Rick Byers:

http://blogs.msdn.com/rmbyers/archiv...16/375079.aspx

Consider what you can do with a collection of animals: you can *add*
any animal to it. What would you expect to happen when you add a tiger
to your collection of horses? What about the other pieces of code which
still had a reference to it as a collection of horses?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 15 '07 #13
Ben Voigt [C++ MVP] <rb*@nospam.nospamwrote:
Hmm... it's a slightly different type of safety, I think - a separate
switch, perhaps. Or perhaps it should just have been disallowed in the
first place. Apparently it was included mostly to be compatible with
Java, bizarrely enough.

No, there's advantages of overloading the "/unsafe" switch such as running
afoul of all the code style guides out there that say "no /unsafe". Because
the people who can't get unsafe code right are not going to get array
variance right either.
Ooh, I don't know about that. I personally steer well clear of unsafe
code, and don't want to think about pinning etc - but I'm comfortable
enough getting variance right.
Yes, I realize that array variance is permissible in a partial-trust
environment, because of the extra runtime type-checking inserted by the
compiler.
Do you mean the JIT compiler? It's not done by the C# compiler.
I guess we could use the "/theoreticallyincorrect" switch instead?
Well, I'd go for something like: /arrayvariance={warn,error,allow} - or
just make it a warning that can be controlled in the same way as other
warnings.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 15 '07 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Kapil | last post by:
For the following code interface class I{}; public ref struct R1 : I { R1(R1%){} R1(){} }; generic <class T> // if you replace it with template, it works.
5
by: Richard Brown | last post by:
Ok, I've been looking through the .NET SDK docs and stuff. I'm wondering if you can provide a control extender that does generic validation or functionality just by dropping it on the form. For...
8
by: JAL | last post by:
Here is my first attempt at a deterministic collection using Generics, apologies for C#. I will try to convert to C++/cli. using System; using System.Collections.Generic; using System.Text; ...
2
by: Harold Howe | last post by:
Howdy all, I am getting a compiler error regarding a consrained conversion. It complains that it can't make the type conversion, even though the generic type argument inherits from the target of...
1
by: Ning Hu | last post by:
Hello, I have a question on why I am getting an error of "Cannot implicitly convert type 'testGenerics.testCollection' to 'testGenerics.IMyCollection<System.IComparable>'. An explicit...
8
by: kasper.rung | last post by:
I have a problem formulating a test to see if an object is implementing a generic interface. I have the following: public interface IGeneric<T> { void Foo(); }
1
by: Anthony Paul | last post by:
Hello everyone! Let's say that I would like a generic type that supports Min/Max properties and can be double or integer or even datetime if need be, something flexible. So I go about...
0
by: ManicQin | last post by:
Hello everyone and especially Kai-Uwe Bux A month ago I post a question in the same name of this one but I didnt managed to explain my question right, so people didn't understand me. Now when I...
15
by: Lloyd Dupont | last post by:
Don't mistake generic type for what you would like them to be!! IFoo<Ahas nothing in common with IFoo<B>! They are completely different type create dynamically at runtime. What you ask is a...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.