You can't do this, because it wouldn't be safe. Consider: List joes = GetJoes(); List humanJoes = joes; humanJoes.Clear(); humanJoes. Add(new Fred()); Joe joe = joes0 Clearly the last line (if not an earlier one) has to fail - as a Fred isn't a Joe The invariance of List.
You can't do this, because it wouldn't be safe. Consider: List joes = GetJoes(); List humanJoes = joes; humanJoes.Clear(); humanJoes. Add(new Fred()); Joe joe = joes0; Clearly the last line (if not an earlier one) has to fail - as a Fred isn't a Joe.
The invariance of List prevents this mistake at compile time instead of execution time.
Well humanJoes is a list of Human, so you shouldn't be attempting (or able) to extra a Joe from it. But each joe is a human, so it should be safe to cast all to subclass safely. – Sonic Soul Oct 27 '10 at 22:22 you certainly can do Human h = joesList0 as Human.. and that's what I was looking for / asking about.. accept on a whole list level – Sonic Soul Oct 27 '10 at 22:23 @Sonic: Why wouldn't you be add an extra Joe or Fred to it?
That sort of variance is always acceptable. Try it: List list = new List(); list. Add("this is a string)";.
Why would you expect that to fail? – Jon Skeet Oct 27 '10 at 22:31 Shouldn't the last line be Joe joe = joes0;? – Ian Henry Oct 27 '10 at 22:32 just pointing out that your example should not compile, but that should not prevent the ability to downcast a list.
If you can do Human h = joe as Human. Why can't you do List h = List as List – Sonic Soul Oct 27 '10 at 22:41.
Instantiate a new human-list that takes the joes as input: List humanJoes = new List(joes).
No. The co/contravariance features of C# 4.0 only support interfaces and delegates. The do not support concrete types like List.
Stackoverflow. Com/questions/245607/… – Limo Wan Kenobi Oct 27 '10 at 22:13 so i'd need to loop through and create a new object for each joe as human and add to new list? That's the only option?
– Sonic Soul Oct 27 '10 at 22:13 1 It's not possible with IList, because that's invariant. – Jon Skeet Oct 27 '10 at 22:14 @Jon doh. Didn't think that one through – JaredPar Oct 27 '10 at 22:28.
No. As Jared said, the co/contravariance features of C# 4.0 only support interfaces and delegates. However it doesn't work with IList either, and the reason is that IList contains methods to add and change items in the list -- as Jon Skeet's new answer says.
The only way to be able to cast a list of "joe" to "human" is if the interface is purely read-only by design, something like this: public interface IListReader : IEnumerable { T thisint index { get; } int Count { get; } } Even a Contains(T item) method would not be allowed, because when you cast IListReader to IListReader, there is no Contains(human item) method in IListReader. You could "force" a cast from IList to IListReader, IListReader or even IList using a GoInterface. But if the list is small enough to copy, a simpler solution is to just copy it into a new List, as Paw pointed out.
If I allow your List joes to be generalized as ... List humans = joes; ... the two references humans and joes are, now onward, pointing to the exact same list. The code following the above assignment has no way of preventing an insertion/addition of an instance of another type of human , say a Plumber, into the list. Given that class Plumber: Human {} humans.
Add(new Plumber()); // Add() now accepts any Human not just a Joe the list that humans refers to now contains both joes and plumbers. Note that the same list object is still referred to by the reference joes. Now if I use the reference joes to read from the list object I might pop out a plumber instead of a joe.
Plumber and Joe are not known to be implicitly interconvertable... so my getting of a plumber instead of a joe from the list breaks down type safety. A plumber is certainly not welcome through a reference to a list of joes. However in the recent versions of C# , its kind of possible to work around this limitation for a generic class/collection by implementing a generic interface whose type parameter has an out modifier on it.
Say we now have ABag : ICovariable. The out modifier restricts the T to ouput positions only (e.g. Method return types). You cannot enter any T into the bag.
You can only read them out of it. This allows us to generalize joes to an ICovariable without worrying about inserting a Plumber into it as the interface doesn't allow that. We can now write ... ICovariable humans = joes ; // now its good!
Humans. Add(new Plumber()); // error.
In C#, roughly we can say that covariance means we can substitute derived type in place of base type. Contravariance means we can substitute base class in place of derived class (you are thinking it's not possible, right? We'll see how it's possible).
In C#, covariance and contravariance are supported only for reference types. We will discuss few covariance and contravariance supports in C#. From C# 1.0, arrays where the element type is reference type are covariant.
For example, the following statement in C# is OK. In the above code, mammal can be stored in animals array as mammal is derived from Animal. But remember, this is only true for reference types.
Why this covariance only for reference types but not for value type? It's because for reference types, the array originally keeps only pointers to the original object and base pointer can refer to derived types. In case of value type, the original value is stored in array itself so the size may vary depending on the type.
So covariance is not supported for array of values. Covariance from method to delegates were included in C# 2.0. In the following code snippets (which is valid in C# 2.0 and later), you'll find that return type supports covariant.
The original delegate has return type of Animal. But the method we have assigned (here, CopyMammal) to a variable (here, cfunc) has return type Mammal. So we can see that covariance is supported in return types.
/// method which delegate copy can accepts. The following statement is valid and an example of return type covariance. Contravariance is supported in parameters.
Now the following code will compile as contravariance is supported here. This is contravariance since we are using Animal parameter of CopyAnimalState in place of Mammal defined in CopyState delegate. But the following code will not be supported as covariance is not supported in parameters.
The above is not valid in C#. But why is it not valid? Let's explain a bit.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.