Yeah literally yesterday I tried to assign value to an int[] property in a constructor of an extension class for a pagination view model and the compiler did not like PageSizes = {10, 20, 50}; Until I did “new int[] {10, 20, 50};” and I thought it was dumb. Quite happy it’s going to work now if I use square brackets.
First version in years that I'm not super excited to upgrade. I will be upgrading ASAP anyway. My biggest would be primary constructors, if I could specify them as read-only. Then I could remove a ton of boilerplate dependency injection constructors
@@Meryovi another bummer is that they do not automagically convert into get-only properties as in records. But then again, maybe it's time to convert our services to record types lol
I thought i understood primary constructors and didn't like them as well, but it's actually more flexible the way they are, if needed readonly: class MyDataService(OtherService otherService) { private readonly OtherService otherService = otherService ?? throw new ArgumentNullException(nameof(otherService)); As you see, not only readonly, but also checked for nulls just in case, and all as part of field initializers. I find it useful to simplify dependency injection, I think Nick didn't cover this point enough.
int[] values = { 1, 2, 3, 4, 5 }; has been around since 2001 as array initialization syntax, but now you can replace the {} by []. So that's pretty cool ^^.
it is similar to Python which can infer the type also. It looks like they are trying to add more syntactic sugar to make c# a more compact language, in your case, it is the same number of chars but using square brackets consistently is nice
As happens quite often, some features were taken from F#, where they've been part of the lang for a long time. I.e.: primary constructors, collection expressions, type aliases. Inline arrays are cool, they were part of MSIL for some time, but you couldn't easily use it.
Awesome video, thank you! I greatly appreciate the quality of life features and I'm sure libraries and code generators will make good use of the other features. I wonder if it's going to be practical to actually use inline arrays or if just using Spans is going to be enough for most of us. Looking forward to default constructors and collection expressions getting fully fleshed out in C#13 and 14.
Please do a video on .NET 8 Minimal API Native AOT on AWS lambda, using a database. There were a lot of improvements in that area compared to .NET 7. Thanks!
Overall this lang version seems a lot less interesting compared to the past 3 versions. Alias any type seems kinda neat, though it's unlikely I'll use it. Primary constructors have a weird implementation and I'm hesitant to treat them as safely usable in comparison to how they work in records. Interceptors are conceptually interesting, but I fear the code some hotshot programmer might write thinking they're clever trying to use a feature intended only for source generators. Collection expressions seem real nice though, easily the most useful thing on the list. C# 8-11 were pretty interesting, adding using declaration statements, switch expressions, explicitly nullable reference types, records, advanced pattern matching, and all sorts of game-changing features. Not really seeing that this time around. Still annoyed we don't have language-level union types or readonly locals yet.
Seems to me most og the “features” we will get are performance improvements, and I’m totally fine with that, as all the frameworks are getting new and nice stuff
@@rex.minglaInterceptors are supposed to work with source generators. Devs should never have to write it by hand. Source generators are run during compilation and will generate code based on the one that's being compiled, so the difference between machines won't matter - the in-memory generated code will be slightly different for each dev (different paths for example), but the compiled code will be the same - the new method will be called, instead of old one. It's basically a feature that wants to replace reflection. Reflection is not only slow, but also only evaluated during runtime. Interceptors will be evaluated during compilation, and produce a runnable, already "rewritten" method call.
I could see the alias feature being useful to pass around a tuple easier inside a class. Interceptors as well for test scenarios where there are no interfaces for the methods and it would be time consuming to refactor legacy code. But neither of those would push me to c# 12.
PrimaryConstructors => look like a poorly-controlled properties with public setters. CollectionExpressions => cool stuff. Interceptors => Beyond mocks, I don't see what new opportunities they offer. All the rest => probably won't use, but thanks for keeping us up to date. 🙏
Interceptors could be very helpful for inserting log messages to where-ever necessary but without actually changing the code being intercepted, and you can easily remove the interceptor code later when logging messages are to be removed, once again no need to change the intercepted code. As for how to specify the InterceptsLocation attribute with accurate file path / line / column info, I guess it would need some smart preprocessing code, but that still seems doable.
Interceptors basically allow you to do what only PostSharp can do without making changes on compiled code (the way PostSharp is doing this), so, imagine nuget, that will generate interceptors which will decorate your code with logging/caching/change tracking and so on by just simply adding one attribute to property/method/class. That's just easier way to do such things than modifying IL. It is also cleaner way of doing this because the code is there and you can debug it easily. But, again, this not for 99% of developers, this is for small percentage of devs who develop cool tooling libraries. Primary constructors are only syntactic sugar and while I get they tried to achieve the same thing e.g. Typescript has, although I prefer the Typescript way actually.
I agree that in this form interceptors are useful but on niche scenarios, probably are design this way to avoid to abuse of them, anyway, file path, line and column.... looks VERY ugly to my eyes, do someone knows if the path can be at least relative? I don't want to check in code that works differently when someone clone it in a different path
@@dukefleed9525 why would you even ever manually write an interceptor? They are ugly because they can be - they will be always generated in some way or another, there is no reason to write them manually because if you can write something like that manually then why don't you just edit your method directly?
Interceptors should be extended to something that can be configurably invoked OnEnterMethod and OnExitMethod (sometimes useful for logging performance or tracing hard-to-.find bugs) and then can be disabled, when the issue is fixed.
Yeah I hope they will revise that again before considering it done. Right now it looks more like a half-arsed text replacement instruction to the compiler rather than proper interceptors
Thanks for the video, very simple and useful. As for me, primary constructors are game-changer, but I don’t like it at all. I believe they add some readonly keyword for parameter in C#13. Because with current implementation you simply cannot replace private readonly fields with constructor parameters and restrict their re-assignment. Collection Expressions - okay, cool, but it’s a pretty little change, so WHY is it cut??? I mean no support for Dictionary. Interceptors are something for library developers, not for regular web devs I think. Btw I waited the ‘field’ keyword for properties. To validate setter without manual creating of a backing field. And discriminated unions, of course. Feels like the whole community is just waiting for them.
I wish that we had struct type collections. I have an instance where I need to do a deep copy on a structure of collections because the data needs to be transformed by multiple users and then merged back into a single structure.
Hey, you said about "void Test(ref readonly int age)" and "void Test(in int age)" - it is OK. But I think in order to understand difference between "ref readonly" and "in", you should say couple of words about "ref readonly int GetAge()". IMHO )))
Going to use all the features here except Primary Constructors and interceptors. Though interceptors are also very interesting but they need to come out of experimental before we can use them.
If I'm understanding this correctly, interceptors could be used by testing libraries to source generate efficient mocks for concrete types and maybe even extension methods?
Interceptors are for source generators, and source generators only. No sane programmer should write them manually in their codebases, otherwise it's a massive footgun.
@@gctypo2838 exactly. I've seen some people complaining they look ugly with those line and column syntax - for me this is even better: if they gonna break after every little change then no one would use them in purpose of manually modifying method. I mean, I don't know who would want to even do that when you can edit your method directly, but I'm glad that syntax is even more discouraging...
This these last years Microsoft seems to be enabling themselves to make everything blazing fast and aot friendly so we can all run all our code extremely efficiently on arm server and laptops soon. Did they do anything to improve the experience of writing source generators? i find usecases for it very often, but it's often a bit crappy to work with, especially if you build and use it in the same solution.
Collection expressions. IDK how I feel about primary constructors. As far as many of the features being Microsoft-centric, they presumably make things better or more performant, so I'm all for them. I'd rather know about them then for them to be hidden.
Alias any type but not generics yet, if I understand correctly. Generics was one of the first things I was looking to alias at some point. One step at a time, I guess.
Primary ctors and collection expressions are ones I like and will be using a lot. The alias is at a note-worthy second place. For the other features I don't see an immedaite use case.
Regarding interceptors so this is mostly for people who have access to source code but don't want to edit it directly but they want to alternate it only for some specific cases that they uses?
The general "we" won't be using most of this features, but like you mentioned yourself: library authors besides Microsoft itself can use it now. That way we don't depend on the wits of Microsoft alone to get stuff which is possible with these features.
they said they were wary of introducing a change that would break the code of the few developers who might have named a field "field". someone from the c# team said they were going to move ahead with it but provide a migration tool and they couldn't get it ready in time, partly because they had been considering several options
Not that many lifechanging features, well it's an LTS version so it makes sense. Feels more like they had to release something so they just used their internal features.
for primary constructors that'd be great if we could have a syntax like public class myclass (readonly ParamType1 param1, readonly ParamType2 param2) { init {some init code} // class stuff}
For me C# 12 brings only 2 good features: Collection Expressions and default lambda parameters. I know many ppl think that Primary Constructors are good one. But for me personally I don't like them at all. The reason is that it breaks naming conventions. I like the fact when I see _smthing it's private field of the class when reading code 200 lines below constructor declaration and if something without underscores - it's method argument or local variable.
Well, you still have the option of not using them at all if you like this weird naming convention of using underscores. And you can also name your params with _ in the primary constructors.
@@alehkhantsevich113 I didn't said your explanation was wrong or bad, or that underscores did not make sense. I said they were weird (and for me, kinda annoying), and I don't like using them in general (and I really never perceived any more difficulty in just using only just the name). For me, most of the time you will not need to make these differentiations, you can get it working pretty well by just using camelCase for fields and PascalCase for properties, and when you are in a constructor you just this., it works and it is not weird.
For me it is a welcome change, I didn't like the _smthing since we have dropped the m_smthing already in an earlier phase. (coming from c++, yep I'm old cat 😅). The compiler will warn you if you have a local or class parameter clash. I strongly believe the _smthing only stayed, because people didn't like to use this.smthing in the c'tor init stage ... Also, side note: if you cannot make up what a variable is, then perhaps your class is doing too much and is too big.
@@diadetediotedio6918 Yes, I apologize for the rude previous reply. I basically agree that it is possible to write this way. But for me, separating private and local makes sense. Looking through the code, I instantly see when other services are called (since they are usually from DI and therefore private with underscore). In general, I like the idea of Primary Constructors, but for me it makes the code harder to read. So, I'll most likely do this: public class SomeClass(ISomeService someService, IAnotherService anotherService) { private readonly _someService = someService; private readonly _anotherService = anotherService; } This does not remove the entire boilerplate, but it does not violate the conventions.
I think that the only new feature I actually dislike are primary constructors. Interceptors can be a great addition for libraries that want to add compile-time AOP functionality to an existing codebase.
I think primary constructors are a great way to reduce boilerplate code for dependency injection. Because for every service you inject you needed to declare a field, declare a constructor argument and assign the argument to the field. Now you only need to declare the service in the primary constructor and you are done. So you reduce the code lines to one third, which may really increase readability the more services you need to inject.
@@maschyt I would agree with you if the generated fields were read-only and enforced non-null constraints. As they are, I don't find them convenient at all. I don't find that this adds anything to the readability since you're not actually clarifying anything for the developer andare instead relying on compiler magic that doesn't make the dependencies apparent as actual dependencies. Instead, what you get is a reduced initialization list for mutable members.
Interceptors are most exciting feature I think. I didn't notice that they put primary constructors like Kotlin. But why they don't copy full potential of this? :P
To me the current implementation seems so clunky that if you try to keep it working in evolving codebase, you spend more time hunting rows and characters than doing anything useful. It would be nice if it worked just marking the class and the method to intercept instead of manually trying to keep up with the changes.
I mean why they don't merge class and records. Records behind the scene creates public properties and just add curly braces to add functions. Besicly they have to extend the records 😜 Anyway.
I wish they would implement semi-auto properties... my view models are cluttered with explicit backing fields since i must call OnPropertyChanged on the setter of public properties
I would like to use the interceptors but without specifying the line and the path... maybe something like using the name of the class and the method that contains that call or something like that. It's very very risky to have these kind of "hardcoded" lines.
I'm guessing the first interceptor overwrites the code being intercepted, then the second interceptor overwrites it again so the second one actually takes the precedence. If this is true, then the whole interceptor mechanism will depend on the order of your codes being compiled. That could be a potential "interceptor hell".
Defining a type via using, it is perhaps similar to typedefs in other languages. Not sure if using defining a new type is a good thing. But sometimes you need a small class but dont want to declare it in an own file and having a possibility to straight up define a tuple combination for example as a type is handy.
Interceptor is just crazy, lol idk why they are releasing that.. so much potential for abuse.. let alone enormous debugging headaches for those who don't know it's being used!
@@prooseelike using a 3rd party library and intercepting code to change the behavior. Or being the 3rd party library, and knowing your consumers use other common 3rd party libraries and changing their behavior. Imagine if newtonsoft.json intercepted code from spotify to send credit card details to an additional server lol. There's hopefully guardrails to prevent this kind of thing.
I don't understand what's the big idea behind inline arrays syntax instead of just allowing fixed int whatever[10] take any type instead of just primitives
Microsoft was like, "Yeah we need this so we added it and made it public. Do you want to use it too? No? Okay well it's here if you change your mind" lol
Interceptors are interesting, can you override functions in dlls where you don't have the code? that would make injecting/changing functionality into existing applications very simple.
But. Only if they would be readonly. They are not, so you simply CAN’T provide the same functionality. You can only remove boilerplate by making your code unsafe.
@@user-qp8bt7gq4b Here is the way you do it readonly: class MyDataService(OtherService otherService) { private readonly OtherService otherService = otherService; and not only readonly, you can do anything you like as part of field initializers, e.g. checking for null or providing default value, or resolving actual value from a factory parameter: class MyDataService(OtherService otherService) { private readonly OtherService otherService = otherService ?? throw new ArgumentNullException(nameof(otherService)); You can set any visibility or define as a property. You can also use any field name conventions, e,g. _otherService.. Honestly, i see it is much better than trying to put in on a single line as part of the parameter.
Initializing arrays is nice, and lambda default params is great! But the constructor, and the using declaration stuff feels terrible, just seems like a bug-ridden land-mine. Not knowing what "new" does isn't a good thing, in my opinion.
@@MaxIzrin you've always been able to do "using X = Y" on most types, but for a few set of types - like for example ValueTuples as illustrated in this video - you couldn't. C# 12 patches that hole in the language specification, simplifying it.
"Because value types are copied by default." Isn't it true that everything is pass by value (by default) regardless of it being a struct or a reference type? For structs it copies the data and for references it does the same thing it just so happens that the value is the reference. Is that accurate?
I use var a lot too but there are a lot of places in my code where I can drop it like a method returning the value of a switch statement there I just had a thing today where I can remove the old array syntax which is nice. The AliasAnyType arguably one of the most anticipated feature for me personally.
I have mixed feelings about the new primary constructors. I would have preferred TypeScript's "parameter properties", where you write a constructor like `constructor(private readonly name: string)`, which in C# might have looked something like `public Person(private readonly string Name)`.
And would be nice if collection expreession would be interpreted automaticly as a list if the type is not specified rather than getting a conpiletime error
F*** it. Spread and interfaces for touples also. Interopability between anonymous classes and touples and defined types/interfaces. And Funcs and Actions can be used to mimic methods an interface or defined type expects
@@KasperDahlTangen why limit it to lists always. Needless heap allocations. They chose to delay natural types in order for improved performance later. Let's say you create a collection and only use it in that method; you'd get improved performance by using a span instead of a list in that context.
@@modernkennnern I’m not quite sure if I understood your question. All I meant in the second comment was that { var collection = [1,2,3] } shouldn’t give you a compile time error, and rather interpret it as { List collection = [1,2,3] } implicitly under the hood. In that sense you should still be able to explicitly write { Span collection = [1,2,3] } for instance without any issues
Great video, thank you! In my opinion, C# is a perfect language for write applications you like. Most of the features are nice to have only. So I don't know if I miss something in C# but on the other hand microsoft improve some little thinks to create a world where people knowing other languages can fast adapt to C#. Great work Microsoft
a comment down below.
😅😅.😅 1:39
So glad they simplified the way you create arrays.
Finally I got PHP like arrays!
Not having a target type is very annoying though, but it's prioritized for C# 13 so hopefully we'll get it sooner rather than later 😃
Yeah literally yesterday I tried to assign value to an int[] property in a constructor of an extension class for a pagination view model and the compiler did not like
PageSizes = {10, 20, 50};
Until I did “new int[] {10, 20, 50};” and I thought it was dumb. Quite happy it’s going to work now if I use square brackets.
You could already do int[] array = { 1, 2, 3 };
Nice python style
First version in years that I'm not super excited to upgrade. I will be upgrading ASAP anyway.
My biggest would be primary constructors, if I could specify them as read-only. Then I could remove a ton of boilerplate dependency injection constructors
Not being able to mark params as readonly is a bummer.
Exactly my thoughts
@@Meryovi another bummer is that they do not automagically convert into get-only properties as in records.
But then again, maybe it's time to convert our services to record types lol
I thought i understood primary constructors and didn't like them as well, but it's actually more flexible the way they are, if needed readonly:
class MyDataService(OtherService otherService)
{
private readonly OtherService otherService = otherService ?? throw new ArgumentNullException(nameof(otherService));
As you see, not only readonly, but also checked for nulls just in case, and all as part of field initializers.
I find it useful to simplify dependency injection, I think Nick didn't cover this point enough.
@@apokislyuknice way to do it
int[] values = { 1, 2, 3, 4, 5 };
has been around since 2001 as array initialization syntax, but now you can replace the {} by []. So that's pretty cool ^^.
it is similar to Python which can infer the type also. It looks like they are trying to add more syntactic sugar to make c# a more compact language, in your case, it is the same number of chars but using square brackets consistently is nice
As happens quite often, some features were taken from F#, where they've been part of the lang for a long time. I.e.: primary constructors, collection expressions, type aliases. Inline arrays are cool, they were part of MSIL for some time, but you couldn't easily use it.
And still, no language is even close to Rust in terms of declaring collections. It is so much easier and more flexible!
Type aliases are way more useful in F# as they are available across the project as a real type instead of acting as a local alias only.
Awesome video, thank you! I greatly appreciate the quality of life features and I'm sure libraries and code generators will make good use of the other features. I wonder if it's going to be practical to actually use inline arrays or if just using Spans is going to be enough for most of us. Looking forward to default constructors and collection expressions getting fully fleshed out in C#13 and 14.
Please do a video on .NET 8 Minimal API Native AOT on AWS lambda, using a database. There were a lot of improvements in that area compared to .NET 7. Thanks!
Overall this lang version seems a lot less interesting compared to the past 3 versions. Alias any type seems kinda neat, though it's unlikely I'll use it. Primary constructors have a weird implementation and I'm hesitant to treat them as safely usable in comparison to how they work in records. Interceptors are conceptually interesting, but I fear the code some hotshot programmer might write thinking they're clever trying to use a feature intended only for source generators. Collection expressions seem real nice though, easily the most useful thing on the list.
C# 8-11 were pretty interesting, adding using declaration statements, switch expressions, explicitly nullable reference types, records, advanced pattern matching, and all sorts of game-changing features. Not really seeing that this time around.
Still annoyed we don't have language-level union types or readonly locals yet.
Guess it's time to start naming my dictionaries Richard 😂
Imagine saying out loud "an API consumes a dic"😂
Use "dict" and make sure you pronounce that t. It's like "pianist" that way. 😉
😂😂
Seems to me most og the “features” we will get are performance improvements, and I’m totally fine with that, as all the frameworks are getting new and nice stuff
I died inside when I realized that for Interceptors, you have to specify the line number
Even the file path literal seems clunky. What happens if devs don’t have the same base path? Maybe there is some relative path option for it.
@@rex.minglaInterceptors are supposed to work with source generators. Devs should never have to write it by hand.
Source generators are run during compilation and will generate code based on the one that's being compiled, so the difference between machines won't matter - the in-memory generated code will be slightly different for each dev (different paths for example), but the compiled code will be the same - the new method will be called, instead of old one.
It's basically a feature that wants to replace reflection. Reflection is not only slow, but also only evaluated during runtime. Interceptors will be evaluated during compilation, and produce a runnable, already "rewritten" method call.
[ ] are square brackets. < > are angle brackets
I could see the alias feature being useful to pass around a tuple easier inside a class. Interceptors as well for test scenarios where there are no interfaces for the methods and it would be time consuming to refactor legacy code. But neither of those would push me to c# 12.
PrimaryConstructors => look like a poorly-controlled properties with public setters.
CollectionExpressions => cool stuff.
Interceptors => Beyond mocks, I don't see what new opportunities they offer.
All the rest => probably won't use, but thanks for keeping us up to date. 🙏
Interceptors could be very helpful for inserting log messages to where-ever necessary but without actually changing the code being intercepted, and you can easily remove the interceptor code later when logging messages are to be removed, once again no need to change the intercepted code.
As for how to specify the InterceptsLocation attribute with accurate file path / line / column info, I guess it would need some smart preprocessing code, but that still seems doable.
Interceptors basically allow you to do what only PostSharp can do without making changes on compiled code (the way PostSharp is doing this), so, imagine nuget, that will generate interceptors which will decorate your code with logging/caching/change tracking and so on by just simply adding one attribute to property/method/class. That's just easier way to do such things than modifying IL. It is also cleaner way of doing this because the code is there and you can debug it easily. But, again, this not for 99% of developers, this is for small percentage of devs who develop cool tooling libraries.
Primary constructors are only syntactic sugar and while I get they tried to achieve the same thing e.g. Typescript has, although I prefer the Typescript way actually.
I agree that in this form interceptors are useful but on niche scenarios, probably are design this way to avoid to abuse of them, anyway, file path, line and column.... looks VERY ugly to my eyes, do someone knows if the path can be at least relative? I don't want to check in code that works differently when someone clone it in a different path
@@dukefleed9525 why would you even ever manually write an interceptor? They are ugly because they can be - they will be always generated in some way or another, there is no reason to write them manually because if you can write something like that manually then why don't you just edit your method directly?
Primary constructors are private fields, not public properties. What do you mean?
As I understand, Code Generator + Interceptor will give us real AOP, so I will be able to remove PostSharp.
Interceptors should be extended to something that can be configurably invoked OnEnterMethod and OnExitMethod (sometimes useful for logging performance or tracing hard-to-.find bugs) and then can be disabled, when the issue is fixed.
Interceptors look like they could be useful for unit testing, although would be a pain to have to specify file, line and char pos.
Yeah I hope they will revise that again before considering it done. Right now it looks more like a half-arsed text replacement instruction to the compiler rather than proper interceptors
Thank you Nick for your wonderful videos. Is it possible to set attributes using record?
Thanks for the video, very simple and useful.
As for me, primary constructors are game-changer, but I don’t like it at all. I believe they add some readonly keyword for parameter in C#13. Because with current implementation you simply cannot replace private readonly fields with constructor parameters and restrict their re-assignment.
Collection Expressions - okay, cool, but it’s a pretty little change, so WHY is it cut??? I mean no support for Dictionary.
Interceptors are something for library developers, not for regular web devs I think.
Btw I waited the ‘field’ keyword for properties. To validate setter without manual creating of a backing field.
And discriminated unions, of course. Feels like the whole community is just waiting for them.
With DU, C# will enter the next echelon. Looking forward to it!!!
I wish that we had struct type collections. I have an instance where I need to do a deep copy on a structure of collections because the data needs to be transformed by multiple users and then merged back into a single structure.
you can stackalloc arrays into Spans though!
Empty what? 🤣🤣
Hey, you said about "void Test(ref readonly int age)" and "void Test(in int age)" - it is OK. But I think in order to understand difference between "ref readonly" and "in", you should say couple of words about "ref readonly int GetAge()". IMHO )))
Looking forward to the libraries built by interceptors! For my use, most likely collection initializers.
Saw no joke in the HelloWorld template and thought Nick is slipping. Then I watched the rest of the video :D
Oh SHIT I forgot! I did meet my 6,9 quota though
Going to use all the features here except Primary Constructors and interceptors. Though interceptors are also very interesting but they need to come out of experimental before we can use them.
As my fullstack colleague said, c# looks at the typescript and try to grab some features from it. But not so fast as someone want.
If I'm understanding this correctly, interceptors could be used by testing libraries to source generate efficient mocks for concrete types and maybe even extension methods?
Interceptors are for source generators, and source generators only. No sane programmer should write them manually in their codebases, otherwise it's a massive footgun.
@@gctypo2838 exactly. I've seen some people complaining they look ugly with those line and column syntax - for me this is even better: if they gonna break after every little change then no one would use them in purpose of manually modifying method. I mean, I don't know who would want to even do that when you can edit your method directly, but I'm glad that syntax is even more discouraging...
lol I'm using ref readonly due to interop code with c++ and its been amazing to help fight accidentally corrupting memory through that process.
This these last years Microsoft seems to be enabling themselves to make everything blazing fast and aot friendly so we can all run all our code extremely efficiently on arm server and laptops soon. Did they do anything to improve the experience of writing source generators? i find usecases for it very often, but it's often a bit crappy to work with, especially if you build and use it in the same solution.
Were UnsafeAccessors cut from .NET 8? I was really looking forward to what seemed to be essentially NativeAOT reflection.
From what I understand, that's not listed because it's a .NET feature not a C# feature, but I could be wrong
Collection expressions. IDK how I feel about primary constructors.
As far as many of the features being Microsoft-centric, they presumably make things better or more performant, so I'm all for them. I'd rather know about them then for them to be hidden.
Alias any type but not generics yet, if I understand correctly.
Generics was one of the first things I was looking to alias at some point.
One step at a time, I guess.
Primary ctors and collection expressions are ones I like and will be using a lot.
The alias is at a note-worthy second place.
For the other features I don't see an immedaite use case.
Year 2030, now you can use C# compiler to compile Scala code.
Still no `using IntDict = Dictionary` :(
What's the shortcut you used in 13:33 to increase the window size?
Ctrl + middle scroll
Regarding interceptors so this is mostly for people who have access to source code but don't want to edit it directly but they want to alternate it only for some specific cases that they uses?
The general "we" won't be using most of this features, but like you mentioned yourself: library authors besides Microsoft itself can use it now. That way we don't depend on the wits of Microsoft alone to get stuff which is possible with these features.
Another cut of semi-auto properties (field keyword) is really shame.
They have been advertising it since two years ago but not releasing it ... sad
they said they were wary of introducing a change that would break the code of the few developers who might have named a field "field". someone from the c# team said they were going to move ahead with it but provide a migration tool and they couldn't get it ready in time, partly because they had been considering several options
Not that many lifechanging features, well it's an LTS version so it makes sense. Feels more like they had to release something so they just used their internal features.
Hey! Please make more video like this! I really liked it!
I always love initializing my DICtionary
I think the new collection syntax, aliasing and the spread operators are the features I'll be using the most in the near future
for primary constructors that'd be great if we could have a syntax like public class myclass (readonly ParamType1 param1, readonly ParamType2 param2) { init {some init code} // class stuff}
I want to develop some optimizations for .NET using the interceptors
Thanks buddy! You're doing a good job.
C# finally catching up with VB.NETs collection literals... but no var allowed, while a dynamic Dim in VB works just fine.
For me C# 12 brings only 2 good features: Collection Expressions and default lambda parameters.
I know many ppl think that Primary Constructors are good one. But for me personally I don't like them at all. The reason is that it breaks naming conventions. I like the fact when I see _smthing it's private field of the class when reading code 200 lines below constructor declaration and if something without underscores - it's method argument or local variable.
Well, you still have the option of not using them at all if you like this weird naming convention of using underscores. And you can also name your params with _ in the primary constructors.
The only weird thing about this is your comment. I wrote the real reason why underscore makes sense.
@@alehkhantsevich113
I didn't said your explanation was wrong or bad, or that underscores did not make sense. I said they were weird (and for me, kinda annoying), and I don't like using them in general (and I really never perceived any more difficulty in just using only just the name). For me, most of the time you will not need to make these differentiations, you can get it working pretty well by just using camelCase for fields and PascalCase for properties, and when you are in a constructor you just this., it works and it is not weird.
For me it is a welcome change, I didn't like the _smthing since we have dropped the m_smthing already in an earlier phase. (coming from c++, yep I'm old cat 😅).
The compiler will warn you if you have a local or class parameter clash.
I strongly believe the _smthing only stayed, because people didn't like to use this.smthing in the c'tor init stage ...
Also, side note: if you cannot make up what a variable is, then perhaps your class is doing too much and is too big.
@@diadetediotedio6918
Yes, I apologize for the rude previous reply. I basically agree that it is possible to write this way. But for me, separating private and local makes sense. Looking through the code, I instantly see when other services are called (since they are usually from DI and therefore private with underscore). In general, I like the idea of Primary Constructors, but for me it makes the code harder to read. So, I'll most likely do this:
public class SomeClass(ISomeService someService, IAnotherService anotherService)
{
private readonly _someService = someService;
private readonly _anotherService = anotherService;
}
This does not remove the entire boilerplate, but it does not violate the conventions.
I wounded if the interceptor could be used to create some interesting ways to prevent data manipulation for hacking in games
“Hello everybody I’m naked”… I can’t unhear this 😂
5:00 deserves an extra like. 🤣
I think that the only new feature I actually dislike are primary constructors. Interceptors can be a great addition for libraries that want to add compile-time AOP functionality to an existing codebase.
I think primary constructors are a great way to reduce boilerplate code for dependency injection. Because for every service you inject you needed to declare a field, declare a constructor argument and assign the argument to the field. Now you only need to declare the service in the primary constructor and you are done.
So you reduce the code lines to one third, which may really increase readability the more services you need to inject.
@@maschyt I would agree with you if the generated fields were read-only and enforced non-null constraints. As they are, I don't find them convenient at all.
I don't find that this adds anything to the readability since you're not actually clarifying anything for the developer andare instead relying on compiler magic that doesn't make the dependencies apparent as actual dependencies. Instead, what you get is a reduced initialization list for mutable members.
Awesome video but I don't think I am going to use any of those LOL. Love your videos though. Thanks for all of the awesome content.
Interceptors are most exciting feature I think. I didn't notice that they put primary constructors like Kotlin. But why they don't copy full potential of this? :P
To me the current implementation seems so clunky that if you try to keep it working in evolving codebase, you spend more time hunting rows and characters than doing anything useful. It would be nice if it worked just marking the class and the method to intercept instead of manually trying to keep up with the changes.
They're thinking about it but couldn't find a solution they liked yet.
I mean why they don't merge class and records. Records behind the scene creates public properties and just add curly braces to add functions.
Besicly they have to extend the records 😜
Anyway.
How interceptors with file location will stores in git?
I wish they would implement semi-auto properties... my view models are cluttered with explicit backing fields since i must call OnPropertyChanged on the setter of public properties
I always wanted primary constructors like many languages did, finally it arrived
I would like to use the interceptors but without specifying the line and the path... maybe something like using the name of the class and the method that contains that call or something like that. It's very very risky to have these kind of "hardcoded" lines.
It's not risky if you only use the interceptors feature from a source generator, as intended by the designers of the feature.
I suspect someone will write a source generator for that soon after release...
What if I have 2 interceptors pointing at the same place? Is there a collision avoidance mechanism? Can it be either of them?
I'm guessing the first interceptor overwrites the code being intercepted, then the second interceptor overwrites it again so the second one actually takes the precedence. If this is true, then the whole interceptor mechanism will depend on the order of your codes being compiled. That could be a potential "interceptor hell".
Compiler error
Defining a type via using, it is perhaps similar to typedefs in other languages. Not sure if using defining a new type is a good thing. But sometimes you need a small class but dont want to declare it in an own file and having a possibility to straight up define a tuple combination for example as a type is handy.
That's what I was thinking, gets us one step closer to typedefs. Still far from it though...
Any performance improvements as compared to .NET 6 and .NET7?
Interceptor is just crazy, lol idk why they are releasing that.. so much potential for abuse.. let alone enormous debugging headaches for those who don't know it's being used!
Abuse how?
Rider just released support for interceptors this week to highlight lines being intercepted
@@prooseelike using a 3rd party library and intercepting code to change the behavior. Or being the 3rd party library, and knowing your consumers use other common 3rd party libraries and changing their behavior. Imagine if newtonsoft.json intercepted code from spotify to send credit card details to an additional server lol. There's hopefully guardrails to prevent this kind of thing.
i love that they just added interceptors from Angular haha
Interceptors looks like some new GOTO hell.
Interceptor feature is sick! However, I cannot find any application to it. Shrug
Awesome!
can i intercept a method that i have a attribute on and wrap it in a transaction and then do the original method ?
yes
Darn when I saw interceptors I thought it would be like Castle Proxy which I love.
I don't understand what's the big idea behind inline arrays syntax instead of just allowing fixed int whatever[10] take any type instead of just primitives
new Dic 😂😂😂
You’re awesome
That dict-tionary sounding like something else, is relatable 😂
Microsoft was like, "Yeah we need this so we added it and made it public. Do you want to use it too? No? Okay well it's here if you change your mind" lol
Awesome 👌
4:52 ...And this kids is why I call them 'dict' instead of 'dic'
Nicest feature array expressions
what do you think the use of interceptors are? cant people just make virtual methods instead?
Can one do an interceptor on another interceptor? :)
chapters would fit this video very good
Nothing I'll use, but good to see development of the language continues apace
Interceptors are interesting, can you override functions in dlls where you don't have the code? that would make injecting/changing functionality into existing applications very simple.
"where you don't have the code" Than how do you think you could provide the exact location of the functon in the source code?
Primary constructors actually make a lot of sense when used for DI, saving a lot of unnecessary boilerplate code.
But. Only if they would be readonly. They are not, so you simply CAN’T provide the same functionality. You can only remove boilerplate by making your code unsafe.
@@user-qp8bt7gq4b Here is the way you do it readonly:
class MyDataService(OtherService otherService)
{
private readonly OtherService otherService = otherService;
and not only readonly, you can do anything you like as part of field initializers, e.g. checking for null or providing default value, or resolving actual value from a factory parameter:
class MyDataService(OtherService otherService)
{
private readonly OtherService otherService = otherService ?? throw new ArgumentNullException(nameof(otherService));
You can set any visibility or define as a property. You can also use any field name conventions, e,g. _otherService..
Honestly, i see it is much better than trying to put in on a single line as part of the parameter.
Initializing arrays is nice, and lambda default params is great!
But the constructor, and the using declaration stuff feels terrible, just seems like a bug-ridden land-mine.
Not knowing what "new" does isn't a good thing, in my opinion.
But you surely know what 'new' does, it is not masked. The usings are very transparent
The using declarative change was for all intents and purposes a bug fix to the language
@@modernkennnern How so? I don't understand what you mean by that.
@@MaxIzrin you've always been able to do "using X = Y" on most types, but for a few set of types - like for example ValueTuples as illustrated in this video - you couldn't. C# 12 patches that hole in the language specification, simplifying it.
@@modernkennnern I didn't know that existed.
using X = Y seems sloppy to me.
"Because value types are copied by default."
Isn't it true that everything is pass by value (by default) regardless of it being a struct or a reference type? For structs it copies the data and for references it does the same thing it just so happens that the value is the reference. Is that accurate?
yes
Yeah but when we say that the value is copied we referred to the actual object not the reference
CollectionExpressions somewhat nice, but I prefer using var so probably won't use these. Nothing else here I'm likely to use.
I use var a lot too but there are a lot of places in my code where I can drop it like a method returning the value of a switch statement there I just had a thing today where I can remove the old array syntax which is nice. The AliasAnyType arguably one of the most anticipated feature for me personally.
4:53 😅
I have mixed feelings about the new primary constructors. I would have preferred TypeScript's "parameter properties", where you write a constructor like `constructor(private readonly name: string)`, which in C# might have looked something like `public Person(private readonly string Name)`.
Would be cool with Dictionary and HashSet expressions (like in python) also
And would be nice if collection expreession would be interpreted automaticly as a list if the type is not specified rather than getting a conpiletime error
And a spread operation for anonymous types. And the ability for anonymous types to inherit interfaces
F*** it. Spread and interfaces for touples also. Interopability between anonymous classes and touples and defined types/interfaces. And Funcs and Actions can be used to mimic methods an interface or defined type expects
@@KasperDahlTangen why limit it to lists always. Needless heap allocations. They chose to delay natural types in order for improved performance later. Let's say you create a collection and only use it in that method; you'd get improved performance by using a span instead of a list in that context.
@@modernkennnern I’m not quite sure if I understood your question. All I meant in the second comment was that { var collection = [1,2,3] } shouldn’t give you a compile time error, and rather interpret it as { List collection = [1,2,3] } implicitly under the hood. In that sense you should still be able to explicitly write { Span collection = [1,2,3] } for instance without any issues
New feature request for C# 13 on behalf of Nick Chapsas: spread operator for keywords.
Example: `Dic…tionary`
I snorted my coffee.. son of a.. hahah
I see the struggle of moving from Rider to VS 😬
I was excited to share this video with my coworkers until the dick jokes. I don't need to get in trouble with HR. Thanks for the video though!
Great video, thank you!
In my opinion, C# is a perfect language for write applications you like.
Most of the features are nice to have only. So I don't know if I miss something in C# but on the other hand microsoft improve some little thinks to create a world where people knowing other languages can fast adapt to C#. Great work Microsoft
С# is becoming typescript
Why would anyone hate being able to define an array with `[1, 2, 3]` versus `new int[] { 1, 2, 3 }` lol
some people hate things just for no reason
I like the way you talk. Fast. Noice!
I fail to see where you would ever wanna use Interceptors?
I only see myself using array definitions this new way...
New *D I C*
...tionary 😂
Man there is a lot of ways to do the same thing, this is gonna confuse a lot of junior and senior devs!
"The DIC" xD