Why I won’t need constructors anymore in C# 11

Поділитися
Вставка
  • Опубліковано 5 вер 2024
  • Check out my new "Integration testing in ASP .NET Core" course and use code INTESTING1 for 20% off (first 300): dometrain.com/...
    Become a Patreon and get source code access: / nickchapsas
    Hello everybody I'm Nick and in this video I will introduce you to the brand new "required" keyword that is being added in C# 11. It is a great language feature that solves one of my biggest problems with object initialization, and it eliminated the need for constructors for that usecase.
    Link to the required keyword feature issue: github.com/dot...
    Don't forget to comment, like and subscribe :)
    Social Media:
    Follow me on GitHub: bit.ly/ChapsasG...
    Follow me on Twitter: bit.ly/ChapsasT...
    Connect on LinkedIn: bit.ly/ChapsasL...
    Keep coding merch: keepcoding.shop
    #csharp #dotnet

КОМЕНТАРІ • 401

  • @nickchapsas
    @nickchapsas  2 роки тому +25

    For those wondering, yes the required keyword IS coming in C# 11. It was demoed at Build and NDC Copenhagen and I confirmed it with Mads Torgersen himself

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

      would you be able to use it to write api's? API should be simple.

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

      This is great news! Will it play nicely with deserialization, I wonder?

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

      YES! FINALLY! 😄
      No more boilerplate constructors duplicating every name and type of every property. Sheesh! We needed this 😅

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

      @@DavidBondOnline that would likely be up the deserializer - it emits an attribute, which the compiler enforces at compile-time, but things like serializers, validators, mappers and DI containers will likely need to use reflection and respect this new attribute. So not a simple, ideal solution in that way - but it's too late for that, I guess. Established languages don't really make breaking changes, and the VM and run-times already support multiple languages - as with most popular software, complexity can only really go up from here. What makes this worth while, is the it lets you remove complexity from your code.

    • @user-zz6fk8bc8u
      @user-zz6fk8bc8u 2 роки тому

      Look like it's not coming in C# 11. At least it's not mentioned in the release notes and the tracking issue is still open.

  • @antonmartyniuk
    @antonmartyniuk 2 роки тому +102

    I was waiting a long time for this feature. I was really upset that it was removed from C# 10 release. As I said in the comments under one of the videos, required keyword is one of the most awaited thing for me in C# 11. I use nullable enabled a lot in my projects so required keyword will be the last thing I am missing to make my code safer and cleaner

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

      I agree, I've been using constructors this entire time to ensure they are properly not null when using nullable it has lead to a way messier codebase than I would have liked

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

      Was going to comment something very similar. Very nice that it's finally coming!

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

      "Attribute constructor" means you could write something like [Required(FullName="Nick")] - because as you saw it's implemented with an Attribute. I haven't tested it though, and I'm not quite sure how that would make sense... unless it acts as a default value? (Or the error message needs some love.)

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

      @@BadgersEscape I do that, makes my code look very enterprise/shitty

  • @travisabrahamson8864
    @travisabrahamson8864 2 роки тому +119

    This feature should have been added when the Explicit Nullablity was added, I would have spent less time having to argue why setting a non-nullable string property value to null using null-forgiveness or empty string is not a good idea on models that have many of these properties that it would create an unwieldly large ctor. The more I see of 11 the more I look forward to its arrival.

    • @nickchapsas
      @nickchapsas  2 роки тому +33

      Yeah I had to basically "lie" in my code and add all those "= default!" or "= null!" calls that are error prone. Finally I can remove them

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

      Can you please elaborate on this, as I am not sure I understand. Let's say you have 10 "required" properties and you create a 10 parameter constructor for that. If you initialized the object the old way, you would have to pass 10 arguments in there. But if you use the required keyword, you still have to provide those 10 values, no? So how does this or Explicit Nullability make it less unwieldy?

  • @cn-ml
    @cn-ml 2 роки тому +26

    Oh wow, finally, this is the most necessary feature i have been waiting for in my use case. This makes Initialization so much cleaner and improves on the nullable scheme C# has been moving towards. This removes so much unnecessary boilerplate code in my codebase that is only useful for making the compiler shut up about warnings, without any additional benefit.

    • @nickchapsas
      @nickchapsas  2 роки тому +8

      You can finally say goodbye to those "= default!" calls. it also makes working with deserializer code so much easier

    • @cn-ml
      @cn-ml 2 роки тому +3

      @@IIARROWS yes, but i have a personal policy on my code that i keep nullable on to write more safe code. I think nullable is a great addition and instead of circumventing warnings, we should introduce semantics that do not raise such warnings. This is why i like this new feature

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

      @@IIARROWS well in fact it can be null. If you mess up and forget to provide the property. That's why I think = default! (except for injected values) or turning off NRT is a bad idea. Just create a constructor for required properties. With named parameters it almost looks like property initialization. That being said the required keyword is better and I will replace my constructors with it.

  • @damaomiX
    @damaomiX 2 роки тому +7

    The discussion in the issue is very interesting. Personally I prefer "public string X { get; required init; }".

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

      Likewise, I think this would add huge amounts of clarity to code.

  • @nanvlad
    @nanvlad 2 роки тому +53

    Attribute constructors means something like [Required(ErorrMessage="Error")] as an example

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

    I really like that they're adding more tools for api/tool code to demand correct usage through compiler errors rather than runtime errors, that's the most powerful thing a compiled language can do to help us

  • @IRofledTheL0L
    @IRofledTheL0L 2 роки тому +7

    I just hope this works well with JSON serialization. That requires a parameterless constructor for deserialization anyways most of the time, so the required keyboard spares me a lot of checking code. I appreciate it immensely. And I also also highly appreciate the work you're doing with Videos and courses.

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

      Constructors also work though. Been using records with json serialization which are very concise for this.

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

      Any updates on this? I remember using deserialization skipped a lot of the initialization rules we had in the past, such as defaulting a property to an empty collection, both in the constructor or as a default property assignment. C# basically just created an object from what it was given and ran nothing else, so it always made sense for us to just have a validation service that would run. Or in this case, "correct" the data. Treating it like a DTO and then mapping to a full fledged object probably would have been the better choice, but live and learn when maintaining feature parity across multiple code bases simultaneously lol.

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

    I felt it when you showed the constructor where each line had a value to pass in required fields. I’ve been in that scenario far too many times. I was also in a bit of a pickle because the settings for our quality gate, SonarCloud, restricted the number or arguments for methods including constructors. So in the end I ended up resorting to “smuggling” arguments in a class solely built for passing all the arguments I needed. I do like the idea of transforming object initializers into de facto customizable constructors with the ability to declare required properties. I’ve been out of the loop for a while due to health issues so I’ve been enjoying catching up watching Nick. Thanks Nick!

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

    This is great in theory, but only for simple constructors. Any time you have to initialize a collection property with an empty List, you’ll be right back to doing it the old way.

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

      You can just initialize the property with an empty list. No need to do that in a ctor.

  • @Bliss467
    @Bliss467 2 роки тому +22

    I wonder if this can be made to eliminate the boilerplate around defining and assigning dependencies in dependency injection

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

      Maybe this? public required IFoo Foo { init; }

  • @jamesmussett
    @jamesmussett 2 роки тому +11

    I’m curious to see if classes with the [RequiredMember] attribute will impact Activator.CreateInstance()… mainly from the perspective of a library/framework maintainer…

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

      I haven't read through the proposal or related media, but based on what I saw here it looks like it's something that only happens at compile time for statically known things, which Activator and co. already don't care about. I imagine this changes nothing since the default constructor should still exist, but I can see a world where they throw an exception I guess.

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

    This helps patch the huge hole created with non-nullable types on properties. Now you won't be able to forget to initialize those important properties. Constructors were sometimes an option but often felt too clunky to use. I'm so glad this feature is finally coming to c#.

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

    I have expected for this for long time.
    I got tired of using ctor just to enforce required members initialization.
    I Think I would use that a lot!

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

    I'll be using it for sure. I was actually waiting for such a feature.

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

    Hey Nick, I would love to see an ASP Net Core class that ignores MVC and focuses purely on the API side using best practices such as mediator and any other libraries you reccomend. If one already exists usisng C# 10 it would be great to hear your reccomendation. All of the tutorials I find focus on MVC and not the API / server side of things. This is interesting for me as I mostly use Blazor WASM as a front end and having a rock solid server side deployment would help make my application enterprise ready.

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

    I love it. I have hated constructors for dto unless you go the full record route. And doing nullable makes it more difficult because you have to assign fake values everywhere. Now you can just require and not deal with string.empty everywhere.
    Thank you as always

  • @masonwheeler6536
    @masonwheeler6536 Рік тому +8

    I kind of take the opposite view: Where initializers exist, they're evidence of a deficiency in the provided constructor(s) on the class. If you have to assign 10 properties to the object to initialize it correctly, the problem isn't that you have a really big constructor; it's that you have a God Object that needs massive amounts of initialization to work correctly.

  • @IAmFeO2x
    @IAmFeO2x 2 роки тому +10

    Great video as always! I'm wondering if DI containers will support the required keyword. As far as I know, all of them rely on constructors for automatically determining which dependencies should be injected.

    • @nickchapsas
      @nickchapsas  2 роки тому +4

      I don't think they will because I don't think it will solve the same problem. The main reason why required makes sense for POCOs (mostly) is that you actually initialize them yourself. For classes with injected dependencies, you never initialize them explicitly (except for unit testing when you pass the mocks)

    • @krzysztofklein3057
      @krzysztofklein3057 2 роки тому +14

      lets wait 5 more versions of c# to have *inject* keyword 😀

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

    That would be WONDERFUL!! I'll use it a lot... well it depends on what exactly mean "required" for a string.

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

    Oooo this is nice, I can stop using named parameters to essentially get the nice explicitness of initiaze lists with required variables

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

    My only issue is if some property is partially required. For example if another property is set like if MiddleName is set then FirstName is required. This should probably be solved by an abstract factory but constructors would also be a solution aka having Person(string first) { } Person(string first, string middle) { } Person(string first, string middle, string last) { }. However it would be good to put required on the first name.

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

    Really glad to see this finally making it into the language, I've wanted this feature for a long time.

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

      Seems almost like a constructor with braces instead of parentheses. Defining by marking the properties themselves as required is nicer than defining the same concept in a constructor. But it is basically the same thing.

  • @efdrgn
    @efdrgn 2 роки тому +4

    The benefit of having constructors is it makes your classes neater IMO. The logic for setting a properties of a class should be within the class itself otherwise you end up having instanciations of your object all over the project. It also makes it easier to read what's implementing that object when using the "2 references" (visual studio enterprise)

    • @fabiant.2485
      @fabiant.2485 2 роки тому +4

      The required keyword on it's own is not meant to replace any meaningful "logic" that would usually be found in a constructor. Instead it is replacing the unnecessary legwork of having to create huge unwieldy constructors which do nothing but take a bunch of mandatory parameters and assign them to properties/fields.
      If you want to implement custom logic during initialization you can still use constructors as before for those properties/fields that need it and use the required keyword for all other mandatory ones. Same as you would use auto properties to simplify get/set access to a single line and only implement custom get/set logic as needed.
      Also another neat C#11 feature which Nick has not mentioned goes very well with this:
      You get field access in auto properties: Each accessor in an auto property will be able to implement themselves and can *refer* *to* *the* *automatically* *allocated* *backing* *field* with the fittingly named keyword *"field".* Example:
      public required string FirstName { get; init => field = value.Trim() }

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

    Dude gets people hyped for a c# release like none other

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

    This is fantastic. Constructors are such an old legacy way of initializing things and being able to not have to use one is amazing 🤩

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

    that feature comes from dart, dart is the language of flutter, in dart you may declare a variable as required on the constructor then you must provide a initial value or the compiler throw a error

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

    Thank you! I would definitely use this. I have needed it for at long time. Also, if you need a xaml control that needed some startup properties, you can't use a constructor for that. As far as I know, there is not "logic" way of making it obvious for the user of your control, which fields are neccessary and which are not. I hope they will make this work with the xaml compiler, so it gets angry if the required fields are not set inside the control element, or at least an option to make it so.

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

    Hi Nick. I just found your channel a couple days ago and I'm loving it! Keep up the good work!

  • @user-dc9zo7ek5j
    @user-dc9zo7ek5j 2 роки тому +3

    Note that properties are not the same as constructors, and the compiled code is much bigger, and thus inefficient compared to the constructors, because each property is set externally outside the class. Funny enough, we even bloat out the source code with by using Property = value and setting each property on a new line and such.
    I think records is one of the features that really helped with making classes short and clean. Plus, when implementing a new feature you can add a parameter to your constructor, or another parameter to the record, and you can safely go through all the places where the class has been instantiated. With properties it's a little harder, since you can't really see where it has been created.
    We really don't need any more ways to create a class neither instantiate the properties, seriously, we could write a top 10 ways to create an object in c#.

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

    With the 'required' keyword on the horizon, it feels like C# is finally turning up the volume on its safety feature. Forget constructors, it's all about concise and clean code now. It's like spring cleaning, but for our codebase!

  • @fred.flintstone4099
    @fred.flintstone4099 Рік тому

    This is great and I look forward to the required keyword, but at the same time, it shouldn't be required if the language was properly designed because we already have nullable and non-nullable data types, so it should already know that the property is required if it is not nullable, but I guess this is because of backwards compatibility.

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

    This is awesome for writing API code and models and now would make the intent much better at compile time!

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

    Nick - thank you for such a well explained video on the upcoming feature.

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

    Cool, something that I could never do before is now actually possible :). I wrote my own DI Container long time ago that uses MEF-like attributes and field-injection and I got massive problems with nullable-reference types. BTW, I love attributes because they tell me exactly how a class plays a role in the infrastructure in comparison to other DI DI containers where I have no clue whether the class should be manually instantiated or retrieved from DI container, I imidiatelly see what dependencies a class has, I don't need to use constructor and extra code to set the fields, and I don't need to register each class. For instance:
    [Export]
    public class C
    {
    [Import]
    private D dependency;
    }
    I got warnings that property is not nullable but is also not initialized directly in code. I don't want it to be nullable because it is not optional and DI container will throw an error while bootstrapping the application if dependency is missing. Using "required" keyword could solve this big problem.
    [Export]
    public class C
    {
    [Import]
    private required D dependency { get; init; }
    }
    I would have to use private properties instead, but it's fine and not much more code to write. But I need to experiment with the feature if it would actually work.

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

    This looks very nice, but i have a big problem with this feature. You cannot do any validation based on the member. A sample would be: You have the properties Start and End and want to validate that Start is smaller than end. How can you handle it with this feature? Constructor is called before any value is set and if you do the logic in the properties the order matters.
    PS: Sorry for my bad english

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

      You can add it in the setter which is really where it should be. Ctor only ensures the creation but not any subsequent value setting

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

    I like this, I always preferred to use constructor parameters but this approach makes it even better

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

    Convenient feature. if you have a ctor with 10 parameters maybe you could use a builder though

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

      Builders are hard when you need to do programmatic stuff with that type, for example writing a serializer. I like it being an option but not the only way unless there is a very specific reason, for example guided initialization

  • @octe-es
    @octe-es 2 роки тому

    I saw that feature on dart and I’m glad it is coming to C# as well, great video, btw

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

    One of my main problems with records is actually that they don't have the pretty class init syntax. I think It is way more readable than using constructor when initting records (even though you can use named parameters). Very excited for this feature to land!

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

      It's more verbose, but you can declare records and just not provide the parameter list. You'd be writing the same { get; init; } properties manually instead, but you get the initializer syntax back. For more complicated records this is what I currently do because the benefit of compiler generated Equals/HashCode is sometimes worth it, just missing the required marker still : (

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

    15 seconds into the video and im already sold

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

    One my next new favorite C# features !!

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

    I like your videos.
    And I like that you use allman braces. They're nicely readable for people with bad eyesight like me.

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

    This great especially when doing refactoring. However multiple overloads was used to have some different options and flow, but given from the example using model I can see many reasons why.

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

    Yeah init was not enough. I was thinking about this yesterday and this video shows up. Kudos

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

    Not gonna lie, this seems really strange to me, I would question why do this when records were just created which still forces that limiting by constructor approch. I'd rather have seen a 'auto generate constructor' rather than having required property construction. Seems like a split path just to try and please everyone.

  • @Erril-1
    @Erril-1 2 роки тому

    Very nice feature, thanks!

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

    This functionality was really lacking before, but the option when the initialized object has fields in the constructor and required fields does not look very good 😅

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

    hello Nick awesome content, I just bought your class about testing (used the code and still worked, yaay!), looking forward to watch it, what I would like to see more is some high performance optimizations, usage of spans, seems like C#11 is moving in that direction with utf support and patter matching, do you think Span will be for mainstream use and proliferate thru most modern c# codebases? Can you consider making course going in depth on this topic - performance, memory allocation and usage of span and memory?

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

      There is actually a course about writing performant c# code coming hopefully this year. It’s really something I wanna make more content about

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

    That's a nice feature. The more boilerplate unnecessary code they can remove, the better c#/.Net coding experience gets.
    I'd love to get rid of constructors just for dependency injection as well. Just add a "injected" keyword instead

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

      How would you mock it? If you set it using object initialization it uses that, otherwise it injects? That'd be cool

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

    Seems like a huge design mistake by C# language designers that a init-only property of a non-nullable type does not need to be initialized during construction.
    Trying to work around that mistake by adding yet _another_ keyword is really disgusting.
    Why not fix the actual design mistake directly?
    The semantics of init should not be that it is identical to a single-use setter (that could be called whenever you like .. or not at all).
    Instead init should mean that initializing the property is part of the initialization of an object during its construction.
    Case in point, with the design presented above, if I had a Widget class with 10 required string? properties, would I need to create an empty Widget like this:
    new Widget () {
    PropA = default,
    PropB = default,
    PropC = default,
    // or nulls...
    PropD = null,
    PropE = null,
    // and so on ...
    }
    ?
    Or is there yet another inconsistency in the design and there is some special handling for this?

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

    Great news! That's one of the reasons I was so upset about using nullability features in C#. They forced me to use constructors to init properties. And I don't make use of constructors for most of my programming thigns.

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

    This one seems really handy!

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

    It will be one of the best features, especially with the recent null state analysis.

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

      "= null!" no more

  • @JustinSommercorn
    @JustinSommercorn 2 роки тому +27

    While I like the idea of the feature, it takes away the ability to explicitly know how to create a class without dealing with errors. Having the values in the constructor at least tells you right away what is required to make the class. This feature you won't know, until you see errors.

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

      So it just needs IDE support for suggestions, not a big deal to implement.

    • @JustinSommercorn
      @JustinSommercorn 2 роки тому +7

      I'm sure they'll have that as well; however, how does that help when looking at documentation of a library? Now you not only have to look at constructors but the properties as well just to figure out how to instantiate it. I just fail to see how this speeds up development.

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

      Reminds me how in records you don't see the argument names like in a property initializer

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

      Agree, and what about polymorpishm, multiple constructors with different required parameters. This is ugly way. I can not imagine big app written with this way. Huh

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

      @@jakubhantak1960 actually having multiple constructors that initialize different sets of properties is a code smell and this pretty much eliminates that code smell, so it's a win.

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

    what if i need to run a class method to initialize a property? i would normally run it in the constructor and assign its return value to the property but like this, without a constructor, i'd have to delegate that to an external method in order to call it during initialization. maybe this will come in handy for a few scenario but constructors will still be needed for complex inits

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

    Excellent video! At time mark 5:00, what are you using to draw on your screen so quickly?

  • @RoaringOrange
    @RoaringOrange 2 роки тому +11

    Would be fantastic to have some kind of constructor or initializer method on a class or struct that runs AFTER all property initializers. So we can add logic with all the parameters already in place passed via init properties. This could be achieved by adding [init] attribute to the parameterless private constructor. Or add "init" keyword in front of it. Also, this method can be invoked by deserializers. Just a thought.

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

      @@Eirenarch my thoughts exactly

    • @user-dc9zo7ek5j
      @user-dc9zo7ek5j 2 роки тому

      Could you give me an example of the use case, im curious.

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

    Nick doesn't need constructors because he's simply so powerful he can instantiate objects by sheer force of will

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

    I would love to have this. I only wish I could dind a migration path from Framework, which doesn’t and won’t support modern C#. This is mainly a question of updating UI from WPF.

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

      This seems like a lowering change, which means it's supported in .Net Framework. Most language changes are supported on Framework.
      I only know of two things that aren't (I'm sure there are others): Default Interface Implementations, and the `with` keyword for structs. Every other thing I've tried (up to and including C# 10) works on .Net Framework 4.8

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

    Love this feature, can't wait to use it

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

    Well presented Νίκο! Thanks for the content!

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

    Once this was explained, I realized how useful it is. Cool!

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

    Interesting choice of arbitrary number Nick

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

    So much syntax sugar were added lately that I'm sure C# 69 would be the sweetest thing ever.

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

    I'd say: really neat for data classes but I wouldn't use this for anything that requires DI.
    Say you need to register to an event on your dependency then this would now need to happen in the property setter. And I'd rather have all my initialization logic for a class in one neat place.
    Also if you ever needed two of your dependencies for some initialization call you'd suddenly have an invisible required order of how your properties need to be set because otherwise the code breaks. And the bad part about it is of course that that requirement can happen down the line and then your only sensible approach to that would of course be to go back to having a constructor. But at that point that would be a breaking change (granted the Di-container really shouldn't care about that breaking change but all your unit tests will mind very much so it's still quite a hassle)
    So tl;dr; will use that for POCOs but not for anything with logic.

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

    Even though this wouldn’t be used for DI, it still gave me a feeling that DI could be trimmed down substantially with a similar approach. We’re almost always doing the same boilerplating in DI (except for e.g. the Options pattern), so reducing it all down to the field with a keyword such as ”inject” or something would make the code a lot more beautiful and completely remove the need for constructors in most cases!

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

      Almost all DI already have this autowire properties functionality. But ctors are better. From point of view autofac is number one especially with optional injections, factory injections etc

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

      @@ztBlackGad True but I don't want to use properties for DI. Just feels wrong to me. Private readonly variables only...

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

      @@briankarcher8338 then how to mock dependencies? :)

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

      @@ztBlackGad Constructor. These variables should be kept encapsulated.

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

      @@ztBlackGad Mind you, I wouldn't mind some sort of attribute or something to mark a private field as an injected field as mentioned by others in the comments. DI can get really heavy on the constructor - too much boilerplate that is unnecessary and not that hard to fix if Microsoft/3rd parties wanted to fix it at the compiler/library level.

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

    I really liked this feature, but I'm still think how it's gonna be for dependency injection via constructor ? It's gonna stay the same?

  • @kenbrady119
    @kenbrady119 2 роки тому +4

    Are you able to "initialize" the required FullName with null or string.Empty?
    I'm likely to stick with constructors. It is rare to have more than a few parameters, and it is the perfect place to verify values.

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

      I would argue it is a bad place to verify the values actually. Should it really be the responsibility of the class itself to know what values are valid? For all the types of models? Both API contracts, Domain object and database DTOs? I'd rather have a centralised piece of code that validates instead of spreading my validation integrity which can lead to problems.

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

      @@nickchapsas Well, taking something from DDD, you can use a Value Object for FullName and I'd say it's totally its responsibility to check valid values for its invariants like don't accept empty strings or null as internal values. Then the Person class should just validate against null FullName values, otherwise, I'd say you're having a kind of anemic domain model.

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

      If you combine it with the field keyword (please tell me it will be in C# 11), you could do your checks in the setter before assigning the value in the backing field.

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

      @@nickchapsas Yes - it is the class's responsibility to verify it's own data integrity. Who else knows better? Granted, a class might consult global and/or injected values to decide what values are valid, but that logic is the responsibility of the class. The old-fashioned term for this is "encapsulation".
      I am indeed old-fashioned - I started learning C# in 2002, and was a C++ & Turbo Pascal programmer since 1988. So I humbly admit I may just be howling at the moon of modernity.

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

      @@Krimog Yes, field will be included.

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

    it has a lot of uses where only a single constructor is needed, but if you are working on a factory type of class that gives access to different implementation based on constructor input then it obviously doesn't work

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

    Cool feature. Fixes the problem of constructor boilerplate and\or missing property inialization. However, the code is still too verbose. And JS\Python\Go\Other developers don't like C# for having so much "useless" code. Looks like the entire concept of properties should be reworked. I know the idea, but adding {get;set} and use it as a field looks like a trick, not like real encapsulation.

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

      E.g. What if we had fields "init" by default? All the fields can be initialized in a constructor or object initializer and accessed only for reading (if they pulblic\internal). And if you need a public setter you add some keyword

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

      I think C# code is verbose as it should be, surely it could be better but IMO the clarity of the code is almost instant for anyone reading.

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

      @@diadetediotedio6918 Well, they add new features to C# itself to make it less verbose, e.g. records. If you compare C# to Kotlin, it less verbose and offers the same features

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

      ​@@dimalisovyk5277
      Maybe, but kotlin comes with the Java garbage and .NET environment is a different thing, so the verbosity in this case is justified because many reasons (like, Kotlin don't have pointers or low-level programming as C# when needed, C# is very old and is actually more prox from Java and/or C++ than a modern looking language like Kotlin. In Kotlin, you depend upon the JVM-compatible runtimes (yeah, I know Kotlin has a project to compile natively using LLVM, but the language features will probably not be less restrictive because the need of interoperability with JS and the JVM) and in C# the CLR is more like a framework than a runtime by itself. So I think Kotlin doesn't offer "the same features" or has the same purposes, C# has a good readability and is getting better on it, it is the tool for some jobs and Kotlin for others, there's no a silver bullet in this area.

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

    Sounds interesting, but we can't say that we won't need constructors. What if I want to encapsulate properties or class members? If I do with this approach, class inner fields must be an ''public', which brakes an Encapsulation approach, because members are visible outside of class. So, in my opinion right place to use it is DTO classes where we need to be initialized their members when we're creating its object. Thanks ;)

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

    I personally not a fan of that approach, I would rather use "static factory method" pattern instead, then you can have a good named method that describes exactly for which purpose you create this object and if you need to create the same object maybe with other properties filled, depending on the use case.

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

      In my own experience having multiple such factory methods have been a sign that I should really have different types for those different use cases and I was trying to jam too much into a single type.

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

      @@bread8176 you mean like bad smell that single responsibility principal was not respected? I think it depends on how many of this methods you use, but sure this pattern can also be misused like every pattern I believe.

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

    Well, with constructor you can do this: new(arg1: value1, arg2: value2, ...); you can omit the name, you can still have argument names; others have raised interesting questions, for example how does this work with reflection. To me, using an explicit constructor would be better, also esthetically it would be practically the same as new Class { args = blah }; we'll see i guess.

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

      You can't always do so. For example in Expression trees (Linq to Sql for example, used in EF queries) this is prohibited.

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

      true but it's also quite a special context anyway

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

    Indeed that's a great way to initialize objects without having to declare a constructor wherever data initialization were only needed, but saying you won't need constructors from now on or barely use them I thing is far fetched. :P Won't you still need to run other functions on initialization to prepare the new class in many cases?

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

    Thank you 👍🏻👍🏻

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

    Nick: Why I won't need constructors anymore
    System.Text.Json: Hello

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

    I think the title is a bit misleading. Constructor dependency injection isn't a special use case.

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

    So this should remove the dreaded " = null!;" after all my properties?

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

      Yeap!

    • @petrusion2827
      @petrusion2827 2 роки тому +4

      Genuinely asking here; in what scenario do you need to do = null! after your properties? It sounds like a huge red flag to me.

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

      @@petrusion2827 It's when you know for absolute certain that a property isn't nullable (using NRTs) but you need to suppress the nullability warnings of C#.It's usually when a field is init only but you don't want to make a constructor to suppress it. It's pretty standard and even Microsoft code uses it, even though I think they do "= default!" not "null!"

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

      @@nickchapsas I'm having some trouble wrapping my head around this. Without the required keyword, aren't you risking that the caller won't initialize the property, making it null?

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

      @@petrusion2827 There is a slight risk. In my case those properties are DTOs only used to receive json api requests, and we already have validations that return 4xx responses if thoses properties are not populated.

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

    An old school approach to eliminating noisy constructors has been passing in a single class to the constructor that contained all the initial property values. I do like learning new ways to accomplish a problem. Where I work I am forced to work in .net 2.0 for the systems I work on.

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

      Having a constructor with a long list of inputs is a design smell anyway, so it's probably better that data is being passed around in smaller classes anyway

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

    Hi Nick, thank you for your videos. Why do u always use num 69 as an example number? Is that mystery num for ya? ;)

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

    Great video! Thanks for the content!

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

    I wonder how it will work in Entity Framework. How EF will bypass such feature.

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

    Finally setting something = string.Empty to stop the compiler complaining is a thing if the past, long overdue feature!

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

    I've always just used the [Required] class annotation for my models

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

    Using constructors:
    ```csharp
    var bill = new Person
    ( FullName: "Bill Was"
    , ...
    );
    ```
    So, if you have a long list it isn't too bad to look at. Basically it is the same as `new Person { FullName = "Bill Was" }`. Except avoiding all the constructor work with `required` would be even nicer 🙂.

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

    I'm torn on this feature. It's definitely good for readability of the code, especially outside of IDE (Pull Requests/Github etc), where you don't see what each constructor parameter actually is. But for developer experience while writing the code I see issues.
    This is nice for a model with 2 properties.
    Model with dozen(s) properties will be much harder to use with this feature, simply because devs will now have to discover which properties are required and must be set. Before that'd be solved with constructor that provides structured way of showing which parameters are required and which are optional.
    Also I've been switching to using records for any POCO/DTO type classes anyway, and those have the opposite approach with being set via the constructors.
    SO I dunno, I feel like this feature is, for now, tact on and sort of starts to interfere with other features they've been introducing. It will also largly depend on good IDE support to help with required property discovery. I'll see how it's handling in "real world" while it's released and what scenarios it becomes better than records, for example. Maybe IOptions, that do not support constructor parameter values injection? Dunno, we'll see.

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

      You can also declare records without constructor, just like normal classes and use object initializer.

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

      This is the comment I was looking for

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

      I think this actually make development more precise.

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

    Hmm, I don't know... at the end of the day you gotta write this down anyway AND you have extra keyword to learn. But I guess nothing beats adding the 'nullable' feature: you code it like a pointer but it has a fragment of the functionality.

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

      This works with the nullable feature. In fact it is what makes it actually work instead of having to fake suppress warning withs "= default!" and "= null!"

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

    I won't be using this. We already have the ability to pass variables by constructor parameter name. The code will look almost identical you just have parenthesis instead of curly braces.
    var person = new Person(
    FullName: "My name"
    );
    vs.
    var person = new Person{
    FullName = "My Name"
    };
    If in the future if you need to mark members based on some of these required members you will now have to use a constructor and broken backwards compatibility. Each instance will need to be rewritten to use the constructor.
    public class Person
    {
    public string FullName { get; init; }
    private bool IsNick { get; init; }
    public Person(string FullName)
    {
    this.FullName = FullName;
    if(this.FullName == "nick")
    IsNick = true;
    }
    }

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

    Where this could be interesting is with places like Entity classes and maybe Razor Pages code files. I often end up disabling nullable reference types in these files because adding massive constructors or having to check for null every time I use a property is not practical. So I'm assuming this was in response to nullable reference types and initially it didn't sound like something I needed but now I'm thinking maybe I do.

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

    I'm looking formward to this, wonder how well it will work with json deserialization.

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

    I imagine that the check is on the codeDom side or at least at compile time
    What happends if you instanciate a person at runtime like this :
    var person = (Person)typeof(Person).GetConstructor(new Type[] { }).Invoke(new object[] { });

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

    This would make DI so much neater, looking forward to it.
    Will the compiled code keep the constraint such that this will work even if the class is used from a dll?

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

      Why would it make DI neater? Most of what I've seen that's dependency injected gets assigned to private fields, not properties.

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

    Can you please do a video on your thoughts on the future of Software Development specifically as a result of the increasing usage of AI? Most of the research that I have done suggests that there will be an enormous amount of job displacement because, whilst big business is pushing the 'augmented' agenda (i.e. AI won't replace people), this doesn't actually appear to be the case at all.

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

    I'm using the [Required] attribute all over the place. Constructors feels a bit "old" sometimes.
    Though the Required attribute only gives runtime exceptions, while what you would really want is compile time errors.
    This seems to be throwing compiletime errors when a field is required, which looks nice!
    Though we have a problem in our current project where we make value-types like int nullable, so that we can use the [Required] attribute to make it actually required... Which seems confusing and error prone.
    Would be nice to see required working on value-types, or being able to state "required init" for a property! We would have less confusing code in our project :-)

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

    Hrm. I guess that's good if you don't do any validation of constructor params. What about initializing the instance with a string.Empty or " " (Whitespace) for FullName property? Can we do validation and throw InvalidArgumentException with required/init?

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

    Constructors already allowed for named parameters to be given. As far as I can tell the only change here is now that you can write exactly the same syntax but with curly braces instead of parentheses?

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

    I don't really get it, but OK.
    What I don't like about third party tools/addons/libraries is the dependency on something you don't control, from people/shops that we don't know and that may stop maintaining their code with no say, support or obligation towards you.

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

    I'm very interested in how this would work with Dependency Injection.

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

      It won’t, you still need ctors for that

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

    Amazing 👏
    I wonder if it works while calling a method with input class that has required properties
    This may improve the method input limitations