Hello everyone, there is the following example:

public abstract class Shape { } public class Circle : Shape { } public interface IContainer<out T> { T Figure { get; } } public class Container<T> : IContainer<T> { private T figure; public Container(T figure) { this.figure = figure; } public T Figure { get { return figure; } } } class Program { static void Main() { Circle circle = new Circle(); IContainer<Shape> container = new Container<Circle>(circle); Console.WriteLine(container.Figure.ToString()); // Delay. Console.ReadKey(); } } 

I'm interested in this line

 IContainer<Shape> container = new Container<Circle>(circle); 

- an instance of circle (passed as a constructor argument) is not reduced to any type in this case - because type T (I know that the type of place to fill with type T is correct, but just "type T" will be shorter) for the class We closed the Container with the same type as this instance (and I mean, because they have the same types, there’s nothing to do with it.)

So, we first type Container to the IContainer type, and the figure field of the Circle type is reduced to the Shape type.

Why is the figure field inside a Container class cast to a Shape?

so my assumptions are:

1) the instance passed as an argument is nothing to do with it - as it was said above, the instance itself is not given to anyone.

2) Due to the fact that the Container type we led to the IContainer type - the type T from which we closed the Shape type

  • and another question arises from here: at the same time, we have two UpCast events simultaneously: Container - IContainer;

Circle-Shape; - which of them, so to speak, affects the constructor argument passed — our instance of circle (yes, I know that I wrote above that UpCast -a instance of circle does not occur - just in the previous example, the instance is cast to the Shape type)

 IContainer<Shape> container = new Container<Shape>(circle); 
  • but, since the field figure changes its type, a link to this field is stored in this instance, which we pass as a constructor argument.

My guess is that since we type T in Container (Circle) - the type of which and the constructor argument of the circle - are cast to the type T in IContainer (Shape), then this argument of the Circle constructor is also implicitly UpCast - following " changes to its type — and accordingly, there will be UpCast types within this instance, including the figure field — which will change its Circle type to Shape.

    2 answers 2

    See it.

    You have in the line IContainer<Shape> container = new Container<Circle>(circle); there is only one type conversion: the left side has the IContainer<Shape> , and the right side has the Container<Circle> .

    Why is such a cast possible? The out case that you have in interface IContainer<out T> . The meaning of this out itself is as follows: if Т1 is a subtype of T2 , then IContainer<T1> considered a subtype of IContainer<T2> .

    Thus, your Container<Circle> converted to IContainer<Circle> , and as a result out IContainer<Circle> converted to IContainer<Shape> .

    That is, at the same time, the actual type of the object as it was, and remains Container<Circle> . The fact that this object can be accessed by reference type IContainer<Shape> , does not cause the field type of the object itself to change.


    Why is it even IContainer<Circle> cast from IContainer<Circle> to IContainer<Shape> ? This is controlled by the compiler. The fact is that type T is in the interface of the position of the return value. This means that if you really have IContainer<Circle> in your hands, then it meets the requirements of IContainer<Shape> : its Figure property returns a Circle object, which means that it can be treated as a Shape object.

    (If T were in the position of the argument, not the return value, the compiler would not let you compile the interface with out .)

      Here is a description from microsoft. In fact, I would not have focused much on this syntactic sugar, because for life, he plays a small role. It is much more important to understand what is generic and how they work. The essence of the links. In the Richter is well described, in great detail, you can still look there.