tags:

views:

155

answers:

4

Is there any way to do something like this?

public interface ISomething
{
}

public class SomethingThatImplementsISomething: ISomething
{
}

public class SomethingElse
{
 public ICollection<ISomething> PropertyName{ get; set; }
}

I've tried it out, and it keeps failing. Any ideas?

+1  A: 

Make sure you have using System.Collections.Generic rather than just using System.Collections at the top of your compilation unit.

Edited to add:

Actually, this probably has to do with the fact that version of C# prior to 4.0 do not allow for covariance or contravariance for generics. In older versions, a generic field must be defined to use an exact data type, to avoid invalid reference type assignments.

Edited again:

Now that I see the actual error message that you are getting, the problem is not in the definition of the field, but in its use. You need to put an explicit cast in the assignment.

Jeffrey L Whitledge
I've tried this a few times, but I guess the syntax is strange within a generic. How can I do an explicit cast within the generic declaration?
Stacey
A: 

And what error it throws? It has been a while since I've done some C#, but I think this should work...

Does it say something like you can't use an interface as generic parameter or what?

Jakub Lédl
Oh f**k, I screwed it again :-( Can some admin delete this? I've swapped comments and answers again.
Jakub Lédl
Cannot implicitly convert type 'System.Collections.Generic.List<Models.Awardable>' to 'System.Collections.Generic.ICollection<IAwardable>'. An explicit conversion exists
Stacey
@Jakub you can delete it yourself, should be somewhere next to edit. :D
CrazyJugglerDrummer
Ah, now we get to the root of the problem!
Anon.
+5  A: 

ICollection<Models.Awardable> can not be converted to ICollection<IAwardable>.

What would happen if someone tried to add an IAwardable to the collection that wasn't a Models.Awardable?

Just instantiate a collection of IAwardable and add instances of Models.Awardable to it.

Anon.
Oh dear, I feel so foolish. Such entry level C#, I was so caught up by the error I neglected to realize that the interface abstraction was precisely the reason I wanted it to work. Thank you so much!
Stacey
I've been there, @Stacey. Sometimes you miss the forest for the trees...
dboarman
Note that in C# 4, you will be able to convert IEnumerable<Awardable> to IEnumerable<IAwardable>, but NOT ICollection<Awardable> to ICollection<IAwardable>. The difference being: since you cannot add things to an IEnumerable, the objection about adding goes away.
Eric Lippert
+1  A: 

It sounds like what you're trying to do is this:

ICollection<SomethingThatImplementsISomething> collection = new List<SomethingThatImplementsISomething>();
somethingElse.PropertyName = collection;

If that's the case, then this is a generic variance issue. ICollection is not covariant in its element type. (Because it it were, you could now go somethingElse.PropertyName.Add(somethingDifferentThatsAlsoAnISomething); -- and you'd have added a SomethingDifferentThatsAlsoAnISomething to a list of SomethingThatImplementsISomething, which breaks type safety.)

You need to instantiate a collection of ISomethings:

ICollection<ISomething> collection = new List<ISomething>();
somethingElse.PropertyName = collection;

You can then add SomethingThatImplementsISomething objects to your heart's content:

somethingElse.PropertyName.Add(new SomethingThatImplementsISomething());
itowlson
Yes, that is correct. I forgot that the generic type is just that, a type, not an object. I was trying to instantiate the generic using a class that implemented the interface, rather than instantiate with the interface and assign objects of classes that implemented it. I understand where the error is, now.
Stacey