C# Covariance

Поділитися
Вставка
  • Опубліковано 11 чер 2020
  • Coding Tutorial: Is a bag of apples a kind of bag of fruit? It all comes down to covariance.
    Source code available at: github.com/JasperKent/Covaria...
  • Наука та технологія

КОМЕНТАРІ • 34

  • @CodingTutorialsAreGo
    @CodingTutorialsAreGo  3 роки тому

    Any questions? Just post a comment.
    Download the source code at github.com/JasperKent/Covariant-Assignment
    And subscribe to keep up to date: ua-cam.com/channels/qWQzlUDdllnLmtgfSgYTCA.html

  • @mohitkumar-jv2bx
    @mohitkumar-jv2bx 2 роки тому +14

    This video is so underrated. finally a great explanation of covariance that I could understand.

  • @Rhysling2
    @Rhysling2 8 місяців тому +2

    Best tutorial I have seen on covariance. This deserves much more attention.

  • @jheysonlima
    @jheysonlima 2 роки тому +5

    Man... Just found your channel and your explanations are so clear and concise, hope you get millions of subscribers... Keep up with the great job! Thank you sir!

  • @stinknay
    @stinknay 6 місяців тому +1

    i lucked out, this is the first video i watched and i kind of got it the first time, when watching a second time it made even more sense. thanks.

  • @th3R341W3n
    @th3R341W3n Рік тому +1

    Theeee best ever covariance explanation!

  • @ZacharyBugay
    @ZacharyBugay Рік тому +2

    Excellently explained. Great job.

  • @TheJessejunior
    @TheJessejunior 9 місяців тому +1

    incredible! never had understood these over years.

  • @paulofernandoee
    @paulofernandoee 2 роки тому +1

    I read the msdn docs, saw other vídeos and couldn't understand, with you i finally got It, thanks!
    But would you mind giving an example of a real world use of covariance?

  • @padmakrishnan3377
    @padmakrishnan3377 2 роки тому +1

    Wonderful video which explains the concepts so well! Thank you!
    I have a couple of comments:-
    1) I got very confused on how you could add a banana to the bag of apples. Took me a lot of time to figure out the base class gets called. If you can draw the reader’s attention to this, it will be very useful as this polymorphism/ inheritance sometimes trips me up.
    2) Is there a need to declare the Fruit class as Abstract?

    • @CodingTutorialsAreGo
      @CodingTutorialsAreGo  2 роки тому

      Thanks for your comments!
      1) Yeah, it's a bit tricky because C# does so much to prevent that sort of thing, so making it happen is a bit of a hack.
      2) Whether or not Fruit is abstract doesn't really affect what we're doing here, but in general OO terms it should be.

    • @alfonsdeda8912
      @alfonsdeda8912 3 місяці тому

      So if you didn't hide the get method with the new keyword the call to the get should have called the bagoffruit and worked correctly? Why this thing is even possible?

  • @peternguyen9382
    @peternguyen9382 3 роки тому +2

    Hello! when you say " there is an inheritance relationship between IEnumerable and List by adding the Out keyword, so when we add the Out keyword to the interface behind the scene the compiler will "understand" List implement the interface IEnumerable ? Or because the IEnumerable is just the read-only inteface and it is safe in this case so the compiler allow us to do so? Thanks so much.

    • @CodingTutorialsAreGo
      @CodingTutorialsAreGo  3 роки тому +3

      Hi Peter,
      When the interface is declared as 'IEnumerable', the 'out' keyword does two things.
      Firstly, it says that wherever T is used in the interface, it can only be in a context where objects of type T are coming out of the interface not going in. Essentially, that means that we can only use T as a return type, not as a parameter type, which would be passing data in (such as Add(T t)).
      The second thing is, it now allows statements such as 'IEnumerable collectionOfFruit = new List();'
      It can do that safely, because it knows (from the first point) that there is no method on IEnumerable which allows you to add or insert a Fruit. If there were and Add (Fruit), then you could add a Banana with 'collectionOfFruit.Add(new Banana());' which means you could add a Banana to a List of Apples, which is clearly wrong, and prevented by this mechanism.
      It's worth noting that without the 'out' (which hasn't always been in C#, and which we could miss off in our own code) we would be able to have List implement IEnumerable, but we wouldn't be able to do the assignment 'IEnumerable collectionOfFruit = new List();'
      Hope that helps.

  • @user-jx1dm4qz1p
    @user-jx1dm4qz1p 2 роки тому +1

    thank you for your help.

  • @peternguyen9382
    @peternguyen9382 3 роки тому +1

    This video got me more clear about covariant in c#, now i know the real reason why Microsoft adding that feature to c#.

    • @CodingTutorialsAreGo
      @CodingTutorialsAreGo  3 роки тому +1

      Glad you found it helpful.

    • @peternguyen9382
      @peternguyen9382 3 роки тому +1

      @@CodingTutorialsAreGo thanks so much for helping! I really appreciate and happy when you reply.

  • @FerdieSwinkels
    @FerdieSwinkels 3 роки тому +1

    Very clear tutorial, thanks for the explanation!

  • @DedicatedManagers
    @DedicatedManagers 3 роки тому +2

    At 6:33why can you add a banana to the bag of apples? Didn’t you overwrite the add method with the type of apples? Or does it not overwrite because of overloading? (I am a JavaScript programmer trying to learn C#)

    • @CodingTutorialsAreGo
      @CodingTutorialsAreGo  3 роки тому +2

      Thanks for the question.
      Essentially, the reason we can't add a Banana to a BagOfApples is one of definition. A BagOfApples is only allowed to contain Apples - it's not just a Bag that happens to contain only Apples at the moment.
      In JavaScript, although that's still a concept you might want, it's hard to enforce since JavaScript is not strongly typed. You could have 'function add(apple)', but even though the parameter is called 'apple', you could still pass in anything at all, not just various types of fruit. (You could do a runtime check that it's an apple, but there's no compile-time checking.)
      In C# it's easy to enforce, since if you have 'void Add(Apple apple)' then the compile enforces the rules for you. And if you use a generic like 'List', instantiated as 'List' happens automatically.
      Of course, even in C# you could cheat in your own BagOfApples class by giving it an overload 'void Add(Banana banana)' put the point is that you don't want to.
      Hope that makes sense.

    • @DedicatedManagers
      @DedicatedManagers 3 роки тому +1

      Thanks for the reply.... unfortunately I don’t think you understood my question. If you click on the number in my comment, that’s a timestamp to a point in the video where you are able to add a banana to the bag of apples.

    • @CodingTutorialsAreGo
      @CodingTutorialsAreGo  3 роки тому +1

      @@DedicatedManagers Ah! I see. Sorry.
      There I'm deliberately writing bad code to highlight the problem.
      The Add(Apple) does not override the Add(Fruit) from the base class because it is a different overload. In some languages (e.g. C++) having a different overload in the derived class would hide the base class method and it would be unavailable (by default) in the derived class. But that's not the case in C#, and so adding a banana calls the base class method for Fruit, while adding an apple calls the derived class method for Apple.

    • @DedicatedManagers
      @DedicatedManagers 3 роки тому +2

      @@CodingTutorialsAreGo Got it. Thanks!

    • @CodingTutorialsAreGo
      @CodingTutorialsAreGo  3 роки тому +1

      @@DedicatedManagers My pleasure.

  • @piotrjan2927
    @piotrjan2927 Рік тому

    7:00 I am a bit confused. Shouldn't it fail right away when we add a banana to BagOfApples? Add method expects an instance of Apple. And Banana class is not derived from Apple. So, even though the underlying structure - List can store any kind of fruit, it appears that the Add method's parameter type should be enough to act as the gatekeeper here.

    • @CodingTutorialsAreGo
      @CodingTutorialsAreGo  Рік тому +1

      In C# a 'new' method in a derived class does not hie the corresponding method in the base class. So Add(Fruit) and Add(Apple) exist side-by -side as overloads, and adding a Banana choose the Fruit overload.

    • @piotrjan2927
      @piotrjan2927 Рік тому +2

      @@CodingTutorialsAreGo Thanks!

  • @iAndrewMontanai
    @iAndrewMontanai 2 роки тому +1

    That code below is also covariance? Everyone mentions only generic interfaces, delegates, array examples.
    Employee emp = new Manager();
    Or
    static void Work(Employee e)
    {
    switch(e)
    {
    case Manager m: m.DoManagerWork(); break;
    case Developer d: ..... break;
    case Employee emp: ..... break;
    }
    }

    • @CodingTutorialsAreGo
      @CodingTutorialsAreGo  2 роки тому +2

      The concept of covariance only really applies when you have collections of objects where the element in the collection is a base class. The 'co' means that the inheritance patterns of the collection and the element go in the same direction (just as with contravariance they go in opposite directions).
      Your first example is simply polymorphism - a base class reference refers to a derived class object.
      The switch example is actually a case of dynamic downcasting (safely converting a base class reference type to a derived class reference type). In more traditional code it is the equivalent of:
      if (e is Manager)
      ((Manager)e).DoManagerWork();
      Doing it a switch as you've shown is much neater, using the pattern matching features introduced in C#8, but it's conceptually the same.

  • @sergeyt4118
    @sergeyt4118 3 роки тому +1

    I still could not get it from the business reasoning standpoint: why building such perversive multi-layered abstractions? what's the point besides that one programmer could do something wrong (there are thousands ways we could f..kup here and there - but thats why tests were invented) ... and to prevent it other programmers invented other strange things ... that later could lead for yet other programmers (who struggle with these perversive abstracts) to introduce new bugs due to complexity constructs now being actively accepted into mainstream (because every other dev wants to show he is cool too, or just smarter and thus irreplaceable, or needs a payrise)
    ... what's wrong with just sticking to the KISS principle? - the code would be 10-15...50% longer (although more humanly readable)? - ok, let it be; to me this seems to justify avoidance of risks of complexity and dangerious bugs it brings manyfold. I am 40+ (so have some life understanding and managerial experience) and I come from the business side of the world. Though I'm still a noob in c# (but keep trying) learning it for some time - but can't throw away a strong impression that business overpays the IT world substantially not just because of hype, but also for some internal competition and smartass tactics programmers apply within the community which reflects on the code and IT products too; and imho this needs to be stopped untill its too late :)

    • @CodingTutorialsAreGo
      @CodingTutorialsAreGo  3 роки тому +3

      In terms of the business benefit it's pretty straightforward:
      abstract class Person {}
      class Employee : Person {}
      class Customer : Person {}
      void ProcessPersons (IEnumerable people) {...}
      List employees = new List {...}
      ProcessPersons(employees);
      The last line only works because of covariance.

  • @auronedgevicks7739
    @auronedgevicks7739 4 місяці тому

    why can't someone simply explain covariance without all these convoluted concepts.