[–] 2 points 9 months ago

Regarding your point about C##…

It does seem like, in their effort to make the language less Java-y/enterprise-y, we now have multiple syntaxes for everything. I get the desire to maintain backwards compatibility but it does start to make the available range of syntax feel kind of messy.

  • source
  • parent
  • context
  • [–] 2 points 9 months ago

    I think that’s one of the reasons I like primary constructors - when you see one, it’s a signal that there’s nothing “special” happening with the parameters.

    On the other hand… there are like 7 different ways to do constructors at this point (exaggerating a little…) and it’s a lot to keep track of.

  • source
  • parent
  • context
  • [–] 2 points 9 months ago (1 child)

    In later .net version for loops can be slower than linq queries. If the compiler knows the iteration does not cause side effects, it often already does not allocate and can even vectorize some loops, so .Sum(...) might be faster then a manual for loop.

    Optimizing without benchmarking is often wasted effort.

  • source
  • parent
  • context
  • [–] 5 points 9 months ago (2 children)

    I think they especially make sense for records so you can easily create shallow modifyable value semantic types with little boilerplate code.

    I do hate that all these features are yet more keywords and weird syntax. It's becoming C##.

    Like the records are just sytesized methods on classes or structs. We already have this in the language with source generation. If something there was missing to create records, it would IMO make more sense to improve the source generation so the community also has access to the ecmxtensions. And the record could be split up in it's separate features (copy constructor, defaul ToString imp, equatable) so we could choose to use part of it.

  • source
  • [–] 3 points 9 months ago

    I wonder if it's similar to the reason why i find it ok to work in, it's feels similar to a python just with brackets and static types. A lot of the bothersome work is hidden from you, at least with .NET.

    One does get annoying things, and a lot of "you should just know to do this" for things you don't really understand or encounter naturally, but that's also something in other languages.

  • source
  • parent
  • context
  • [–] 3 points 9 months ago (3 children)

    No language is perfect and they all have their quirks…

    But, even though Microsoft made it, C# is one of my favorite languages to write in. And to be 100% honest about it, I’m not sure I entirely know why I enjoy it so much. I’ll have to give that some thought!

  • source
  • parent
  • context
  • [–] 0 points 9 months ago (4 children)

    There are ugly languages. There are unusable languages. There are languages with nuances beyond comprehension.

    And there's csharp which for some reason tries to be all of these things.

  • source
  • [–] 2 points 9 months ago (2 children)

    Interesting stuff. I used to work under an engineer who was obsessed with performance tuning. I remember him converting all of our foreach loops to for loops. He probably told me, but I never knew/retained that it allocated on the heap. I also had always assumed reflection = slower.

    Though, as he points out, .NET 10 does a similar kind of optimization for you. So, it seems like largely an unnecessary optimization. I can only imagine a 40-byte allocation optimization matters in an extremely low memory environment or at extreme scale.

  • source
  • [–] 5 points 9 months ago*

    TIOBE is controversial, but regardless, I'm not surprised. C# is a pleasure to use, and the barrier to entry is decreasing every day. It's the best option for web, video games, and desktop apps. I wouldn't be surprised if it overtook Java.

    I hope that means that this community and the dotnet community will become more active.

  • source
  • Unless the purpose is to get a destructor to trigger only. This is the most correct answer. This pattern is very widely used and can prevent crashes. The using block is a try{}finally{} behind the scenes but without the catch it just throws and could be caught higher up the stack on accident. When I was a fresh grad this pattern saved my dumb ass when I unintentionally would catch the exceptions somewhere else, but hey it didn't crash.

  • source
  • parent
  • context
  • [–] 6 points 10 months ago* (1 child)

    My recommendations would be:

    • Do not rely on GC.Collect() in any real program code. Just let the GC do its thing.
    • If you need guarantees about when the destructor (or equivalent) is called, use the dispose pattern and use a using statement or declaration explicitly so Dispose gets called as soon as possible.
    class DestructorDemo : IDisposable
    {
        public string Name { get; set; }
        public DestructorDemo(string name)
        {
            Name = name;
            Console.WriteLine($"demo object {Name} constructed");
        }
        public void Dispose()
        {
            Console.WriteLine($"demo object {Name} disposed");
        }
    }
    
    using var obj1 = new DestructorDemo("obj1");
    
    using (var obj2 = new DestructorDemo("obj2"))
    {
        Console.WriteLine("Press key to dispose 'obj2'");
        Console.ReadKey();
        // obj2 goes out of scope at the end of the block
        // this will automatically call `.Dispose()` on it
    }
    
    Console.WriteLine("Press key to dispose 'obj1' and exit");
    Console.ReadKey();
    
    // obj1 goes out of scope here
    

    Note that this code is just to showcase the using keyword (in relation to IDisposable). If you want to implement the disposable pattern properly you should look at the help article I linked. Such as making sure that Dispose is called even if the object is naturally garbage collected, that is if you forget to use using. (I also didn't check the validity of the code but it should get the idea across.)

  • source
  • view more: ‹ prev next ›