6 INSANE Things You Didn't Know You Could Write in C#

Поделиться
HTML-код
  • Опубликовано: 13 дек 2024

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

  • @local9
    @local9 Год назад +170

    Alternative Title, "6 quick ways to get your repo access revoked"
    Some examples, I can see some use cases, but most (specially the date) would likely get me shouted at.
    Heard you like some async, so I put some more async inside your async.

    • @mikaelsyska
      @mikaelsyska Год назад +3

      But that's not a click bait title 😉

    • @local9
      @local9 Год назад +3

      @@mikaelsyskaIts Nick, I'd still click it.

    • @mikaelsyska
      @mikaelsyska Год назад +3

      @@local9 yes, no matter what the title is, I would still watch.

  • @vyrp
    @vyrp Год назад +99

    For those who are wondering: in `async async async(async async) => await async`, we have:
    * First async: the keyword.
    * Second async: the method return type.
    * Third async: the method name.
    * Forth async: the parameter type.
    * Fifth async: the parameter name.
    * Sixth async: the parameter again.

    • @DoGGy1110
      @DoGGy1110 Год назад +5

      That's obvious, but why c# allows method name and parameter's to be async? That's the question

    • @highlanderdante
      @highlanderdante Год назад +16

      Async is a contextual keyword, for backwards compatibility reasons. Same goes for var, await, get and set and many others

    • @jongeduard
      @jongeduard Год назад +5

      The main point for me is that the async keyword was introduced in C# version 5, and in order not to break compatibility with older code, the compiler team probably decided that they couldn't just make such variable or parameter names suddenly forbidden.
      So they really had to work around it and support it both as a identifiers as well as keywords, depending on the place where they are used.
      However, on the other hand, I am not sure at this point why I cannot make a variable called await, but while I can call it async.

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

      @@jongeduard You can make a variable named "await", just not inside an async method. Because 'await' has a special meaning in that context. On the other hand, 'async' only has a special meaning as a modifier in the method declaration.

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

      @@louisfrancisco2171 Thanks! That explains it all, and also confirms the compatibility thing even more! However, what must have confused me, when I quickly test on Sharplab, I get a compiler error for it in top level code too (no problem since the whole top level code thing far newer).
      When I make a synchronous local function inside that, the variable name is accepted. LOL.
      Thinking further that actually makes sense too, since top level code is optionally asynchronous too, as soon as the first await call is written.

  • @louisfrancisco2171
    @louisfrancisco2171 Год назад +4

    2:07 I would have gone one bit further and add an implicit conversion to string.
    8:50 "Be very careful with your extension methods on types you don't own" There is usually less need to add extension methods on types you do own.
    I tried some crazy stuff, just for the fun of it. For example:
    WriteLine(from x in 42 where 7 select x);
    This writes "[0, 7, 14, 21, 28, 35, 42]"

  • @warny1978
    @warny1978 Год назад +16

    The new insane thing to do in c#8 is using static methods in interfaces.
    It's powerfull as hell.
    There's loads of interfaces already existing. For example, if you want a type to be parsable from string, just derive it from IParsable. You know that particular type will have Parse and TryParse methods. If you create a generic class/method like this :
    public void TestParse(string value) where T : IParsable
    you'll then be able to write :
    T v = T.Parse(value);
    This comes with many more interfaces such as IAdditionOperators, ISubstractionOperators, ITrigonomertyFunctions...
    This means you can define you own class with compiled standardized names. That's so cool !
    This also means that you no longer have to create functions for each numeric type; you can handle everything at once :
    public T Addition(T num1, T num2) where T : IAdditionOperators => num1 + num2;
    for example, here's the signature for my matrix class :
    public sealed partial class Matrix : IFormattable, IEquatable, IEquatable, IEquatable, IEquatable, ICloneable,
    IAdditionOperators,
    ISubtractionOperators,
    IEqualityOperators,
    IEqualityOperators,
    IMultiplyOperators,
    IMultiplyOperators,
    IMultiplyOperators,
    IDivisionOperators,
    IUnaryNegationOperators,
    IUnaryPlusOperators
    where T : struct, IFloatingPoint, IPowerFunctions, ITrigonometricFunctions, IRootFunctions
    It now handles both double and float

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

      But that's C# 11 and dotnet 7, not C# 8.

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

      @@jongeduard You are right, but i did not get it work properly in c#11

  • @DemoBytom
    @DemoBytom Год назад +27

    The first one is a technique Nuke Build uses for their paths. It also has implicit operator to cast it to string.

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

      When I saw it in Nuke I thought it is so cool usage of operator overload

    • @Grafsnikers
      @Grafsnikers Год назад +1

      If I’m not mistaken, this technique was added to standard library in Python

    • @Spartan322
      @Spartan322 Год назад +1

      @@Grafsnikers Its better part of the C++ standard since 2017 when std::filesystem::path came in C++17

  • @ivank6486
    @ivank6486 Год назад +5

    Just remember that you can get the length of the string directly from memory (unsafe obviously):
    TypedReference ref = __makeref(str);
    IntPtr ip = **(IntPtr**) &ref;
    var ptr = (int*) ip.ToPointer();
    var len = *(ptr+2);

  • @firestrm7
    @firestrm7 Год назад +11

    For the lock-monitor insanity my guess is that the lock is a syntax sugar which translates to the usage of System.Threading.Monitor and since you just created your own version of it it takes precedence over the BCL when compiling.

    • @gctypo2838
      @gctypo2838 Год назад +5

      My first thought was for debugging concurrency issues.
      One thing I've done fairly recently was create an IDisposable class that takes a lock on an object and releases it upon disposal, but also allowing parameterizing a timeout before the lock fails, as well as logging a message if the lock is held for too long - and I could just replace the lock(obj) with a using(...). This class ended up helping a lot with some very improperly-threaded legacy code. If I altered the Monitor class like this I might have been able to get the diagnostics I needed much earlier.

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

    Thanks!

  • @karthikkrishnaswami3164
    @karthikkrishnaswami3164 Год назад +4

    One interesting that got junior devs stumped in my project was the use of implicit and explicit and how the hell incompatible types get assigned and yet compiled!

  • @killymxi
    @killymxi Год назад +6

    6:13 - `foreach (var i in 5..10)` - actually seems sensible and would be nice to have in the language, I think.
    Immediately, I went to check if `foreach (int i in [5,6,7,8,9,10])` would work, but unfortunately, it complains that there is no target type...

    • @davidbottiau5408
      @davidbottiau5408 Год назад +1

      I think a lot of languages have this feature. Rust has it so you can do `for i in 0..5 { }`. It is so convenient.

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

      I thought it looked like something from Python or the like

    • @louisfrancisco2171
      @louisfrancisco2171 Год назад +1

      You are just missing a 'new' before those square brackets.

  • @bslushynskyi
    @bslushynskyi Год назад +4

    Well, in my experience the bullshit I did with C# I can name 2 things: extension methods for Span/ReadOnlySpan and overloading operator+ that accepts 2 different types and returns an enumerable of 3rd type. Something like Papa+Mama=Kids.

  • @bsoter
    @bsoter Год назад +1

    Bizarre operators usage in C#*
    *Me*: Nuts!
    *Also me trying to do anything in F#*: Yeah, ok, first things first - let's wrap this two-arguments function with some bizarre operator.

  • @mdonatas
    @mdonatas Год назад +3

    Something which fits nicely to this theme is Add() method duck-typing and collection initialization. So you could have something like new List { "2023-12-05" }; given that you have an extension method: public static void Add(this List col, string param) { col.Add(DateTime.Parse(param)); }

  • @PyronTheMage
    @PyronTheMage Год назад +6

    I saw most of these on a reddit post recently. Guessing you got the idea from the same post? The third one (range extensions) I've implemented myself and have been using for a few years, it's a shame it's not part of the default Range class/syntax.

    • @nickchapsas
      @nickchapsas  Год назад +1

      I had shown 3/6 of them already in other videos in the past, one was from twitter which i mentioned and one was from a talk from Jared Parsons

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

      @@nickchapsas Ah, maybe these must have been going round the internet for a while then. Either way, love your explanations on them and thanks for sharing!

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

      Just odd timing as I thought I had deja-vu lol

  • @arztje
    @arztje Год назад +3

    This is one of my favorite videos as of late. "How the hell can we do this?" Always a winner. :)

  • @davidwilliss5555
    @davidwilliss5555 Год назад +1

    the Monitor lock thing I could see maybe for debugging where you could log out which thread got the lock. But Heisenberg would rear his ugly head and the logging would change the timing of whatever thing you were trying to debug .

  • @VeNoM0619
    @VeNoM0619 11 месяцев назад +1

    You say "Dont do this" but I have to say these are nice.
    As long as the extensions aren't GLOBAL, and only used with specific "using namespace", I see it as no different than other extension methods.

  • @Tsunami14
    @Tsunami14 Год назад +7

    For the async one, I wonder if that's from then they first introduced the keyword... so it wouldn't break existing code?

  • @AduMaster
    @AduMaster Год назад +1

    The overloading of `operator /` done in `FilePath` seems quite normal if you're familiar with C++ and `std::filesystem::path`.

  • @talwald1680
    @talwald1680 Год назад +2

    That fileinfo operator is exactly how python's recommended pathlib.Path object works.

  • @ryanjeffares8238
    @ryanjeffares8238 Год назад +8

    The first one is a thing in the C++ standard library. The filesystem::path class has / overloaded to append any string or path-like object. It feels wrong in a way, but actually quite ergonomic, and nice to know that path separators are all taken care of properly

    • @Kitulous
      @Kitulous Год назад +10

      that's better than using bit shift operators for printing to streams and reading from streams but it's in the same ballpark

    • @ryanjeffares8238
      @ryanjeffares8238 Год назад +2

      @@Kitulous Yeah, the shift operators were... A Decision. I pretty much exclusively use superior third party libraries for those things lol

  • @S0p0r10
    @S0p0r10 Год назад +1

    We did use the Extensions on int to create dates for our unit test.
    IT IS really nice to read in tests that require different dates and such

  • @MZZenyl
    @MZZenyl Год назад +3

    Hehe, glad I shared Jared's async madness on Reddit the other day.
    It also highlights why the language design team are so careful when working with contextual keywords, for example in relation to the proposed "semi-auto properties" (exposing the implicit backing field of properties the "field" contextual keyword), in situations where you might already have a field named "field".

  • @_nikeee
    @_nikeee Год назад +2

    async can probably be used as a type or identifier because it was added later to C#, when there was already code that used that as a name. So in some contexts, the keyword can be used as an identifier. Same story with nameof.

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

    11:37 Filename checks out

  • @joshpatton757
    @joshpatton757 Год назад +8

    I've used the integer awaiting before in a serious project, one that required lots of intricate precise timing. But instead of making custom awaiters on integers directly, I created a new class that was covariant with integer, and awaited that. (with the minor abstraction of 'beat', as this was timing against music, and so the length of time represented by a beat scaled with a 'tempo' setting) This and a simple static method to return beat let me 'await Beats(2)'.

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

      But in that case, if you care about performance, I would have chosen to wrap it inside a struct and definitely not a class. There is no reason to allocate memory on the heap for 1 single integer value. Wrapping and int in a class instead of a struct is basically another way of boxing, al be it not in the popular terms.

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

      @@jongeduard Absolutely true in general practice. What I am describing has both a small instance size, wraps a single value, and is immutable - all indicators towards a struct as the preferred approach.
      This particular case, however, had one reason why I went class over struct: those beats get passed around a lot. And I mean a lot. Since structs are value types, both referencing and any casting that happens as they get passed around and used generates more boxing and unboxing than using a struct saves. As a class though, just needed to pass the references around and saved that overhead.
      It also helps that I owned the only hardware that ever ran on, so knew exactly what the limitations were and didn't have to fine tune performance beyond what was needed to run the show - this was a live procedural music generator/lighting controller, that was generating both individual notes of the music and controlling individual movements/hue changes for the gobos.

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

      ​@@joshpatton757 A struct containing an Int32 is 4 just bytes, the size of the int. While A reference is actually a pointer and is 8 bytes on a 64bit system.
      A class containing an Int32 needs both 8 bytes for each reference, as well as 4 bytes for the actual int value.
      When you have a struct that is no larger than 16 bytes, you are always the most efficient with a struct, both in CPU performance as well as in memory, even if you are copying it a million times. And that is exactly what Spans are as well, they are ref structs that contain both a pointer and a length value.
      And my personal benchmarks show even 24 byte structs to still be pretty memory efficient, I yet have to find out why exactly.
      Larger structs are indeed less memory efficient than reference types, but they often still win in CPU performance over reference types most of the time.
      This is purely because of GC overhead, always slowing down things. For each newly created reference to an object, the GC is doing extra work to track it.
      If you really need to pass references because you actually need to share the same thing between methods, the fastest thing is to use ref parameters to your struct. Then you don't have the copy problem at all, giving you both CPU and memory efficiency back.

    • @ralfwarnat9257
      @ralfwarnat9257 11 месяцев назад

      but do not await Beasts(7);

  • @code8986
    @code8986 Год назад +2

    Can you please do a video (if you haven't already) on all the uses and contexts of the "ref" keyword? I know one of them, but not the rest. Thank you!

    • @richardzheng5774
      @richardzheng5774 10 месяцев назад

      ref means passing the reference of a value type, for example when you have an int as parameter, normally we pass a copy of the int to it, even the mothed edits the int value, it wound affect the original variable we passed, and if you allow the method to change it, pass (ref i) to it, in this case the method body has the reference to that int variable, any change on the int variable will affect the value itself

  • @billy65bob
    @billy65bob Год назад +2

    6:00 This trick is cooler with ranges, i.e. 0..5
    It's also the only one I'd consider useful... strictly with ranges only...
    Well, maybe with a ValueTuple variant for setting the step size...

    • @Kitulous
      @Kitulous Год назад +1

      no, add an extension method Step for it!
      public static RangeWithStep Step(this Range rng, int step) => new(rng, step);
      foreach (var i in 0..5.Step(2)) { ... }

  • @antonzhernosek5552
    @antonzhernosek5552 Год назад +2

    That last one was also missing "public class var" to demonstrate the full sillyness of context-based keywords

  • @flybyw
    @flybyw 10 месяцев назад

    I used the Monitor technique to replace System.Net.Quic with OpenSSL and QUIC Datagram support on Windows 10 back in .Net 6 when .Net 7 was in preview and only supported Windows 11 with TLS 1.3 in SChannel. Used with conditional preprocessor to target different versions of runtimes.

  • @isnotnull
    @isnotnull Год назад +2

    Monitor.Enter is the funniest thing I've ever seen so far 🤣

  • @acmesoft
    @acmesoft Год назад +1

    can you make a video of ActionResult, IActionResult, IResult and Result and the differences. Why and When we need to use each case?

  • @christian.levesque
    @christian.levesque Год назад +4

    The most insane thing I've done in C#? One time, I reversed an array without using Stack Overflow

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

      Only insane if that took you less time than another developer looking it up and spending the time on something else ;)

  • @agailloty
    @agailloty Год назад +1

    The first one has the same behavior as the Path class in the Python pathlib library.

  • @benoitrousseau4137
    @benoitrousseau4137 Год назад +1

    The date and path joining tricks might come from someone trying to replicate the C++ standard library, those features were standardized relatively recently.

  • @biohaz999
    @biohaz999 Год назад +3

    What about some IDisposable ones? Especially for the monitor thing. Await using lock = new Lock();

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

    1. This technique is extremely useful in any language because it allows you to join values together in a clearly regulated way that's still easy to read. Use it where it clearly would make sense to, if you start overriding != to produce a class you really should be beat upside the head
    6. Dear God, its type of crap that makes the most vexing parse sound trivial.

  • @leandroteles7857
    @leandroteles7857 6 месяцев назад

    With the new "Extension Everything" feature coming in C# 13 we will be able to add the "/" operator directly to string, enabling this path concatenation hack without a helper class.

  • @MonkeyVaughan
    @MonkeyVaughan Год назад +2

    I remember working on PL/1 on the mainframe (I love that language with fond memories) but that 'async' example reminded me of something that broke my heart that you could do with PL/1... IF IFIF = IF THEN IFIFIF = IFIFIF; something to do with being able to use keywords when you probably shouldn't, it's just mischievous eh!

  • @AvenDonn
    @AvenDonn Год назад +1

    The Monitor stuff feels like some serious insanity

  • @proosee
    @proosee Год назад +3

    I like range extension to facilitate in foreach (not for integers, though), in fact, I don't quite understand why language don't have it by default - I mean, shouldn't ranges be iterable?
    Path joining - I think this a (rare) valid use case for operator overloading - I see no harm here.
    Rest is... well... no comment, lol

  • @guybahar6856
    @guybahar6856 11 месяцев назад

    For the lock-monitor, you can do something like "smart" using

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

    @03:04: a Microsoft manager probably won't showcase Jetbrains products, and only Jetbrains ReSharper / Rider can do certain refactorings. So I have doubts about that course's completeness (in terms of how to do them automatically).

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

    9:06 is a nice technique for a malware to do some source code infection

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

    duck typing in c# is extremely powerful, imagine what you can do if the switch operator/expression were able to resolve which "case" go into, by calling a special method (or a method on an interface, why not) on the type that need to be switched on....i hope they will do it one day.

  • @TicoCryptonaut
    @TicoCryptonaut 8 месяцев назад

    I like the idea of piping file paths and I'd never thought about it. Is the only counterpoint that other developers will be confused by it? I'm tempted to keep using it.

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

    Could I maybe use that monitor class override to use default timeout to lock keyword? So that all my locks would timeout, instead of wait indefinitely in case of deadlock?
    I am now using IDisposable LockWithTimeout(this object lck) ... method and "using" keyword to do the locking, but this would be much, much pretier.

  • @Chris-zb5nm
    @Chris-zb5nm Год назад

    Basically you can create all sort of these interesting things with the power of Extensions.
    That's why I loved C#.

  • @ekeke7125
    @ekeke7125 Год назад +1

    Monitor and the lock really surprised me

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

    actually we learn everyday with you Nick, Thank you 😁😁

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

    As I watch this, David Letterman's "Stupid Pet Tricks" comes to mind.

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

    The monitor thing could be useful to make a distributed lock. Immediately came to mind because I had to solve this exact problem just days ago

  • @tkadosh
    @tkadosh 2 месяца назад

    Very cool 👍

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

    As a general rule, probably don't do most of these. But, conceptually, how they work can be interesting and useful.

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

    Some of those things have such strong Ruby vibes!

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

    When you were beginning to show the lock statement, I was thinking "will we try to goto into a locked lock statement maybe?".
    It didn't turn out that way, but I'm curious if it's possible. 🤔
    (So can goto be used to enter a lock)

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

    Wasn't the raw object locking as a mutex the old canonical way of locking stuff in C#? If I remember correctly it was because having a separate object as the mutex instead of locking the container itself is cleaner and less error prone supposedly. I could see that make sense in wrapper containers that maintain multiple internal representations for example but I never really understood the argument more generally tbh.

  • @viophile
    @viophile Год назад +1

    I personally do not appreciate any kind of trickery. The simpler it is, the better.

  • @alexanderkvenvolden4067
    @alexanderkvenvolden4067 Год назад +1

    11:06 Buffalo buffalo, Buffalo buffalo buffalo, buffalo Buffalo buffalo.

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

    Well, another 6 insane interview questions

  • @orterves
    @orterves Год назад +10

    Insane C# techniques that no one in their right mind will use - except course the C# team, who will probably add them to the base language in the next release.

    • @volan4ik.
      @volan4ik. Год назад +1

      Actually / operator is used in some projects and is a very nice feature, for example in Nuke build automation library to provide path concatenation

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

      @@volan4ik. I know - just joking that many recent C# versions have come with new language features that modify the look of the language quite drastically (mostly for the better, it is to be said). It's good though - it can be hard to justify adopting approaches that are unconventional, if beneficial, when they are just some random NuGet library; when they are implemented within the language itself there's not so much second guessing using them when they are useful.

  • @lordicemaniac
    @lordicemaniac Год назад +2

    maybe not insane, but using monads will do quite interesting transformation to your code and flow

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

      Reminder that awaitable tasks are already monads in C# with language-level support.

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

    Javascript developers are now really considering C# after this vid

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

    Sir would love to see .net AI content..langchain vector search etc.. any plans?

  • @funkydiddykong
    @funkydiddykong Год назад +11

    Maybe you could show some things that are flat out impossible in C#.

    • @AvenDonn
      @AvenDonn Год назад +2

      C# is Turning Complete, so it's an empty list technically

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

      @asedtf I know of one niche thing, hooking functions used by the GC such as GlobalMemoryStatusEx. Managed code does not like being run in that context and will throw.
      So there are things.

    • @diadetediotedio6918
      @diadetediotedio6918 Год назад +1

      You can really do anything with it, even GPU programming (there are some transpillers from IL to cuda code for example)

    • @егор-ш2о5з
      @егор-ш2о5з Год назад

      For example, if you use unsafe code, you can allocate and delete an instance of any class just like in C++

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

    Your scientists were so preoccupied with whether or not they could, they didn't stop to think if they should.

  • @pillmuncher67
    @pillmuncher67 10 месяцев назад

    Why would you not use am embedded language for file paths? It's common practice in Python, it's there in the standard library (pathlib.Path).

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

    7:13
    Well, this is not unrecommendable I think, some modern languages like Rust and Kotlin have similar ways of looping

  • @Aly_._
    @Aly_._ Год назад

    Nice video. Where’d you get your haircut?

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

    this video made me smile :)

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

    The Monitor is really something. How does that even work, not complaining about existing class/conflict... Hmm

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

    Mine is just evil, not proud. Create a Console class with WriteLine method that prints "Compilation error" in a project of a newbie that didn't know about namespaces.

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

    whenever I see creative uses of opperator overloading I hear the jojo "ooooh noohh" meme in my head :P

  • @BittermanAndy
    @BittermanAndy Год назад +2

    0:46 SUBLIMINAL MESSAGING

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

    They should have just made the range type enumerable. Not really sure why they didn't.

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

    Can't wait to have some python nerd make a package called pysharp or Cspy or whatever, with all the magic stuffs x)

  • @AlFasGD
    @AlFasGD Год назад +1

    I cannot wait until async becomes a normal keyword and the async bs is no longer valid. Same goes for var, and many other contextual keywords that should no longer be accepted as valid identifiers.

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

    the async stuff looks like a war crime

  • @HoussamR-x7e
    @HoussamR-x7e Год назад

    my favorite is Infinite await sequence:
    Var ret = await await...... await 3;

  • @brkr78
    @brkr78 Год назад +2

    This looks like something one could use to troll/haze the new hire. async async async is my favorite, the foreach-thing is almost usefull.

  • @leandroteles7857
    @leandroteles7857 5 месяцев назад

    For the "extension nonsense" example, I got an even better approach:
    var today= 30 / November / 2023;
    Just define a helper struct with static readonly members for each month, overriding "/" operator accordingly. And also put a "global using static" for that struct, so the month names can be unqualified 🤣🤣🤣

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

    The last thign with async async async... it scares me, because it turns C# into javascript LOL

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

    Dude, what are you waiting for? Actually an async of an async of async of async of asynce...Yeah, totally describes the state I'm in, most of my life!

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

    People are afraid of a lot of nightmare fuel. This is so cursed so it beats any horror to date.

  • @user-tk2jy8xr8b
    @user-tk2jy8xr8b Год назад

    Ha, didn't know `lock` had such semantics

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

    When you do something for the heck of it.

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

    6 cursed things and other possible C# warcrimes

  • @PedroHenrique-us5ks
    @PedroHenrique-us5ks Год назад

    6 ways to write cursed C#

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

    Dude just made Ruby from C# by Extension methods xD

  • @Naton
    @Naton Год назад +2

    Time to make F# chaining operator

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

      That async operator example looks ripe for creating knockoff computation expressions

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

    This video is basically WAT by Gary Bernhardt, but redone in C# 😂

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

      NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN

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

    this video made me scream "NOOOOOOOOOOO"

  •  Год назад

    Monitor 'override' is really weird.

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

    This is some cursed stuff dude.

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

    Some smells Python lol so I hate it, but the lock() one is kinda cool.

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

    loved first one with overload for /, also pipe was awesome, have to try it some time

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

    yeah, code obfuscation by extension methods 😬

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

    WTFs said while watching this video was out of range

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

    i love the forech range the most its amazing

  • @onetoomany671
    @onetoomany671 Год назад +1

    Enumerating a range of integers that way (a..b) actually sounds pretty neat. But I would need built-in support from the language out of the box, doing it custom like this is the smelliest of smells.