The New Way of Calling Your Code in .NET 8 Is INSANE

Sdílet
Vložit
  • čas přidán 20. 09. 2023
  • Use code DOCKER15 and get 15% off the brand new Docker course on Dometrain: dometrain.com/course/from-zer...
    Become a Patreon and get source code access: / nickchapsas
    Hello, everybody, I'm Nick, and in this video, I will introduce you to an extremely powerful feature added in .NET 8 called the UnsafeAccessor. This feature aims to replace reflection on many levels and provide compile time performance but also allow for NativeAOT support.
    Subscribe to Dan: @danclarkeuk
    Workshops: bit.ly/nickworkshops
    Don't forget to comment, like and subscribe :)
    Social Media:
    Follow me on GitHub: bit.ly/ChapsasGitHub
    Follow me on Twitter: bit.ly/ChapsasTwitter
    Connect on LinkedIn: bit.ly/ChapsasLinkedIn
    Keep coding merch: keepcoding.shop
    #csharp #dotnet

Komentáře • 534

  • @gustavo-santos-dev
    @gustavo-santos-dev Před 7 měsíci +396

    This is probably a crime in +50 countries.

    • @dextergandini
      @dextergandini Před 7 měsíci +13

      It is also forbidden by Genebra convension!

    • @fakhrulhilal
      @fakhrulhilal Před 7 měsíci +3

      It means we can do anything what we want to be in any framework we’re using😂

    • @mattkins99
      @mattkins99 Před 7 měsíci +8

      OMG I don’t want to support this when I find it 10 years from now in a class that starts with the comment // Don’t touch, thar be dragons

    • @adambelos2157
      @adambelos2157 Před 7 měsíci +1

      Mama i am a criminal...

  • @clementdato6328
    @clementdato6328 Před 7 měsíci +293

    Finally, I can change the value of a static private read only field of a class in some other person’s code so that when another person use my library they will learn to read through all code before actually believing something is read only and private.

    • @Spid88PL
      @Spid88PL Před 7 měsíci +20

      INSANE

    • @fifty-plus
      @fifty-plus Před 7 měsíci +22

      Make sure your comments are totally off base too 😉

    • @IvanRandomDude
      @IvanRandomDude Před 7 měsíci +17

      Truly a gAmE-cHaNgEr

    • @erynmacdonald
      @erynmacdonald Před 7 měsíci +5

      WARNING *sarcasm* DETECTED

    • @phizc
      @phizc Před 7 měsíci +11

      You could have done that in previous versions of .NET too. It's just become a more pleasant coding experience to do so now 😛.

  • @KieranFoot
    @KieranFoot Před 7 měsíci +178

    I'm guessing this is part of getting rid of reflection for AOT...

    • @peanutcelery
      @peanutcelery Před 7 měsíci +11

      Yeah a lot is being set up for AOT like minimal apis.
      I feel like .NET 8 was the setup to make AOT more common for the next .NET versions.

    • @z0nx
      @z0nx Před 7 měsíci +4

      Interesting.. Is it because this can be done at compile time or something?

    • @renauddanniau676
      @renauddanniau676 Před 7 měsíci +3

      @@z0nx Exactly, I think they will combine this with source generator to generate code at compile time and not during runtime ;).

    • @RiversJ
      @RiversJ Před 7 měsíci +2

      Yup Native AOT plays a big role in .Net 8

    • @davidfowl
      @davidfowl Před 7 měsíci

      @@peanutcelerySomebody has been paying attention 🫡

  • @woocaschnowak
    @woocaschnowak Před 7 měsíci +31

    With great power comes great responsibility.
    Don't use your power to change static readonly fields :D

  • @mrsajjad30
    @mrsajjad30 Před 7 měsíci +9

    For this feature I must say "With greater power comes greater responsibility". Excellent demonstration. Thank you Nick.

  • @DennisFazekas
    @DennisFazekas Před 7 měsíci +69

    This seems really handy for unit testing, but I have concerns about using it in other contexts. As someone who writes a lot of infrastructure code, I find it crucial to restrict developers from accessing certain parts of the code.

    • @Kerbiter
      @Kerbiter Před 7 měsíci +14

      Sure, except when stubborn library devs only design something in the way they see consumers want, not what the consumers really want, and won't change anything and/or it's a lot of hassle to make them change, or it's just simply the way they're building their library.

    • @parcanapp1193
      @parcanapp1193 Před 7 měsíci

      nuke with mandatory .nuke folder immediately came to mind. I use .config for all configuration, and now have an extra folder. I will now go back and check if it is a static readonly as opposed to const by any chance. @@Kerbiter

    • @ehudv9276
      @ehudv9276 Před 7 měsíci +2

      Yes. haven't thought of that. thats actually a good use case.

    • @DennisFazekas
      @DennisFazekas Před 7 měsíci +1

      ​@@KerbiterI totally get where you're coming from! If the devs aren't providing what's really needed, then there might be a bigger issue going on. I'm all about sharing knowledge and having open code reviews. That way, everyone knows what's going on in the code and if any tweaks are needed, I'm more than happy to make them. I'd rather work together like this than have people go around my code, which could create headaches down the road. 😊

    • @TheRavenCoder
      @TheRavenCoder Před 7 měsíci +1

      Unit tests are definitely the most obvious use case. I've used reflection before on unit tests and it's a bit messy. I didn't want to make the methods public, because they should not be used directly by the application, but the logic needed to be tested as mistakes could cost the company millions of dollars. This feature would've cleaned that code up a bit.

  • @ElmoTheAtheistPuppet
    @ElmoTheAtheistPuppet Před 7 měsíci +11

    "The value is Nick" - You are the value mate appreciate your work

  • @PereViader
    @PereViader Před 7 měsíci +37

    Compile time performance is the best part of this ❤

    • @parlor3115
      @parlor3115 Před 7 měsíci +2

      I don't think it matters since you're mostly going to use this in tests where you run your methods a few dozen times each at most.

    • @BillyBraga
      @BillyBraga Před 7 měsíci

      You can probably get the same perf with reflection if you compile lambda expressions

    • @neppe4047
      @neppe4047 Před 7 měsíci

      ​@@BillyBragayeah I think he did something like that in another video, not sure why didn't in this one

  • @dhochee
    @dhochee Před 7 měsíci +11

    "It's a pain ... where you don't want to be painful" is hilarious. I'm gonna steal that. Regarding the main topic ... I've used reflection to access private members before, but only when it was an abstraction designed to handle cases where you don't know the member names at design-time. This new feature doesn't help with that, so it's just ignoring the original developer's intentions. I suppose if you absolutely need to do it, having it be declarative with "Unsafe" in the keyword is better than hiding it behind reflection. Also much faster, of course, as you observed.

  • @OlofLagerkvist
    @OlofLagerkvist Před 7 měsíci +17

    Great video, but I think one additional way of doing it should have been in the benchmark. That is, getting the MethodInfo object through reflection, then build a Func (or similar) delegate of it and then cache that delegate and call that instead of using the dynamic Invoke() method each time. Many years ago I changed that in lots of places in a code base that had a lot of reflection and improved performance a lot. The question now is how that compares to this new way of doing it!

    • @TheMonk72
      @TheMonk72 Před 7 měsíci +4

      I routinely use LINQ lambda expressions to build funcs for methods I'm accessing via reflection because they're faster than invoking a MethodInfo. And they work well with generics. Would love to see a speed comparison with this.

  • @Demonata1223
    @Demonata1223 Před 7 měsíci +7

    I had a very good use case for this recently. We use private constructors for some of our objects because we want to tightly control how new things are made. But that inadvertently effected serialization. System.Text.Json cannot serialize with private constructors. Newtonsoft can. Thats an example of when something is private. but you may still need to access it externally in some situations. I dont want to open up something thats private in the code base but i still want to be able to serialize/deserialize it properly.

  • @mindstyler
    @mindstyler Před 7 měsíci +50

    Will we get a dedicated in-depth video about the volatile keyword at some point? It's been 2 years already since you covered it briefly the last time.

    • @ludwintor4986
      @ludwintor4986 Před 7 měsíci

      absolutely agree

    • @thatcreole9913
      @thatcreole9913 Před 7 měsíci

      👀

    • @tarsala1995
      @tarsala1995 Před 7 měsíci +3

      Ideally with some multithreaded examples

    • @IronJmo
      @IronJmo Před 7 měsíci

      It's funny seeing a comment about this because I just used this recently on a project for the first time.

    • @renauddanniau676
      @renauddanniau676 Před 7 měsíci +3

      Volatile is not really complex, you should read what MSDN has on it and you will easily understand how to use it :).
      You need to have a good understanding about how multithreading works and what are L1, L2 and L3 caches.

  • @BillyBraga
    @BillyBraga Před 7 měsíci +46

    Personally, I think a valid use case is when you are using a nuget package that doesn't expose the functionality or configuration required for functioning properly in your app.

    • @MayronDev
      @MayronDev Před 7 měsíci +6

      I've had this problem a number of times. One example has been when a package is serializing data using its own internal serializer and does not provide any configable settings or callbacks. This has prevented me from using custom logic required by an app I was working on. It's good to open up an issue on their pull request but that could delay your code from going live or completely block you if they choose to ignore your issue for years.

    • @phw1009
      @phw1009 Před 7 měsíci +1

      That will be very useful, especially on nuget packages those not maintained anymore.

    • @noon9548
      @noon9548 Před 7 měsíci +1

      ​@@phw1009how would you improve the packages that not maintained anymore? Do you mean changing inners of packages or extending functionality?

    • @davidmartensson273
      @davidmartensson273 Před 7 měsíci

      @@noon9548 It could be enough to be able to access some internals to be able to work around a problem.

  • @DivingDeveloper
    @DivingDeveloper Před 7 měsíci +1

    Thank you for this, Nick. Concise and helpful as always. I can see the use - as you demonstrated - clean and fast running, if potentially dangerous code.

  • @ristopaasivirta9770
    @ristopaasivirta9770 Před 7 měsíci +15

    Who would win: ten years of SOLID principles vs one unsafe boi?

  • @markhenderson5283
    @markhenderson5283 Před 7 měsíci +14

    My experience with code using refection is it is either doing something really powerful and useful or something stupid. It is usually always the second one.

    • @anonimxwz
      @anonimxwz Před 7 měsíci +3

      Imo reflection is useful for testing private things or to call generic methods with multiples types.

  • @benjaminclehmann
    @benjaminclehmann Před 7 měsíci +18

    I'm wondering if this is safer, for example if the method doesn't exist or the signature is incompatible would this fail at compile-time? Because in that case this seems like a massive win, especially for those who are committing these types of sins on code they don't have access to.

    • @marton-vincze
      @marton-vincze Před 7 měsíci +2

      I highly doubt that compile time checking for private field are possible, the input parameter for the accessor can be typed as an interface or an abstract class where some implementations will possibly have this method/field

  • @PeteSauerbier
    @PeteSauerbier Před 7 měsíci +2

    Can this be done with extensions as well?

  • @Tolg
    @Tolg Před 7 měsíci +7

    This is fantastic! I think it will allow for me to make more things private, and still have them testable. I’ve had so many cases where I couldn’t make something private because I needed to expose to my testing framework.

    • @filadog
      @filadog Před 7 měsíci

      @@jkdmyrs how do you test private async event handlers on UI, say WinForms? This will be handy in such cases when in memory UI testing is required. Faking button clicks and such. In my place we use MVP pattern for UI code extensively and have a custom framework for testing presenters with specflow. It's real nice to work with, you just say User clicks button "Download". And reflection magic calls private event handler for that button in the presenter. Might use this feature in the future instead.

    • @jangohemmes352
      @jangohemmes352 Před 7 měsíci +1

      The tests are screaming at you that you aren't designing your code and tests right. NEVER test internals. They are internal so that they are free to change without breaking tests

    • @Tolg
      @Tolg Před 7 měsíci +1

      I know this is a contentious topic and I don't intend to start a, how to correctly write and test your code correctly war, here in Nick's video comments. In general, I do agree with you. You should only need to test your public interfaces. However, even for backend code, sometimes in libraries there is good reason unit test certain methods such as utility methods which may have flexibility extended to them to address future needs or test integration code that is not conducive to easily being mocked out without leaking abstraction. You could abstract out such code, mark things as internal and add InternalsVisibleTo to your library to allow its testability, but I feel that modifying a base library in such a way just to be able to test, is not exactly proper either. So I will certainly experiment with this new capability to help improve my code and my code's testability.

    • @paulcarlton598
      @paulcarlton598 Před 6 měsíci +1

      I've dealt with this too, to get around it, I'll create a testing interface for the object only to expose the needed methods through that testing interface only. It's a way to keep the intent of the contract while being able to cast to a testing interface for the unit test suite. This functionality though actually gets rid of that need which I definitely appreciate, because in all honesty I feel like my workaround, although stays clean, is kind of a workaround.

  • @metaltyphoon
    @metaltyphoon Před 7 měsíci +4

    If all the reflection based methods on the BLC gets to use this feature under the hood, then most reflection code can be AOT compatible

    • @Alex-ABPerson
      @Alex-ABPerson Před 7 měsíci

      That doesn't really work because the parameters on the attributes need to be _constant_ - while reflection obviously only knows what strings it's getting when it's executed.

  • @TheRicherthanyouguy
    @TheRicherthanyouguy Před 7 měsíci +33

    I’m so mixed on this I can definitely see value from a unit testing perspective because there are codebases that have private methods that really have too much going to be private. Which really just needed to be rewritten. I strongly dislike accessing things that should be private purposefully but I also love the performance boost

    • @leerothman2715
      @leerothman2715 Před 5 měsíci +1

      I can see it being useful for testing DDD classes that have immutable properties on a test fixture setup. Not sure I’d use it for executing private methods though. Unit tests should be decoupled from the implementation of the subject under test.

    • @TheRicherthanyouguy
      @TheRicherthanyouguy Před 5 měsíci

      @@leerothman2715 agreed I think we are all mostly on the same page of this can be useful but only in rare or extreme situations.

  • @kelton5020
    @kelton5020 Před 7 měsíci +1

    I dig it. I think this makes a lot of sense for them to iterate and improve all aspects of the ecosystem, instead of just neglecting the unsightly parts.

  •  Před 7 měsíci +14

    My prediction is that in a few years c# documentation will be bigger than the bible. The fields and classes will have some 15 keywords to define them. I'm now waiting for AI related keywords to brought into the language. 🎉🎉

    • @peanutcelery
      @peanutcelery Před 7 měsíci +4

      Right there are so many methods and properties added every update. I came from Java and I’m like damn this language updates slow but then I came to C#…

    • @solovoypasando
      @solovoypasando Před 7 měsíci +1

      @@peanutcelery c# is moving way too fast now I understand why Java is more popular, there's no way to keep up with C# and have a life at the same time

    • @cgeorgescu72
      @cgeorgescu72 Před 7 měsíci

      Yeah, it will be like:
      [ChatGptImplemented]
      public partial int GetWeatherForCity(string city){}
      and will automatically fill the method body for you at build time. And will write a personalised resignation letter as well.

    • @Yudikab
      @Yudikab Před 6 měsíci

      @@solovoypasando hell yaa.i moving to open source soon enought

  • @PeterOeC
    @PeterOeC Před 7 měsíci +1

    My mind was blown once, when my colleague showed me how to make a self-updating const in JavaScript.
    Now you're showing me that private properties can be changed from outside classes 🤯
    I need to sit down

  • @jcmorin2007
    @jcmorin2007 Před 7 měsíci

    I would like to point that in my code I'm using reflection for calling public type in some cases where I don't have instance of the class, but just the type. (static fields for instance)

  • @JackoCribbo
    @JackoCribbo Před 7 měsíci

    Nick's on a mission to one up each .Net 8 video with something having even more terrifying possibilities.

  • @fredericbrown8871
    @fredericbrown8871 Před 7 měsíci +1

    I think it can help write more robust and cleaner code when you have to use reflection anyway (assuming type safety is enforced for the extern methods of the caller class). However I would be warry of accessing, let alone setting (especially if read only), private members. I guess there might be edge cases I'm not thinking about that justify it, but unless it's for the purpose of diagnostic it feels antithetical to encapsulation and the safety it provides and looks like looking for trouble to me.

  • @gliaMe
    @gliaMe Před 7 měsíci

    Regarding the code mess of the reflection solution, I had an extension method for the reflection calls in a project. Worked for any property of any class.

  • @F1nalspace
    @F1nalspace Před 7 měsíci

    This is awesome! I had some cases in the past, where i had to use reflection to get a private value out - and it was very slow.
    Great that there is now a tool for doing the same thing - and more, for compile time performance. I like it ;-)
    Thanks for sharing.

  • @99aabbccddeeff
    @99aabbccddeeff Před 7 měsíci

    It's really helpful feature in some rare cases. Thanks for the sharing.

  • @IllidanS4
    @IllidanS4 Před 7 měsíci +2

    I love nothing more than ways to break guarantees in a runtime (but readonly fields were modifiable before using... ways). Anyway I feel your performance benchmark is missing the case when you call the method via a delegate, as that is the "proper" way of binding to it (as opposed as Invoke having to perform argument unboxing and whatnot before getting to the method). Perhaps throw a function pointer into the mix as well.

  • @anm3037
    @anm3037 Před 7 měsíci +1

    The first place I will use it is to grab the array under List

    • @mbenoni7397
      @mbenoni7397 Před 7 měsíci

      You can already do that with CollectionsMarshal.AsSpan()

  • @Dimencia
    @Dimencia Před 7 měsíci +13

    This isn't the worst thing you can do in C#; most of a dev's job is finding that balance between terribleness and efficiency. Always nice to have more tools in the kit

    • @ForeverZer0
      @ForeverZer0 Před 7 měsíci +3

      I agree. More power is never a bad thing, so long as their is sufficient barriers in place from doing it accidentally. As long as the user must do "unsafe" (I hate this term) explicitly, there is nothing wrong with a language supporting it.

    • @memes_gbc674
      @memes_gbc674 Před 7 měsíci +1

      a wise man named terry davis has mentioned this many times

    • @ForeverZer0
      @ForeverZer0 Před 7 měsíci

      @@memes_gbc674 TempleOS was glorious: an entire OS where everything occurred in kernel-space. The "muh safety" cult would lose their minds if they knew.

  • @modernkennnern
    @modernkennnern Před 7 měsíci +4

    How does this interact with string.Empty? I remember reading that it used to be changeable but they fixed that. Does this reintroduce the possibility of changing it? It's a static readonly after all

    • @nickchapsas
      @nickchapsas  Před 7 měsíci +8

      I tried. You can't set its value since its marked as a JIT intrinsict

    • @modernkennnern
      @modernkennnern Před 7 měsíci

      @@nickchapsas that's great

  • @the-niker
    @the-niker Před 7 měsíci +4

    Ooof.. I sense a major rewrite in my future. How is the compatibility with older .NET7 or 4.8, can you multitarget to those and compile or do you have to #if NET8_0_OR_GREATER and write the reflection version anyway?

    • @Daniel15au
      @Daniel15au Před 7 měsíci

      This is likely a compile-time feature, meaning it should be possible to compile to a .NET 4.8 target. I haven't tried it though. It'd likely just compile to the old-style reflection code when targeting older runtimes.

  • @bluesillybeard
    @bluesillybeard Před 5 měsíci

    Surprisingly often I find myself needing to call a method that isn't in the public API of a library.
    It's usually a method that should be public, but the creator of the library thought otherwise or just accidentally wrote the wrong keyword.
    Using this will be a lot easier than using reflection, so I consider it a bonus. Plus, I imagine it works with AOT too (since it links at compile time) to make reflection-like things possible for anyone using AOT.

  • @ja_mcito
    @ja_mcito Před 7 měsíci +6

    Maybe it's just for use in highly optimized libraries

    • @SimpMcSimpy
      @SimpMcSimpy Před 7 měsíci +3

      Perf is only one reason but no the main one. It's mostly for AoT and code trimming scenarios where reflection can't figure out what to take out or what to leave.

    • @Daniel15au
      @Daniel15au Před 7 měsíci

      ​@@SimpMcSimpyThe property name is still a string though, rather than a static reference... Will this help with AoT?

  • @MrDragnil
    @MrDragnil Před 7 měsíci +1

    Could be useful for certain testing situations as well.

  • @RobinJohannesson
    @RobinJohannesson Před 7 měsíci +2

    That is awesome!
    But how does it work underneath? How do UnsafeAccessor attribute know what type I am using? And what happens if I have two instances of the same class, but with different values? And what happens if there is multiple functions with the same name?

    • @TheMonk72
      @TheMonk72 Před 7 měsíci

      My guess is that the "extern" keyword is doing all the heavy lifting here. In previous versions of the language it creates code to call a library method. Looks like they did something similar here except the compiler just inserts code to call/reference things you normally wouldn't have access to.

    • @GumbootMan
      @GumbootMan Před 7 měsíci +1

      @@TheMonk72 Good guess, but nope, the compiler is not involved. Rather, this feature is implemented in the JIT -- it sees the [UnsafeAccessor] attribute and generates the appropriate IL to call the method or get a reference to the field. If the target method/field is not found, then it generates code to throw an exception instead. (This actually explains why getting the name wrong is not a compiler error -- can't trigger a compiler error if the compiler is not involved!)

  • @jc_alpha
    @jc_alpha Před 7 měsíci

    4:17 “It doesn’t take a genius to understand that having to write something like this *every single time* is very very tedious”
    You make it sound like this is the first thing we do every morning before standup.

  • @lordmetzgermeister
    @lordmetzgermeister Před 7 měsíci

    I assumed the compiler generates the references at compile time, but according to documentation the implementation is generated by the runtime.
    How the heck is it so fast then?

  • @yessenzhol8989
    @yessenzhol8989 Před 7 měsíci +20

    .NET developers before:
    C++ is unsafe, so we invented delegates in C#
    .NET developers now:
    Now we can call functions in unsafe manner as C++
    Great job!🤣🤣🤣

    • @ebubekircagrsen7824
      @ebubekircagrsen7824 Před 7 měsíci

      This is gentlemans, worst way to criticize

    • @jean-michelgilbert8136
      @jean-michelgilbert8136 Před 7 měsíci

      LOL. This is worse than any bad pattern in C++. It lets any class call and modify private methods and fields easily. The next time I see a C# developer ranting about the friend keyword in C++, I'm countering with this 🤣

    • @JacobSnover
      @JacobSnover Před 7 měsíci

      C# has had unsafe keyword since the start, they avoid it by default to save devs from tedious operations and to be 'more safe', but it's always been there. C# is used in different applications than c++ making unmanaged code much less needed.

    • @SimpMcSimpy
      @SimpMcSimpy Před 7 měsíci

      @@jean-michelgilbert8136
      This is expected when you are redesigning JIT compiler to support AoT.
      They run into wall with reflection and trimming.

    • @KurtVanBever
      @KurtVanBever Před 7 měsíci

      Your observation is correct but I think you are drawing the wrong conclusion. Remember that the type safety was not put in place because type safety is a wonderful thing in and of itself. The main purpose behind it was the almighty dollar: type safety results in fewer bugs, so development goes faster and as you know time is money.
      As said in the video MS made this feature because there are some solid use-cases for it. You could take the perspective that they are running back to C++, and in some sense that is exactly what they are doing. But the fact is that this is all part of an ongoing, more elaborate, evolution. In the same category you will find for example CYTHON (Python running back to C++).
      I think we should get used to the arrival of new or renewed languages that will put the best of both worlds together. Transition will be like going from an automatic car to driving a stick. I think it will benefit all of us.

  • @qub1n
    @qub1n Před 7 měsíci

    Is compiler able to detect missing method in compile time? The most pain to me on reflection is maintaining someone's else code based on reflection.

  • @DemoBytom
    @DemoBytom Před 6 měsíci +1

    This is gonna be used in source generators so much, and I'm 99% sure that was the main reason the feature got introduced to the runtime.
    In pre .NET 8, to extend a class with source generator you have to make the class partial, and then have the generator create the extension in the class' partial.
    With this feature we will be able to extend non partial classes, just as if they were, without bloating said class with the generated methods, you might NOT need outside of what the generated code was for. This is an amazing, though very dangerous, thing indeed.

  • @blaaaaaaaaaaaaargh
    @blaaaaaaaaaaaaargh Před 7 měsíci

    Will this work in external code? Ie 3rd party plugins you'd otherwise have to have a license for and skip their license checks?

  • @B1aQQ
    @B1aQQ Před 7 měsíci +2

    So did they add it with direct use in mind, or is it mainly for source generators?

    • @nickchapsas
      @nickchapsas  Před 7 měsíci +4

      It's mainly for NativeAOT

    • @GumbootMan
      @GumbootMan Před 7 měsíci

      Yes, it's primarily for source generators. This feature is extremely fragile when used manually (since it depends on the class internals), but when used in a source generator the UnsafeAccessor calls can be tailored to exactly match the class internals, whatever they might be. For example, it could be used in a source generator to serialize all the private members of some arbitrary class.

  • @kconfesor
    @kconfesor Před 7 měsíci +3

    This will be really useful for mocking libraries and testing 😊

    • @cgeorgescu72
      @cgeorgescu72 Před 7 měsíci

      Will be really useful for messing up with the juniors in your team: overwrite their readonly int=1 then let them struggle a day to understand why it doesn't pass the test.

  • @Noceo
    @Noceo Před 7 měsíci +1

    This is gonna result in some fun code bases to maintain in 3-5 years from now...
    (I do see a case for debugging, learning and fiddling around with stuff, but never for production code)

  • @nocturne6320
    @nocturne6320 Před 7 měsíci +3

    This is an amazing feature, only a shame that you haven't included a benchmark for a compiled lambda as well.

    • @AlwaresHUN
      @AlwaresHUN Před 7 měsíci +2

      Its great till my colleagues don't know about it :D

  • @rade6063
    @rade6063 Před 7 měsíci

    Great video! Quick question are you using some kind of theme for rider or is this new UI?

    • @mikkirefur
      @mikkirefur Před 7 měsíci

      that looks VS Code to me. but just a guess

    • @chris-pee
      @chris-pee Před 7 měsíci

      @@mikkirefur this hardly looks like VS Code, and you can see Rider's logo in the corner. It's their new, redesigned UI

    • @rade6063
      @rade6063 Před 7 měsíci

      @@chris-pee But new UI doesnt have bottom tabs or at least it didnt have them and there is no text like terminal or git its just icons as far as i am aware

    • @mikkirefur
      @mikkirefur Před 7 měsíci

      @@chris-pee thank you. i have been relegated to more devops and mgmt work lately.

  • @andersborum9267
    @andersborum9267 Před 7 měsíci

    It provides the same end result for the developer, but comes with a significant perf improvement; setting protected members using reflection has been a thing for years using reflection.

  • @dadcraft9949
    @dadcraft9949 Před 7 měsíci +5

    Did you know that if you cache an open instance delegate instead of the MethodInfo you can get the same performance with "reflection" (actually with a delegate) that you see with the UnsafeAccessor? All you have to do is call CreateDelegate with a type argument that accepts the target type as a parameter, in this case Func.
    var testInstance = new Example();
    var openDelegate =
    typeof(Example)
    .GetMethod("Method",
    System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
    .CreateDelegate(null);
    var name = openDelegate(testInstance);

    • @nickchapsas
      @nickchapsas  Před 7 měsíci +8

      I do, and I have made a video on it. It's not quite the same performance and it can't be JITed the same way either plus its usecases are quite more limited, but it's very close

    • @SimpMcSimpy
      @SimpMcSimpy Před 7 měsíci +8

      That is not the point of this feature. This was added for AoT compilation. Reflection in general doesn't work well with AoT, this is sort of quick patch for such cases.

    • @dadcraft9949
      @dadcraft9949 Před 7 měsíci

      @@SimpMcSimpy yeah I'm not recommending anyone should choose this approach (for anything ever, really). I just think it's worth knowing about if you are stuck with legacy reflection code and need to optimise it. It's odd to me how many performance focussed articles and videos will measure reflection performance without touching on how trivial it is to boost the performance to match a virtual method call in many situations.

    • @SimpMcSimpy
      @SimpMcSimpy Před 7 měsíci

      @@dadcraft9949
      You are correct. I saw that in many articles :)

    • @DynamicalisBlue
      @DynamicalisBlue Před 7 dny +1

      Thanks for this. I'm using cached reflection for something at the moment. I also thought of creating a delegate for performance purposes, or at least some reference to an actual native method but I couldn't figure out how to do it. I didn't know there was a method called CreateDelegate this entire time.

  • @knifekitty_ls
    @knifekitty_ls Před 7 měsíci

    can you get static field of Method() and replace it with new Func that has completely different implementation?

  • @aispweelun
    @aispweelun Před 7 měsíci

    How are you able to set the value of Field by calling the function and then assign 'John' to it? Could someone explain this?

    • @nickchapsas
      @nickchapsas  Před 7 měsíci +2

      Because it’s a reference due to the use of the ref keyword

    • @aispweelun
      @aispweelun Před 7 měsíci

      @@nickchapsas i see. So having the ref keyword would allow the function achieve the same purpose as something like propertyInfo.SetValue(Example, "Nick")?

  • @TohidAzizi
    @TohidAzizi Před 5 měsíci

    Nice! it is something that I probably only use in my unit tests!

  • @AlFasGD
    @AlFasGD Před 7 měsíci +3

    I got ill just by hearing your voice, get well soon Nick

    • @nickchapsas
      @nickchapsas  Před 7 měsíci +1

      Damn I didn't know people would notice! Thanks ❤

  • @user-dq7vo6dy7g
    @user-dq7vo6dy7g Před 7 měsíci +1

    This can help to fit or fix problems in 3rd party components when you have access to the source code, but you don't want to build your own version just to change that one read only value to activate tls or something like that.

  • @Andrei15193
    @Andrei15193 Před 7 měsíci

    Had this issue with the Azure Table Storage stub I was working on, there was no public constructor for creating a result set. I had to use reflection to get an instance although it is only a DTO. Very annoying as everything else was accessible.

  • @rreiter
    @rreiter Před 7 měsíci +1

    5:50 Yes, I want to easily access private members that I shouldn't be using, and, oh, 11:00 so much for readonly, ... this will be fun (especially if it is performant, lol). I wish the Law worked like this: "Yes, Officer, I broke this law, but I said a special word when I was doing the bad act, so that makes it ok and it's all good."

  • @Misteribel
    @Misteribel Před 7 měsíci

    Is this a compiler feature or a dotnet feature? That is, does it get desugared by C#, or does it work with any language?
    PS reflection is usually used with names or other member or class features nor known at compile time. Once you know it statically, like in your example, you can use existing tricks to make it as fast (cache and use delegate) as a normal method call. Of course, this approach makes certain use cases simpler, but does not replace reflection.

  • @peryvindhavelsrud590
    @peryvindhavelsrud590 Před 7 měsíci +1

    Have had to access internal methods from external APIs previously, this would have made that experience easier. Looks a lot like calling external APIs in the.net 3.5 days, so its at least consistent with how interop code was written to get access to hardware drivers etc.

  • @IceQub3
    @IceQub3 Před 7 měsíci

    Thanks I will use it in all my code now

  • @aprobinda
    @aprobinda Před 7 měsíci +1

    Thanks for the awesome demo, Nick!
    I don't think it's something that I am going to use in the near future. Plus, I am not aware of scenarios that warrant messing with private members of classes in a C# app code.
    Perhaps, other viewers would describe such scenarios?

    • @SimpMcSimpy
      @SimpMcSimpy Před 7 měsíci

      It's mostly for Ahead of Time compilation.

    • @Quasindro
      @Quasindro Před 7 měsíci +3

      Video game modding is also a good example (though modders DEFINITELY were not the target Microsoft was aiming at 😂)

    • @mindstyler
      @mindstyler Před 7 měsíci

      Quite a few in frameworks/engines like Unity. E.g. editor extension and code reuse you otherwise would have to write yourself from scratch.

  • @tyronestephen4263
    @tyronestephen4263 Před 7 měsíci

    Can you use this to do unit tests on private methods?

    • @gbjbaanb
      @gbjbaanb Před 7 měsíci

      why would you want to? A class is the unit, private methods should not be tested like that - you test the public API, the only one you use.

  • @hichaeretaqua
    @hichaeretaqua Před 7 měsíci +1

    I think this is a good approach to access private things if there is no other way. But I'm glad we have code reviews and hope tampering with private things never gets through...

  • @darthruneis
    @darthruneis Před 7 měsíci +1

    I have an actual use case for this that I'm dealing with right now, but unfortunately its on Net Framework, so this wouldn't really apply. Its on an old MS library for OIDC support on OWIN, so its a good use case in the sense that the code is very mature and very unlikely to change, and also the implementation is not extension-friendly (its all private/internal, not protected and/or virtual).
    So, I guess I'm stuck with the reflection code (or copying their implementation verbatim from github).

  • @innerbytes
    @innerbytes Před 7 měsíci

    I see it very usefull for testing in some scenarios.

  • @microtech2448
    @microtech2448 Před 7 měsíci

    Microsoft can address that issue with overriding static field value too. But I wanna know in which scenarios one would need to call private methods through reflection or other way at all?

  • @onman999
    @onman999 Před 7 měsíci +2

    I guess this enables you to test private methods (which isn't really necessairy unless you develop BIG methods with multiple tasks combined). Is there any other use case for this?

    • @77Zamien
      @77Zamien Před 7 měsíci

      Exactly my first thought as well

    • @lordmetzgermeister
      @lordmetzgermeister Před 7 měsíci

      There are many ways to write code but only a few produce code that is easily testable. This can be quite helpful for badly written legacy code I suppose.

    • @Daniel15au
      @Daniel15au Před 7 měsíci +1

      If your methods have multiple tasks combined, they're too large and should be broken into smaller methods. Ideally private methods are implementation details that don't need to be tested on their own.

    • @GumbootMan
      @GumbootMan Před 7 měsíci

      FYI Microsoft is planning to use this feature to enable the built-in JSON serializer to deserialize private members in source generation mode (in a way that is compatible with NativeAOT).

    • @onman999
      @onman999 Před 7 měsíci

      @@Daniel15au My point exactly.

  • @dimitris470
    @dimitris470 Před 2 měsíci

    WoW this is God-sent. I've been writing a state-machine/workflow library kind of thing, and the fastest I managed to access properties etc was with compiled expressions, which still was a lot slower than direct access. Too bad it does not support Generics yet... it would simplify many things

  • @iam3yal
    @iam3yal Před 7 měsíci

    I've read various comments that essentially say that this kind of mechanism defeats the purpose of access modifiers so I hope my explanation is going to help and clarify some of that confusion or misconception, as strange as it might sound to some people access modifiers were never designed as a permission system but as an encapsulation mechanism to control the visibility of different parts of the system not to prevent it, this concept exists in programming mainly for maintainability and usability, e.g., the engine of a car is hidden within the engine compartment whereas the hood is restricted. Point is this mechanism of .NET 8 to access members (and soon types) changes nothing people that wanted/needed to access your code before could always do it through reflection or more hacky alternatives depends on the language/platform so if people are using access modifiers to restrict developers from code that is actually sensitive data then they are using the wrong tool for the job.

  • @mclifeleader
    @mclifeleader Před 7 měsíci

    As a developer and an engineering manager, I can say that as helpful as this maybe it wreaks of code smell!

  • @user-nq8ln7ps7x
    @user-nq8ln7ps7x Před 7 měsíci +1

    I wonder if it can be used with generic methods/interfaces as well? It's always pain when some libraries only expose generic methods, so you have to live without polimorthism and specify concrete generic interfaces, or create some non-generic decorators with lots of delegate generation / caching / casting. For example: Kafka producers in MassTransit

    • @alexisfibonacci
      @alexisfibonacci Před 7 měsíci

      I instead create a lightweight generic wrapper with non-generic interface implementation. Instantiate that wrapper per type and cache the wrappers in a dictionary with the Type as the key. When needed, do the lookup, call to the instance to get the work done, and move on.
      But I guess .NET 8 can simplify all of that and we get to delete some code.

  • @warny1978
    @warny1978 Před 7 měsíci +1

    I see a use case. I used that use case many times.
    I have a method that I need to unit test. I also do not want developpers to directly use that method so I make it private or protected. This allows to do that without complicated code.
    Another Use Case: I have created an abstract class that keeps track of field changes. This is done with backing field not visible to the end class. This allows me to access these hidden fields without permitting a developper to use it directly.

  • @MichaelMortensen
    @MichaelMortensen Před 5 měsíci

    Wonderful insights, thanks!

  • @diadetediotedio6918
    @diadetediotedio6918 Před 7 měsíci +2

    11:55
    Yeah, but you can do it with unsafe (in fact, something very much more unsafer than to change a readonly field, but to change the string contents itself)
    Reflection was not able to do it before? I have an impression that it could

    • @nickchapsas
      @nickchapsas  Před 7 měsíci +3

      You can do anything with unsafe but no, you couldn't do it with reflection

    • @diadetediotedio6918
      @diadetediotedio6918 Před 7 měsíci

      ​@@nickchapsas
      Hmmm, thanks. That probably was a mistake or false memory of my part

    • @vyrp
      @vyrp Před 7 měsíci +2

      After some quick tests, I see that trying to modify a static readonly field in .NET 7 throws FieldAccessException, but works fine in .NET Framework 4.8

  • @aathifmahir
    @aathifmahir Před 7 měsíci +5

    Great power comes with great responsibility, hope devs don't start doing stupid things with this feature

  • @hinekde
    @hinekde Před 7 měsíci

    The only thing I can think of, where it makes sense to access private members would be in tests. Microsoft has/had an way for this in their own test framework using a class I think called PrivateObject.

  • @TheLatyos
    @TheLatyos Před 7 měsíci

    Nick: *extern* you probably haven't seen this keyword before.
    Me, who interops C/C++ to C# for a living: Yeah Nick, I wish. I really wish.

    • @Marius-ir1qn
      @Marius-ir1qn Před 7 měsíci

      What happened ? Spell it out boy.

  • @tanglesites
    @tanglesites Před 7 měsíci +1

    This breaks encapsulation. What use cases does this have?

  • @seancapes2
    @seancapes2 Před 7 měsíci

    Looks like it could be useful if you want to extend/modify something that wasn't designed to be extended.

  • @0ceanswave
    @0ceanswave Před 7 měsíci

    Function pointers are amazing!

  • @jimwithheld7217
    @jimwithheld7217 Před 7 měsíci

    So I have a private var inside my class, and I 100% trust it only holds 1 of 4 values that my method calls allow. But now it might be any other value too. How on earth is safe and tested code possible with those kinds of rules at play?

    • @toebeann
      @toebeann Před 7 měsíci +2

      If someone messes with your code and changes the private value to something unexpected and it breaks, it isn't your job to support them beyond saying "yeah, don't do that."
      Using reflection and other means to access private members have existed in .NET for a long time, there is nothing you are seeing in this video that wasn't already possible some other way. It's just a new API for doing it with the same performance as it it were public, and that's already possible, via even more unsafe means.
      So, treat private the same way you always have. Most users of your libraries etc. won't ever think about trying to access private members, and those that do will almost never come crying to you about it if they break something in the process, because they should know better.

  • @MichaelBattaglia
    @MichaelBattaglia Před 7 měsíci

    Can you use this new way to set a value to a property that is read-only?

    • @phizc
      @phizc Před 7 měsíci

      Probably not directly.
      public string Prop { get; } = "hi";
      will get a get_Prop method, but not a set_Prop method.
      That said, it will get a backing field, and that one can be accessed.

  • @MarkRendle
    @MarkRendle Před 7 měsíci +15

    This would be even better if there were a compile-time check that ensured the target member exists, which does seem like something it could do.

    • @mortenmoulder
      @mortenmoulder Před 7 měsíci

      Instead of "Method" you could use nameof() I guess. Which you also should, because if your method ever changes name, your unsafe accessor breaks. Small improvement over Nick's example, but that's about it

    • @mindstyler
      @mindstyler Před 7 měsíci

      There is

    • @matthew_jackson
      @matthew_jackson Před 7 měsíci +1

      ​@@mindstylerWanna point it out for the rest of us?

    • @GumbootMan
      @GumbootMan Před 7 měsíci

      @@mindstyler I tried it and it threw a runtime exception (MissingFieldException).

    • @MarkRendle
      @MarkRendle Před 7 měsíci

      @@mindstyler I tried it out, there was no check, it just threw an error at runtime.

  • @JohnAndrews_nz
    @JohnAndrews_nz Před měsícem

    I wouldnt use this for private, but the performance boost, often we use reflection on a "object" where we knnow that object has a property/method, that doesnt have a common interface to expose it, that this could then be used to call that public property/method to get/set that value.

  • @thunderdeer6073
    @thunderdeer6073 Před 7 měsíci +1

    Sometimes you gotta do what you gotta do

  • @JorneDeSmedt
    @JorneDeSmedt Před 6 měsíci

    Seems useful for unit testing your private methods.

  • @trevorprice2490
    @trevorprice2490 Před 6 měsíci

    Thinking ahead to use cases I might encounter, I'd probably add an "Unsafe" suffix to all my "Caller" method names just to add a reminder to any users about what's potentially happening behind the code

  • @briantaylor7695
    @briantaylor7695 Před 6 měsíci

    Any idea if it works with Local functions, if so that would be so useful for unit testing

  • @tiendatniit
    @tiendatniit Před 7 měsíci

    Could someone help me to explain why 10 years before They referred to use the of reflection?. It's really painful to debug in the huge system.

  • @frankquednau889
    @frankquednau889 Před 7 měsíci +2

    Kinda OK with having this. Just yesterday I had to use some internal setters for tests involving types of the blobstorage lib. But allowing this to break promises like static readonly seems to me *absolutely bonkers*. Really.

  • @twiksify
    @twiksify Před 7 měsíci

    I actually think that UnsafeAccessor is safer than the previous example using reflection.
    Using the attribute; the class name, method name and kind needs to be known at compile time.
    Using reflection you can traverse and call unknown code, which I think is way more unsafe.

  • @jacquesdemolay2699
    @jacquesdemolay2699 Před 7 měsíci +2

    Could you give examples of when we MIGHT need to access a private method ?

    • @markmidwest7092
      @markmidwest7092 Před 7 měsíci +2

      Unit tests

    • @arjix8738
      @arjix8738 Před 7 měsíci +1

      One great example is modding Unity games!
      Although when modding you'd probably use a fake assembly as ur reference, so the compiler thinks that everything is public (lookup NStrip)
      (yeah this didn't age well)

    • @stxnw
      @stxnw Před 7 měsíci

      @@arjix8738 "so the compiler thinks that everything is public" are you talking about injecting code into the unity process? because I still have to use reflection to access private variable if I am injecting.

    • @toebeann
      @toebeann Před 7 měsíci

      ​​@@arjix8738Assembly Publicizer has been my go-to for the same purpose, but I see NStrip is made by the BepInEx creator so I will give it a look too!
      Do somewhat wish this new API existed back in .net 4 or something so we could use it instead of publicizing all members (I much prefer the idea of only publicizing those members I need rather than everything - less footguns that way!)

  • @StephenCoda
    @StephenCoda Před 7 měsíci

    Seems a little safer than reflection since it must be harder to mess up/exploit at runtime.

  • @GTSJoeG
    @GTSJoeG Před 4 měsíci +1

    Which editor is he using? Doesn't look like Visual Studio nor VS Code.

  • @tedchirvasiu
    @tedchirvasiu Před 7 měsíci +2

    Well, but this uses attributes. So the method name has to be hardcoded, right?

    • @SimpMcSimpy
      @SimpMcSimpy Před 7 měsíci

      Yes, but you have to do that with reflection approach as well. So no difference compared to the old way.

    • @tedchirvasiu
      @tedchirvasiu Před 7 měsíci

      @@SimpMcSimpy The GetMethod receives a string as a parameter which can be a variable. If you do something dynamic, you can pass a computed value there. On the attribute you can't as far as I know.

  • @bsoter
    @bsoter Před 7 měsíci

    I can almost hear typing noises of dotnet tech leaders updating their teams' code guidelines in 'Forbidden techniques' section xD

  • @matthewhamby5749
    @matthewhamby5749 Před 7 měsíci

    Does this work for generic methods?

  • @ForeverZer0
    @ForeverZer0 Před 7 měsíci

    I am totally opposed to the thinking that "too much power" or "is too unsafe" in a language. C# suffered from this thinking for a very long time until recent years when they begin adding some more powerful features and better management over arbitrary memory. A "safe" language should have all the guardrails in place, but completely removing the ability for the programmer to explicitly bypass them can be frustrating where there is something non-standard that needs done.
    Building and emitting IL at runtime was previously the next best thing to do other than just using a different language, so I am glad to see MS putting some more power and trust in programmers.