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/Jas...
Пікірлер: 35
@CodingTutorialsAreGo4 жыл бұрын
Any questions? Just post a comment. Download the source code at github.com/JasperKent/Covariant-Assignment And subscribe to keep up to date: kzbin.info/door/qWQzlUDdllnLmtgfSgYTCA
@mohitkumar-jv2bx3 жыл бұрын
This video is so underrated. finally a great explanation of covariance that I could understand.
@Rhysling2 Жыл бұрын
Best tutorial I have seen on covariance. This deserves much more attention.
@jheysonlima2 жыл бұрын
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!
@th3R341W3n Жыл бұрын
Theeee best ever covariance explanation!
@stinknay Жыл бұрын
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.
@TheJessejunior Жыл бұрын
incredible! never had understood these over years.
@paulofernandoee2 жыл бұрын
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?
@peternguyen93823 жыл бұрын
This video got me more clear about covariant in c#, now i know the real reason why Microsoft adding that feature to c#.
@CodingTutorialsAreGo3 жыл бұрын
Glad you found it helpful.
@peternguyen93823 жыл бұрын
@@CodingTutorialsAreGo thanks so much for helping! I really appreciate and happy when you reply.
@ZachBugay2 жыл бұрын
Excellently explained. Great job.
@iAndrewMontanai2 жыл бұрын
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; } }
@CodingTutorialsAreGo2 жыл бұрын
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.
@peternguyen93823 жыл бұрын
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.
@CodingTutorialsAreGo3 жыл бұрын
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.
@vladmaiorov10723 ай бұрын
You have two Synchronous Yield Return in Collections playlist and no C# Contravariance
@DedicatedManagers3 жыл бұрын
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#)
@CodingTutorialsAreGo3 жыл бұрын
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.
@DedicatedManagers3 жыл бұрын
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.
@CodingTutorialsAreGo3 жыл бұрын
@@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.
@DedicatedManagers3 жыл бұрын
@@CodingTutorialsAreGo Got it. Thanks!
@CodingTutorialsAreGo3 жыл бұрын
@@DedicatedManagers My pleasure.
@padmakrishnan33772 жыл бұрын
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?
@CodingTutorialsAreGo2 жыл бұрын
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.
@alfonsdeda89128 ай бұрын
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?
@piotrjan29272 жыл бұрын
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.
@CodingTutorialsAreGo2 жыл бұрын
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.
@piotrjan29272 жыл бұрын
@@CodingTutorialsAreGo Thanks!
@小林です-n3q2 жыл бұрын
thank you for your help.
@FerdieSwinkels3 жыл бұрын
Very clear tutorial, thanks for the explanation!
@CodingTutorialsAreGo3 жыл бұрын
Glad it was helpful.
@sergeyt41183 жыл бұрын
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 :)
@CodingTutorialsAreGo3 жыл бұрын
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.
@auronedgevicks773910 ай бұрын
why can't someone simply explain covariance without all these convoluted concepts.