For once I got to 90% of the video feeling "I got this" and then fall short as I've never used copy constructors before. Not knowingly atleast. You learn something new every time you watch a video from Zoran. Thank you for sharing as always.
After re-watching some of your earlier videos and then coming back to the newer ones, I'm surprised at how much I like having that small overlay of you talking in the corner of the videos. The message is still conveyed of course but the added facial expressions and hand gestures is really the tops. Either way, you're an awesome teacher. Thanks for all the amazing content over the years Zoran!! 🙏
What a brilliant round up! I suspected that copy contructors might be able to access private fields/methods of the other object but not got around to confirming this. Thanks Zoran.
We need a course about these topics! you are great! always I got a new things form you! you are my mentor ... please think of making more courses on pluralsight, udemy or even dometrain!
Another intriguing thing for me about constructors was a moment when I realized that they could not be asynchronous. Even an async factory method eventually creates an object synchronnously. The concept of asynchronous constructor and object that is being under construction for some time that is growing and growing to finally get "born" sounds cool, but I couldn't find a good use case for that.
@@serviceengine That is a topic for another video, which I already have under construction, which covers what should and should not be the part of a constructor.
@@serviceengine No, don't stop. I had no plans to mention async methods, but now that you have put them into the context of constructors I have something interesting to think about.
@zoran-horvat asynchronous constructors concept kinda overlapping with my previous comment about the amount of logic inside constructors now. Imagine some async method executed in the constructor in the sync way like GetAwaiter()... Now, if the construction of an object is taking a minute, for example, it will be so, so destructive.
I'm wondering if there is some kind of "runtime limbo" when object construction is so long. Exactly between moments when the creation starts and when memory is allocated at the end of the constructor execution.
Love your videos, Zoran! Do you have any experience working with F# I've seen you reference it a few times in your other videos. Could you recommend some good resources for learning best practices?
Really cool video! I would like to hear more about the accepted amount of logic in constructors themselves. I mean, we all know that except validation or simple assignment logic, it is better to avoid more complex logic in constructors . Is there some rule of thumb for that? I faced many times that the constructor executed a setting method, and that method was quite complex. It was setting many properties from different fields and other helper methods, and those from other and so on. Where could an acceptable limit for a constructors logic to handle?
@@serviceengine That is a very good question. Actually, I do have a script for that video sitting in the queue for quite some time. The short answer is that I prefer static factory methods when there is a substantial chunk of work to do other than, say, just collecting some input items into a private collection, etc. The very fact that the caller must call a method already rings the bell that there might be a cost that the caller should not ignore. For example, creating many objects in a loop is assumed to be cheap. But calling a factory method many times in a loop could be a different story, and we should consult with that method's documentation before deciding.
I wonder if you consider the De~constructor as another type of constructor. Regardless, I'd love to hear your thoughts on when to use a deconstructor vs IDisposable, and if there's even still a good use-case for deconstructors these days.
C# doesn't have destructors. They are called Finalizers and their usage is a bit finicky and not recommended if you do not have idea what you are doing. Objects with a finalizer are handled differently by the GC than the ones without and it can have an impact on performance. Generally, if you can, use Dispose() instead.
The DisplayName = $"{firstName} {lastName}" code is functionally problematic: 1) it assumes the first name (=given name) is displayed prior to the last name (=surname) and 2) it assumes a space is used between first and last names. Neither are correct in, for example, Japanese; it should be last name followed by first name and usually there is no space. (And if space is used it is the not same space being used here.)
@@dono42 You are both right and wrong. The wrong part is in assuming those cases apply - it is the customer's requirements that define the domain of application, and, consequently, the cases that apply. The cases you mentioned are valid, but if none applies to the software you are developing, then you won't implement them!
I always wondered, why include a private setter in your properties, even though they are set only from a constructor? It's like using a field and not marking it as readonly... Is there something I am missing?
@@promant6458 We do that in mutable classes. I wasn't developing the class's behavior further in this demo, but that is where we would supposedly change the values of properties. On the other hand, there is something in your comment. My usual process is to leave properties readonly until it is proven they need a setter.
@@zoran-horvat The primary constructor (#9) explicitly does NOT mark them as readonly - they are mutable. In addition your sample code generates 2 copies of the each field's value, as the auto property will have it's own backing field generated, not linked to the primary field. If you use a public property, it should only have only a getter, and return the primary field.
@@robslaney3729 My code will not create two copies of the field unless I use the class parameter again, which I do not do and which, by the way, would cause a compile-time warning to say so. Therefore, the issue you are informing us of - does not exist.
I always learn something from your fabulous videos Zoran, even as a senior dev with decades of experience... Thank you
For once I got to 90% of the video feeling "I got this" and then fall short as I've never used copy constructors before. Not knowingly atleast. You learn something new every time you watch a video from Zoran. Thank you for sharing as always.
Zoran, you're my copilot, seriously! Thank you so much.
Well, seriously, it's a great idea. A gpt model trained with Zoran's knowledge! 😜
After re-watching some of your earlier videos and then coming back to the newer ones, I'm surprised at how much I like having that small overlay of you talking in the corner of the videos. The message is still conveyed of course but the added facial expressions and hand gestures is really the tops.
Either way, you're an awesome teacher. Thanks for all the amazing content over the years Zoran!! 🙏
I know, I know. But the job wants it differently - you cannot imagine the cost of having that on my end. I also miss that.
Wow, first video of yours that I understood in one pass, even the bullet points at the end. Either I'm learning or getting smarter.
Great job Zoran.
What a brilliant round up! I suspected that copy contructors might be able to access private fields/methods of the other object but not got around to confirming this. Thanks Zoran.
@@ChrisWalshZX That is the only way to get to them - through a member of that class. And what better member there is than a constructor itself.
What a great explanation of constructors! Thank you!
We need a course about these topics! you are great! always I got a new things form you! you are my mentor ... please think of making more courses on pluralsight, udemy or even dometrain!
As usual, great and instructive video. Sometimes I forget the power of C#, this is a good reminder :)
Another intriguing thing for me about constructors was a moment when I realized that they could not be asynchronous. Even an async factory method eventually creates an object synchronnously.
The concept of asynchronous constructor and object that is being under construction for some time that is growing and growing to finally get "born" sounds cool, but I couldn't find a good use case for that.
@@serviceengine That is a topic for another video, which I already have under construction, which covers what should and should not be the part of a constructor.
@@zoran-horvat Looking forward then. I will stop spoiling your future plans again😉
@@serviceengine No, don't stop. I had no plans to mention async methods, but now that you have put them into the context of constructors I have something interesting to think about.
@zoran-horvat asynchronous constructors concept kinda overlapping with my previous comment about the amount of logic inside constructors now. Imagine some async method executed in the constructor in the sync way like GetAwaiter()... Now, if the construction of an object is taking a minute, for example, it will be so, so destructive.
I'm wondering if there is some kind of "runtime limbo" when object construction is so long. Exactly between moments when the creation starts and when memory is allocated at the end of the constructor execution.
Love your videos, Zoran! Do you have any experience working with F# I've seen you reference it a few times in your other videos. Could you recommend some good resources for learning best practices?
You can follow Scott Wlaschin for F#. His site fsharpforfunandprofit.com is indispensable.
Really cool video! I would like to hear more about the accepted amount of logic in constructors themselves. I mean, we all know that except validation or simple assignment logic, it is better to avoid more complex logic in constructors . Is there some rule of thumb for that? I faced many times that the constructor executed a setting method, and that method was quite complex. It was setting many properties from different fields and other helper methods, and those from other and so on. Where could an acceptable limit for a constructors logic to handle?
@@serviceengine That is a very good question. Actually, I do have a script for that video sitting in the queue for quite some time.
The short answer is that I prefer static factory methods when there is a substantial chunk of work to do other than, say, just collecting some input items into a private collection, etc. The very fact that the caller must call a method already rings the bell that there might be a cost that the caller should not ignore. For example, creating many objects in a loop is assumed to be cheap. But calling a factory method many times in a loop could be a different story, and we should consult with that method's documentation before deciding.
I wonder if you consider the De~constructor as another type of constructor. Regardless, I'd love to hear your thoughts on when to use a deconstructor vs IDisposable, and if there's even still a good use-case for deconstructors these days.
@@nGAGE0nline I don't remember using deconstructors ever in my code.
C# doesn't have destructors. They are called Finalizers and their usage is a bit finicky and not recommended if you do not have idea what you are doing. Objects with a finalizer are handled differently by the GC than the ones without and it can have an impact on performance. Generally, if you can, use Dispose() instead.
I hope to watch part 2 (all the other possibilities) 👀
@@haraheiquedossantos4283 I hope to record them!
Pure gold.
I still learned something new even about a topic I thought I had a good handle on.
The DisplayName = $"{firstName} {lastName}" code is functionally problematic: 1) it assumes the first name (=given name) is displayed prior to the last name (=surname) and 2) it assumes a space is used between first and last names. Neither are correct in, for example, Japanese; it should be last name followed by first name and usually there is no space. (And if space is used it is the not same space being used here.)
@@dono42 You are both right and wrong. The wrong part is in assuming those cases apply - it is the customer's requirements that define the domain of application, and, consequently, the cases that apply.
The cases you mentioned are valid, but if none applies to the software you are developing, then you won't implement them!
You didn't mention about the most tricky constructor: static constructor
@@TheBabbl978 Possibly on a separate video. Static constructors fall into a niche that has its own rules.
Technically not a constructor, though. It's called a type initializer.
Cool, but now Buddha can't register into your app, because birthyear can't be negative, and he was born 500 bc....
@@DavidSmith-ef4eh True. It is important to recognize the limitations and improve the model on the way.
@@zoran-horvat sorry, you didn't say anything controversial in this one, so I had to make something up. :D
@@DavidSmith-ef4eh Of course.
Buddha has transcended the need for software.
@@zoran-horvat would you have made the birthYear into a domain object with Year and CalendarEra? (i'm not sure is the proper name)
First!
I always wondered, why include a private setter in your properties, even though they are set only from a constructor? It's like using a field and not marking it as readonly... Is there something I am missing?
The owning object can still change the value of the property in its methods besides the constructor
@@promant6458 We do that in mutable classes. I wasn't developing the class's behavior further in this demo, but that is where we would supposedly change the values of properties. On the other hand, there is something in your comment. My usual process is to leave properties readonly until it is proven they need a setter.
@@zoran-horvat The primary constructor (#9) explicitly does NOT mark them as readonly - they are mutable. In addition your sample code generates 2 copies of the each field's value, as the auto property will have it's own backing field generated, not linked to the primary field. If you use a public property, it should only have only a getter, and return the primary field.
@@robslaney3729 My code will not create two copies of the field unless I use the class parameter again, which I do not do and which, by the way, would cause a compile-time warning to say so. Therefore, the issue you are informing us of - does not exist.