Come home, white man

>C# Thread
>Language of the year
>Better than java
>Faster than java at parsing 1 billion rows
What do you guys use it for?

Schizophrenic Conspiracy Theorist Shirt $21.68

Homeless People Are Sexy Shirt $21.68

Schizophrenic Conspiracy Theorist Shirt $21.68

  1. 1 month ago
    Anonymous

    why the frick is every program i encounter written in C# slow as shit.

    • 1 month ago
      Anonymous

      name them

  2. 1 month ago
    Anonymous

    Why the woman in thigh-highs?

    • 1 month ago
      Anonymous

      thats what white men want

    • 1 month ago
      Anonymous

      thats what white men want

      thats what white men have become

  3. 1 month ago
    Anonymous

    Is there a scripting language that has great interopability with C#?

    • 1 month ago
      Anonymous

      you dont need one, c# is not bloated like java or c++, can even do functional programming with it

      • 1 month ago
        Anonymous

        Haven't used java since Java 7 or 8, have you? it's got just about every useful C# feature + a diverse ecosystem of non-Java JVM languages. Both languages and runtimes are equally bloated as well.

      • 1 month ago
        Anonymous

        >c# is not bloated

      • 1 month ago
        Anonymous

        I want it for game dev, so I have engine written in C# and then users can write code in a scripting language to code the actual game flow

        • 1 month ago
          Anonymous

          or just do it like terraria and many other games did and just use c# for everything
          It just works

        • 1 month ago
          Anonymous

          save the effort and just use C# for the scripting

        • 1 month ago
          Anonymous

          I'm the one primarily flaming C# right now. But even I think it's fine for game scripting, tbh. Pre-Kotlin and KTS, I wrote a fairly large MMO project that relied exclusively on Java for content plugins and things were fine.

          The boilerplate and verbosity trade-off with using C# or Java as the primary 'scripting' language will pay off if you do anything big:
          - JVM and CLR ecosystem, from the libraries, static analysis tools, and build systems to IDEs are just leaps and bounds ahead of any other popular language/ecosystem. Even if VS itself sucks wiener [and not in a good way, sorry blahaj sisters, Rider is *nearly* as good as IntelliJ, which is just about as good as it gets, IMO.

          - Static typing alwaysssss pays off. Yes, prototyping some random tiny script in something like Python may be quicker (barely?), strong, static typing will pay off that very tiny initial investment back 100 fold when your project grows. You will find obvious issues at compile time, and your static analysis tools will have a much easier time actually understanding what the frick is going on in your codebase, again, helping you reduce/eliminate large swaths of bugs that would creep up if you used something like Python, Ruby, JS, or even my beloved Lua.

          Our MMO project probably had about ~500k SLOC worth of Java content. Not only was it quite fast, but it was just so much more manageable than writing that much code in any traditional 'scripting' language. Boilerplate wasn't all that bad to begin with, but even then, you can create IDE templates to generate whatever.

          Eventually, I transitioned to Lombok. And despite Lombok bringing in some 'magic', it's all code-gen magic, which means if something breaks, you can still look at what was generated and debug it like any other bit of code. I'm not sure I'd go Lombok again in 2024, though, since both have improved a ton. But it may still be worth looking at. I believe C# has a port as well as its own home-grown equivalents.

          cont.

          • 1 month ago
            Anonymous

            Mistakes I made and lessons learned:

            1. Avoid reflection. I abused it so much for hot-reloading of content, automatic plugin registration, etc. It was beautiful and satisfying when it worked, but it was an over-engineered nightmare to debug when things didn't go as planned. It negated many of those static analysis benefits, and the stacktraces are just horrible.

            1.1. Hot-reloading in proudction wasn't really all that useful IMO. Unless you think very hard about object lifetimes and such, you'll likely end up with issues that make it finicky and undesirable anyway, and most of the time, your bugs aren't usually that important that it can't wait for the weekly content-update restart. And if you do run into something horrible like item duplication bugs or whatever, it's better to immediately turn things off and actually ensure you've solved the problem anyway.

            1.2. Automatic plugin registration just isn't worth the reflection mess. Hard-wire what you want on startup instead of scanning for content on startup. Code-gen and/or an IoC container will help alleviate the boilerplate here.

            1.3. RE: IoC containers. I made the mistake of using Spring, but any reflection solution is just too much magic IMO for a large project. Nice when it works, awful when it doesn't. I am not a fan of Guice, the ASP.NET built-in IoC container system, Ninject, Autofac, etc. What I found to be the absolute best of both worlds, at least on the JVM, was Dagger 2; it allowed for similar low-effort DI of Spring, but rather than convoluted reflection, it did code-generation, which A. meant start-up times were insane, but importantly, B. it simply generated almost 1:1 hand-written DI, which meant it was debuggable like any part of your codebase and no insane reflection stacktraces.

            I'm not sure what the .NET equivalent of Dagger is, but I'm certain I've seen similar. I'm sure you can find something if you Google for 'zero reflection di' or 'dagger 2 equivalent .net'.

          • 1 month ago
            Anonymous

            Mistakes I made and lessons learned:

            1. Avoid reflection. I abused it so much for hot-reloading of content, automatic plugin registration, etc. It was beautiful and satisfying when it worked, but it was an over-engineered nightmare to debug when things didn't go as planned. It negated many of those static analysis benefits, and the stacktraces are just horrible.

            1.1. Hot-reloading in proudction wasn't really all that useful IMO. Unless you think very hard about object lifetimes and such, you'll likely end up with issues that make it finicky and undesirable anyway, and most of the time, your bugs aren't usually that important that it can't wait for the weekly content-update restart. And if you do run into something horrible like item duplication bugs or whatever, it's better to immediately turn things off and actually ensure you've solved the problem anyway.

            1.2. Automatic plugin registration just isn't worth the reflection mess. Hard-wire what you want on startup instead of scanning for content on startup. Code-gen and/or an IoC container will help alleviate the boilerplate here.

            1.3. RE: IoC containers. I made the mistake of using Spring, but any reflection solution is just too much magic IMO for a large project. Nice when it works, awful when it doesn't. I am not a fan of Guice, the ASP.NET built-in IoC container system, Ninject, Autofac, etc. What I found to be the absolute best of both worlds, at least on the JVM, was Dagger 2; it allowed for similar low-effort DI of Spring, but rather than convoluted reflection, it did code-generation, which A. meant start-up times were insane, but importantly, B. it simply generated almost 1:1 hand-written DI, which meant it was debuggable like any part of your codebase and no insane reflection stacktraces.

            I'm not sure what the .NET equivalent of Dagger is, but I'm certain I've seen similar. I'm sure you can find something if you Google for 'zero reflection di' or 'dagger 2 equivalent .net'.

            3. Avoid ORMs. Again, I made the mistake of using Spring since it was a large MMO that already needed DI, lots of database interaction, etc, and it seemed to just make sense to use the Enterprise TM all-in-one solution. But again, what a mistake. My experience with Spring, Entity Framework, and virtually every other ORM is that they are just gay and cringe. Debugging is harder, you have to be constantly vigilant that your fancy, clean C#/Java code isn't generating horrific queries, etc. Realistically, you aren't going to constantly switch between 17 database systems, so just pick one and hand-write SQL; it's not hard, your code will be infinitely more debuggable, much more performant, and you won't be constrained by lowest-common-denominator features & instead can take advantage of everything your DBMS has to offer. Every time I have used EF and similar, I am lulled into a false sense of happiness at first with how painless everything is, until it's suddenly just not, and you find yourself fighting the ORM -- "how do I make use of X postgres-specific locking mechanism I really need right now".

            Also, I think the repository-style pattern you'll see often is bad and annoying because it inevitably results in either suboptimal usage of your database or heavily leaking DBMS-specific details into your code. I think my current favorite way of dealing with DB communication is probably CQRS; far more flexible, easy to integrate, less detail leaking, etc. If you do actually end up needing multiple DB backends, you can still totally write separate code for, say, SQLite along with Postgres with minimal effort.

          • 1 month ago
            Anonymous

            I have never met someone who hasn't been burned by Spring + ORMs. Worst experience of my life.

          • 1 month ago
            Anonymous

            Mistakes I made and lessons learned:

            1. Avoid reflection. I abused it so much for hot-reloading of content, automatic plugin registration, etc. It was beautiful and satisfying when it worked, but it was an over-engineered nightmare to debug when things didn't go as planned. It negated many of those static analysis benefits, and the stacktraces are just horrible.

            1.1. Hot-reloading in proudction wasn't really all that useful IMO. Unless you think very hard about object lifetimes and such, you'll likely end up with issues that make it finicky and undesirable anyway, and most of the time, your bugs aren't usually that important that it can't wait for the weekly content-update restart. And if you do run into something horrible like item duplication bugs or whatever, it's better to immediately turn things off and actually ensure you've solved the problem anyway.

            1.2. Automatic plugin registration just isn't worth the reflection mess. Hard-wire what you want on startup instead of scanning for content on startup. Code-gen and/or an IoC container will help alleviate the boilerplate here.

            1.3. RE: IoC containers. I made the mistake of using Spring, but any reflection solution is just too much magic IMO for a large project. Nice when it works, awful when it doesn't. I am not a fan of Guice, the ASP.NET built-in IoC container system, Ninject, Autofac, etc. What I found to be the absolute best of both worlds, at least on the JVM, was Dagger 2; it allowed for similar low-effort DI of Spring, but rather than convoluted reflection, it did code-generation, which A. meant start-up times were insane, but importantly, B. it simply generated almost 1:1 hand-written DI, which meant it was debuggable like any part of your codebase and no insane reflection stacktraces.

            I'm not sure what the .NET equivalent of Dagger is, but I'm certain I've seen similar. I'm sure you can find something if you Google for 'zero reflection di' or 'dagger 2 equivalent .net'.

            [...]

            3. Avoid ORMs. Again, I made the mistake of using Spring since it was a large MMO that already needed DI, lots of database interaction, etc, and it seemed to just make sense to use the Enterprise TM all-in-one solution. But again, what a mistake. My experience with Spring, Entity Framework, and virtually every other ORM is that they are just gay and cringe. Debugging is harder, you have to be constantly vigilant that your fancy, clean C#/Java code isn't generating horrific queries, etc. Realistically, you aren't going to constantly switch between 17 database systems, so just pick one and hand-write SQL; it's not hard, your code will be infinitely more debuggable, much more performant, and you won't be constrained by lowest-common-denominator features & instead can take advantage of everything your DBMS has to offer. Every time I have used EF and similar, I am lulled into a false sense of happiness at first with how painless everything is, until it's suddenly just not, and you find yourself fighting the ORM -- "how do I make use of X postgres-specific locking mechanism I really need right now".

            Also, I think the repository-style pattern you'll see often is bad and annoying because it inevitably results in either suboptimal usage of your database or heavily leaking DBMS-specific details into your code. I think my current favorite way of dealing with DB communication is probably CQRS; far more flexible, easy to integrate, less detail leaking, etc. If you do actually end up needing multiple DB backends, you can still totally write separate code for, say, SQLite along with Postgres with minimal effort.

            4. Related to 1.1: Immutability wherever possible and try to think about your object lifetimes. We ran into horrible issues relating to things like accidentally keeping player objects around far longer than we should've (i.e., way after they've logged out or whatever) because references to players were kept in things like active group minigame lobbies and such after the player had logged out. Instead, if I were doing it again, I'd probably make much more use of immutable data objects since A. it just avoids entire classes of bugs that come with accidentally mutating player state, but B. I'd be less likely to accidentally keep the full player stuck in memory somewhere.

            Similarly, I'd probably go more extreme and go the Jagex route of using integer-based UIDs and looking up the player whenever necessary instead. Even if it does live in memory longer than it should, one 64-bit integer is much less of a problem than the entire monstrosity that was our player class. If you do this, you'll avoid the horrible memory leaks we had + possibly open up the ability for hot-reloading without the issues we experienced.

            cont.

          • 1 month ago
            Anonymous

            Mistakes I made and lessons learned:

            1. Avoid reflection. I abused it so much for hot-reloading of content, automatic plugin registration, etc. It was beautiful and satisfying when it worked, but it was an over-engineered nightmare to debug when things didn't go as planned. It negated many of those static analysis benefits, and the stacktraces are just horrible.

            1.1. Hot-reloading in proudction wasn't really all that useful IMO. Unless you think very hard about object lifetimes and such, you'll likely end up with issues that make it finicky and undesirable anyway, and most of the time, your bugs aren't usually that important that it can't wait for the weekly content-update restart. And if you do run into something horrible like item duplication bugs or whatever, it's better to immediately turn things off and actually ensure you've solved the problem anyway.

            1.2. Automatic plugin registration just isn't worth the reflection mess. Hard-wire what you want on startup instead of scanning for content on startup. Code-gen and/or an IoC container will help alleviate the boilerplate here.

            1.3. RE: IoC containers. I made the mistake of using Spring, but any reflection solution is just too much magic IMO for a large project. Nice when it works, awful when it doesn't. I am not a fan of Guice, the ASP.NET built-in IoC container system, Ninject, Autofac, etc. What I found to be the absolute best of both worlds, at least on the JVM, was Dagger 2; it allowed for similar low-effort DI of Spring, but rather than convoluted reflection, it did code-generation, which A. meant start-up times were insane, but importantly, B. it simply generated almost 1:1 hand-written DI, which meant it was debuggable like any part of your codebase and no insane reflection stacktraces.

            I'm not sure what the .NET equivalent of Dagger is, but I'm certain I've seen similar. I'm sure you can find something if you Google for 'zero reflection di' or 'dagger 2 equivalent .net'.

            [...]

            3. Avoid ORMs. Again, I made the mistake of using Spring since it was a large MMO that already needed DI, lots of database interaction, etc, and it seemed to just make sense to use the Enterprise TM all-in-one solution. But again, what a mistake. My experience with Spring, Entity Framework, and virtually every other ORM is that they are just gay and cringe. Debugging is harder, you have to be constantly vigilant that your fancy, clean C#/Java code isn't generating horrific queries, etc. Realistically, you aren't going to constantly switch between 17 database systems, so just pick one and hand-write SQL; it's not hard, your code will be infinitely more debuggable, much more performant, and you won't be constrained by lowest-common-denominator features & instead can take advantage of everything your DBMS has to offer. Every time I have used EF and similar, I am lulled into a false sense of happiness at first with how painless everything is, until it's suddenly just not, and you find yourself fighting the ORM -- "how do I make use of X postgres-specific locking mechanism I really need right now".

            Also, I think the repository-style pattern you'll see often is bad and annoying because it inevitably results in either suboptimal usage of your database or heavily leaking DBMS-specific details into your code. I think my current favorite way of dealing with DB communication is probably CQRS; far more flexible, easy to integrate, less detail leaking, etc. If you do actually end up needing multiple DB backends, you can still totally write separate code for, say, SQLite along with Postgres with minimal effort.

            [...]
            [...]
            4. Related to 1.1: Immutability wherever possible and try to think about your object lifetimes. We ran into horrible issues relating to things like accidentally keeping player objects around far longer than we should've (i.e., way after they've logged out or whatever) because references to players were kept in things like active group minigame lobbies and such after the player had logged out. Instead, if I were doing it again, I'd probably make much more use of immutable data objects since A. it just avoids entire classes of bugs that come with accidentally mutating player state, but B. I'd be less likely to accidentally keep the full player stuck in memory somewhere.

            Similarly, I'd probably go more extreme and go the Jagex route of using integer-based UIDs and looking up the player whenever necessary instead. Even if it does live in memory longer than it should, one 64-bit integer is much less of a problem than the entire monstrosity that was our player class. If you do this, you'll avoid the horrible memory leaks we had + possibly open up the ability for hot-reloading without the issues we experienced.

            cont.

            Also, regarding immutable data objects, when we wrote most of our Java content, it was before Java and C# had records/data classes as a language feature. Which, of course, meant all the fun boilerplate of:

            public final class PlayerDetails {
            private final String username;
            private final long uid;
            private final int position;

            public PlayerDetails(final String username, final long uid, final int position) {
            this.username = username;
            this.uid = uid;
            this.position = position;
            }

            public String getUsername() {
            return username;
            }

            /*
            * omitted for brevity
            */
            }

            Lombok made this painless, though, since we could just annotate the class with `@Value` and have it take care of all that boilerplate with nice, debuggable code-gen. Eventually C# and Java both got records/data classes. But last time I used either on a daily basis (.NET 5.0? JDK 17?) both lacked one crucial feature of Lombok that really helps: `@Wither`/`@With` -- as the slightly weird name implies, it generates 'with'-er methods:

            @Value
            @With
            @NonNull
            public class PlayerDetails {
            String username;
            long uid;
            int position;
            }

            Would turn into:

            public class PlayerDetails {
            private final String username;
            private final long uid;
            private final int position;

            public PlayerDetails(@NonNull final String username, final long uid, final int position) {
            if (username == null) throw new NullPointerException();
            this.username = username;
            this.uid = uid;
            this.position = position;
            }

            public @NonNull String getUsername() {
            return username;
            }

            public PlayerDetails withUsername(@NonNull final String username) {
            return new PlayerDetails(username, uid, position);
            }

            /*
            * omitted for brevity
            */
            }

            Kotlin has this by default, which is really nice, since it allows for effortless cloning to 'mutate' records. Don't think C# or Java have it natively yet, though.

          • 1 month ago
            Anonymous

            PlayerDetails player1 = new("OpIsAhomosexual", 0, 10);
            PlayerDetails player2 = player1 with { username = "OpIsStillAhomosexual" };

            Console.WriteLine(player1);
            Console.WriteLine(player2);

            public record PlayerDetails(string username, long uid, int position){}

            PlayerDetails { username = OpIsAhomosexual, uid = 0, position = 10 }
            PlayerDetails { username = OpIsStillAhomosexual, uid = 0, position = 10 }
            Nope, don't lump C# with your dogshit language ranjeet

          • 1 month ago
            Anonymous

            >Records support with expressions to enable non-destructive mutation of records.
            Nice. Glad to hear it made it finally. Like I was saying, I haven't used either on a daily basis since .NET 5.0 and JDK 17--neither of which had `with` yet.

            They are both improving. And both have been slow to adopt very basic features. Whenever I used Java, I missed C# properties. Whenever I used C#, I missed Java's covariant return types (how fricked was it that it took decades for a meme OOP language to be able to return a concrete subtype while fulfilling interface contracts?). They are always trading blows. I don't think you can really say one is better than the other -- especially when you factor in the entire ecosystems as a whole.

            >Nope, don't lump C# with your dogshit language ranjeet
            Just wait for 2038 when Valhalla, Panama, and Loom finally all become stable. India will rise, mashallah.

            P.S. Kotlin is C# but better.

            Oh, probably ensure you have a solid event system for players to hook and override different game behavior. This may seem ironic given what I've said about magic, debugability, etc, considering pubsub-style code can be quite annoying to follow and debug sometimes, but I think you will make your users' lives much easier if they can listen for and intercept things like 'on fire' events when a gun is used that way they can easily modify the behavior of core gameplay logic easily -- e.g., "oh, I want to make a mod for incindiary ammo -- just listen for some item pickup event, apply this buff variable, and now whenever the damage event is fired, I can check whether the attacker has incindiary ammo or not".

            Possibly related, I think designing as much of your game with composibility in-mind -- e.g., an ECS of some sort -- while may be foreign at first, will allow for significantly easier modding and adaptability.

            Also, one more thing, while we eventually switched to Kotlin for KotlinScript--which gave us all the nicities of Kotlin + the ability to really transform it into a game-specific DSL, I think you could probably achieve similar results with modern C#. With all their hype about "omg, you can make classless ASP.NET applications now!" [which was dumb and useless], I would imagine all the work that went into that and the ability to embed Roslyn and stuff would allow you to turn C# into something like KotlinScript.

            Use the nullability? meme early if you haven't already. That aspect of Kotlin eliminated so many bugs in our Java code for free and I don't get why C#oids have been so hesistant to use it now that it's a thing. Use it everywhere. Similar to static typing, it'll pay off. I cannot count the number of issues in games like Garry's Mod related to Lua 'nil' and similar.

            And also, speaking of Garry's Mod, while maybe not the best example of the hooks/events meme, it's a prime example of even ghetto pubsub allowing for crazy extensibility.

          • 1 month ago
            Anonymous

            Mistakes I made and lessons learned:

            1. Avoid reflection. I abused it so much for hot-reloading of content, automatic plugin registration, etc. It was beautiful and satisfying when it worked, but it was an over-engineered nightmare to debug when things didn't go as planned. It negated many of those static analysis benefits, and the stacktraces are just horrible.

            1.1. Hot-reloading in proudction wasn't really all that useful IMO. Unless you think very hard about object lifetimes and such, you'll likely end up with issues that make it finicky and undesirable anyway, and most of the time, your bugs aren't usually that important that it can't wait for the weekly content-update restart. And if you do run into something horrible like item duplication bugs or whatever, it's better to immediately turn things off and actually ensure you've solved the problem anyway.

            1.2. Automatic plugin registration just isn't worth the reflection mess. Hard-wire what you want on startup instead of scanning for content on startup. Code-gen and/or an IoC container will help alleviate the boilerplate here.

            1.3. RE: IoC containers. I made the mistake of using Spring, but any reflection solution is just too much magic IMO for a large project. Nice when it works, awful when it doesn't. I am not a fan of Guice, the ASP.NET built-in IoC container system, Ninject, Autofac, etc. What I found to be the absolute best of both worlds, at least on the JVM, was Dagger 2; it allowed for similar low-effort DI of Spring, but rather than convoluted reflection, it did code-generation, which A. meant start-up times were insane, but importantly, B. it simply generated almost 1:1 hand-written DI, which meant it was debuggable like any part of your codebase and no insane reflection stacktraces.

            I'm not sure what the .NET equivalent of Dagger is, but I'm certain I've seen similar. I'm sure you can find something if you Google for 'zero reflection di' or 'dagger 2 equivalent .net'.

            [...]

            3. Avoid ORMs. Again, I made the mistake of using Spring since it was a large MMO that already needed DI, lots of database interaction, etc, and it seemed to just make sense to use the Enterprise TM all-in-one solution. But again, what a mistake. My experience with Spring, Entity Framework, and virtually every other ORM is that they are just gay and cringe. Debugging is harder, you have to be constantly vigilant that your fancy, clean C#/Java code isn't generating horrific queries, etc. Realistically, you aren't going to constantly switch between 17 database systems, so just pick one and hand-write SQL; it's not hard, your code will be infinitely more debuggable, much more performant, and you won't be constrained by lowest-common-denominator features & instead can take advantage of everything your DBMS has to offer. Every time I have used EF and similar, I am lulled into a false sense of happiness at first with how painless everything is, until it's suddenly just not, and you find yourself fighting the ORM -- "how do I make use of X postgres-specific locking mechanism I really need right now".

            Also, I think the repository-style pattern you'll see often is bad and annoying because it inevitably results in either suboptimal usage of your database or heavily leaking DBMS-specific details into your code. I think my current favorite way of dealing with DB communication is probably CQRS; far more flexible, easy to integrate, less detail leaking, etc. If you do actually end up needing multiple DB backends, you can still totally write separate code for, say, SQLite along with Postgres with minimal effort.

            [...]
            [...]
            4. Related to 1.1: Immutability wherever possible and try to think about your object lifetimes. We ran into horrible issues relating to things like accidentally keeping player objects around far longer than we should've (i.e., way after they've logged out or whatever) because references to players were kept in things like active group minigame lobbies and such after the player had logged out. Instead, if I were doing it again, I'd probably make much more use of immutable data objects since A. it just avoids entire classes of bugs that come with accidentally mutating player state, but B. I'd be less likely to accidentally keep the full player stuck in memory somewhere.

            Similarly, I'd probably go more extreme and go the Jagex route of using integer-based UIDs and looking up the player whenever necessary instead. Even if it does live in memory longer than it should, one 64-bit integer is much less of a problem than the entire monstrosity that was our player class. If you do this, you'll avoid the horrible memory leaks we had + possibly open up the ability for hot-reloading without the issues we experienced.

            cont.

            [...]
            [...]
            [...]
            Also, regarding immutable data objects, when we wrote most of our Java content, it was before Java and C# had records/data classes as a language feature. Which, of course, meant all the fun boilerplate of:

            public final class PlayerDetails {
            private final String username;
            private final long uid;
            private final int position;

            public PlayerDetails(final String username, final long uid, final int position) {
            this.username = username;
            this.uid = uid;
            this.position = position;
            }

            public String getUsername() {
            return username;
            }

            /*
            * omitted for brevity
            */
            }

            Lombok made this painless, though, since we could just annotate the class with `@Value` and have it take care of all that boilerplate with nice, debuggable code-gen. Eventually C# and Java both got records/data classes. But last time I used either on a daily basis (.NET 5.0? JDK 17?) both lacked one crucial feature of Lombok that really helps: `@Wither`/`@With` -- as the slightly weird name implies, it generates 'with'-er methods:

            @Value
            @With
            @NonNull
            public class PlayerDetails {
            String username;
            long uid;
            int position;
            }

            Would turn into:

            public class PlayerDetails {
            private final String username;
            private final long uid;
            private final int position;

            public PlayerDetails(@NonNull final String username, final long uid, final int position) {
            if (username == null) throw new NullPointerException();
            this.username = username;
            this.uid = uid;
            this.position = position;
            }

            public @NonNull String getUsername() {
            return username;
            }

            public PlayerDetails withUsername(@NonNull final String username) {
            return new PlayerDetails(username, uid, position);
            }

            /*
            * omitted for brevity
            */
            }

            Kotlin has this by default, which is really nice, since it allows for effortless cloning to 'mutate' records. Don't think C# or Java have it natively yet, though.

            Lastly,

            5. Again, related to immutability and avoiding reflection, I often, understandably, see things like having an immutable data representation of classes along with the full fat business logic class or ORM entitity objects, etc. At some point, you'll want to convert between, say, `PlayerDetails` and your Player entity or whatever. If you're down for the boilerplate, you can definitely hand-write all of that, but if you're lazy, and most are, what I usually see in the .NET world is shit like AutoMapper -- which sounds nice, it allows you to ... automatically map between objects based on their field names and such.

            However, the problem with automapper and most similar solutions I've seen is that, again, it's all reflection garbage. In the JVM world, I would recommend MapStruct instead; it's very, very mature and works the exact same from a developer UX/feature perspective but rather than reflection, it generates all the mappings at compile time -- so again, you get the same debuggability of regular code.

            In the .NET world, I haven't come across anything quite as mature, but a couple years ago I used Mapperly for a large ASP.NET project, which despite its [at the time] relative immaturity, worked nearly as well as mapstruct and follows the same principle of code-gen > reflection for generating mappings.

          • 1 month ago
            Anonymous

            Anyway, end of rantings - I recognize much of that may not be applicable to you depending on what kind of game you're making, but you still may benefit from some of it. In particular, I really *do* think things like C#/Java/Kotlin are actually for content -- the tooling and debugabillity outweight any downsides. And again, just don't fall into the traps that heavily introspectible VM languages offer; keep it simple and you can write a really nice content development system that works well for both you and your players. Write your C# more like C or Go sometimes and you'll be a much happier person.

            If you want to go the extra mile, try experimenting with alternative CLR/CLI languages during the design process -- e.g., F#/IronPython.

            Again, not that I think you should probably use either, especially not IronPython, for your actual content, but if you do make an active attempt to ensure your content API feels fluent across all three, you can probably leave the language decision up to the players; if they don't like C#, let them use IronPython or whatever.

          • 1 month ago
            Anonymous

            Oh, probably ensure you have a solid event system for players to hook and override different game behavior. This may seem ironic given what I've said about magic, debugability, etc, considering pubsub-style code can be quite annoying to follow and debug sometimes, but I think you will make your users' lives much easier if they can listen for and intercept things like 'on fire' events when a gun is used that way they can easily modify the behavior of core gameplay logic easily -- e.g., "oh, I want to make a mod for incindiary ammo -- just listen for some item pickup event, apply this buff variable, and now whenever the damage event is fired, I can check whether the attacker has incindiary ammo or not".

            Possibly related, I think designing as much of your game with composibility in-mind -- e.g., an ECS of some sort -- while may be foreign at first, will allow for significantly easier modding and adaptability.

    • 1 month ago
      Anonymous

      PowerShell

    • 1 month ago
      Anonymous

      i love C#.

      Python.NET and IronPython are both a thing. both are interoperable with C#. IronPython is a Python implementation that runs on the CLR, Python.NET is a connector of sorts for "vanilla" Python.

  4. 1 month ago
    Anonymous

    >we're open sores now
    >our ide? nah, figure that out on your own. you can use our open-washed electroid editor, though
    >uhh, debugger? no, that's propriietary too. go use samsung's if you want to do "debugging" fossoid
    no thank you.

    • 1 month ago
      Anonymous

      >Rider
      >I use linux
      >Microsoft have been working on the linux kernel since 2009
      tell me you're a nocoder junior gay without telling me that kek

      Haven't used java since Java 7 or 8, have you? it's got just about every useful C# feature + a diverse ecosystem of non-Java JVM languages. Both languages and runtimes are equally bloated as well.

      .net has f# which is the only thing that matters, no jvm pseudo-functional language can compete with it

      .net is about the only left SANE ecosystem there is

      • 1 month ago
        Anonymous

        >tell me you're a nocoder junior gay without telling me that kek
        I use Rider too. Doesn't change anything I said about the whole ".NET is open now guys!" thing. What, we rely on a proprietary JetBrains IDE, have to get debugging tools from Samsung instead of Microsoft if we want FOSS, etc. It's all a meme. It's the same gay shit they've been doing with VSC.

        It's time to adopt the JVM; F# is dead four-eyes. Kotlin ate your food, broke your glasses and took your lunch money. Even the Scaloids have given up.

        • 1 month ago
          Anonymous

          who said it's open source? stop being a toddler with that mentality, use great tool to make greatsoftware, it wont go anywhere as it didnt for the past 20 years

  5. 1 month ago
    Anonymous

    >C#
    >Come home, white mtf

  6. 1 month ago
    Anonymous

    What does C# give me that C/C++ don't?

    • 1 month ago
      Anonymous

      women and money

    • 1 month ago
      Anonymous

      Don't compare the holy language to the monstrosity that is C++. Even C# is less haram. Peace be upon you.

  7. 1 month ago
    Anonymous

    [...]

    I wrote it from the perspective of having writing a large game in Java, but it's all applicable to C#. It's all stuff I wish I did from the start.

    - "If you're writing a large game, please don't fall into the trap of using dynamic languages for scripting; C# has a lot of benefits due to tooling, static typing, and so on"
    - "If you're writing any sort of server for your game, please consider avoiding ORMs, because they will bite you"
    - "If you're using DI, like many C# applications, please consider avoiding IoC containers that use reflection"
    - "Prefer code-gen over reflection. Prefer hand-wiring things where you don't actually need code-gen. You will have an easier time debugging your game"
    - "Don't fall into the trap of directly passing large objects in a multiplayer game if you're not very vigilant about lifespans of the objects, because the GC will not clear them; they can still in be use even if you might not think they are"
    - "Try to avoid mutability and use record-like objects where you can, because you will minimize state-related bugs, and if you do end up with lifespan issues, a couple of integers and a string is going to eat up less memory than full-fat player and other entity objects"
    - "Start using the nullability operator early because it's a very useful C# addition that Java didn't have; my workflow changed significantly when I began using a language that had it"
    - "Prefer composition over inheritance because it will make your game easier to mod"
    - "Ensure there is an adequate way for end-users to hook into core logic"

  8. 1 month ago
    Anonymous

    Do 3 billion devices use it?
    Didn't think so.

  9. 1 month ago
    Anonymous

    I wish I was a C# Chad working with Visual Studio proper on Windows like a white man... Instead I have to stick to node homosexualry and webshit

  10. 1 month ago
    Anonymous

Comments are closed.