Hello World in .NET written using IL code

Поделиться
HTML-код
  • Опубликовано: 16 сен 2024
  • Subscribe: bit.ly/ChapsasSub
    Become a Patreon and get source code access: / nickchapsas
    Hello everybody I'm Nick and in this video I am going to have a little fun by writting a .NET application that prints Hello World! by emiting IL code. IL or Intermediate Language is the language that C#, VB.NET and F# will all compile into and it's what the CLR or Common Language Runtime, will ultimately execute. C# provides a way to emit that IL code and this can be used in multiple things from building dynamic proxies to speeding up reflection.
    Don't forget to comment, like and subscribe :)
    Social Media:
    Follow me on GitHub: bit.ly/ChapsasG...
    Follow me on Twitter: bit.ly/ChapsasT...
    Connect on LinkedIn: bit.ly/ChapsasL...
    Keep coding merch: keepcoding.shop
    #csharp #dotnet

Комментарии • 46

  • @thinker2273
    @thinker2273 3 года назад +18

    Metaprogramming never fails to surprise me with each new way of writing code to avoid having to write code.

  • @ivandrofly
    @ivandrofly 3 года назад +8

    yes, more IL tutorial please!

  • @kano636
    @kano636 3 года назад +8

    Your HelloWorldWithIL code actually could be translated to IL code using C# as well, creating the HelloWorld inception nightmare

  • @astralpowers
    @astralpowers 3 года назад +3

    I remember doing this for a university compiler project back in the .NET 2.0 days. But then System.Linq.Expressions in .NET 3.5 made it all obsolete.

  • @matthewblott
    @matthewblott 3 года назад +1

    Nick's a smart guy.

  • @barmetler
    @barmetler 2 года назад +1

    This is so cool! IL this kind of stuff.

  • @marna_li
    @marna_li 3 года назад +1

    The average developer does not need this. But they should at least know about it.
    A typical use case for this is when you build have to generate IL code in memory, like when building a compiler, or for some optimized task.
    And a lot of compile-time tooling is based around Reflection.Emit or Cecil. That can now be replaced by Roslyn and source generators.
    There is even a third-party package called Cecil that is used for inspecting and building assemblies - without dependency on Reflection.Emit.
    Nowadays, people can use Roslyn and source generators to generate high-level C# code at compile-time instead. It is easier to debug, and suits better for most cases.

    • @nickchapsas
      @nickchapsas  3 года назад +5

      This is partially true. Yes 99% of .NET developers don't need to know how to do this. That being said I disagree with the source generator statement. I think they both have their place for various reasons. Firstly, Source Generators are only supported on specific dotnet version and specific C# versions, while IL emittion works across the board. It is also fundamentally different since one will emit IL code directly while source generation is subject to lowering and then IL emition (which is not the same). You don't get to control IL with SG but you do with IL emit (and some times you need to). Source Generators have a long way until their developer experience becomes acceptable (it is currently horrible to work with). You won't see Moq migrating to source generators anytime soon.
      As a side note, my content is not necessarily there to teach something (that's why I explicitly make it shorter than other people in the same area), but it rather acts as a catalyst to get someone started on a topic. This video is no different.

    • @marna_li
      @marna_li 3 года назад

      @@nickchapsas I agree. I know that they are not the same, and of course there are limitations.
      What I meant to say is that tools have been using Reflection.Emit for emitting compile-time structure or IDE experiences, in cases where you, today, could use source generators.
      You need know on what level you need to generate code.
      Anyway, I’m a compiler nerd so I have experimented a lot with IL and metadata generation. It is fun generating IL and to see it run 🙂
      Keep up the good work with your channel!

  • @p4xx07
    @p4xx07 3 года назад +1

    Why would you want to do this though? What do you get out of it to create assemblies during run time?
    I guess you could have a config file, and then create different assemblies based on the config... But it seems a bit gimmicky

    • @nickchapsas
      @nickchapsas  3 года назад +2

      Unit testing mocking frameworks are built this way. You can also significantly speed up reflection to be as fast as actual compiled code. Is more use-case specific for sure, but certainly something you should be at least aware of

  • @CocoszFTW
    @CocoszFTW 3 года назад +3

    is there any reason to do this? like can you actually out-code the compiler?

    • @nickchapsas
      @nickchapsas  3 года назад +2

      Technically it depends but I wouldn't try to out-code the compiler because the compiler evolves and might out-code you by upgrading. This is very valuable if for example reflection absolutely is the only way to do something but you want it to be as fast as possible. IL Generation for proxy classes and other things is also a very valid usecase but it might eventually become less relevant as source generators evolve.

    • @MulleDK19
      @MulleDK19 3 года назад +7

      You can do things that C# doesn't allow. For example, you can make a int ReinterpretFloatAsInt(float x) value by doing
      ldarg.0
      ret
      This will load the first argument onto the evaluation stack, then return the value. Since the argument is float but the method returns int, this will effectively reinterpret it as an int. IE. you'll get the raw integer value of the float, equivalent to return BitConverter.ToInt32(BitConverter.GetBytes(x)); but significantly more performant.
      Just an example.

    • @carpal4489
      @carpal4489 3 года назад

      @@MulleDK19 just use Bitcast if I'm not wrong.

    • @carpal4489
      @carpal4489 3 года назад

      Compilers that run on the crl use it to generate IL code

    • @MulleDK19
      @MulleDK19 3 года назад +1

      ​@@carpal4489 They've added BitConverter.SingleToInt32Bits() in .NET 5. But that's not a language feature. This was just an example of what IL allows.

  • @dragon_programming
    @dragon_programming 2 года назад

    Does anyone have any idea why Console.Readline can't be called from il?
    I tried it with every kind of method ( methods with return types, methods with parameters,methods without any of these) - all of them work.
    But if you try to use any of the read methods from the console ,the il fails , givinh you a System.Reflection.TargetInvocationException with an InnerException of InvalidProgramException.
    If anyone has a solution i would love to hear it.

    • @jonas9
      @jonas9 Год назад

      Are you using the value? You can't return a value from a void method.

  • @lincolntx98
    @lincolntx98 3 года назад

    is london always cold? just asking because i think i never saw you without a coat \o/

  • @moeenkamali1288
    @moeenkamali1288 3 года назад +1

    I'm not sure when we really need to write il code directly

    • @nickchapsas
      @nickchapsas  3 года назад +3

      You don't until you have a usecase for it. Then you do.

    • @sheglova
      @sheglova 3 года назад

      There aren't many use cases, but one example might be when you need to generate optimized code based on user configuration i.e. you're building a DSL.

    • @temp50
      @temp50 3 года назад

      @@sheglova I can give you a real world example.
      I had to add an x509 certificate to every assembly built for production.
      I also had to write an x509 cert validator for these assemblies. the method had been added to the LoadAssembly event handler so every managed dll which was loaded by a given assembly was checked if they contained the required certificate.
      And I had to write unit tests for that event handler logic to verify that the cert validation is really doing what it should do.
      So how you do it from a unit test? Exactly, you create an assembly (with a "helloworld"-like method in it), load the assembly from a memory stream with Assembly.Load and trigger the validation logic for positive and negative tests. Of course for positive tests you also have to add a valid certificate to your dynamically created and loaded assembly. :D

  • @acidrazor
    @acidrazor 3 года назад +3

    Now you just showing off 🤨

  • @amaillo
    @amaillo 3 года назад +1

    Is that Rider?

  • @clearlyunwell
    @clearlyunwell 3 года назад

    👍🏽

  •  3 года назад

    OMG

  • @pabloturnesg
    @pabloturnesg 3 года назад +1

    Hi nick, what method would you recommend using to store passwords and keys used in source code running in .net core, thanks

    • @sps014
      @sps014 3 года назад

      Don't store passwords, if possible use hash+randomized salt will provide decent security.

    • @ElSnakeObwb
      @ElSnakeObwb 3 года назад

      Check out IDataProtector it's in Microsoft.AspNetCore.DataProtection

    • @pabloturnesg
      @pabloturnesg 3 года назад +1

      @@sps014 I may have not explained myself well, I was talking about api keys and db passwords needed to run the app services, not user passwords.

    • @sps014
      @sps014 3 года назад

      @@pabloturnesg my bad i assumed something else ...

    • @nickchapsas
      @nickchapsas  3 года назад +2

      Use a secure key store solution like Azure KeyValut or AWS KMS. I have a video on the subject showing you how to do it.

  • @sob4655
    @sob4655 2 года назад

    This is useless. You can't claim to teach IL Emit without any mention of the push/pop sequence of the evaluation stack.

    • @nickchapsas
      @nickchapsas  2 года назад +2

      Never claimed to teach IL at any point in the video or the title.