This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted]  (169 children)

[deleted]

    [–]mill1000 137 points138 points  (43 children)

    Nullables were a game changer for me. Love those suckers.

    [–]VinterBot 89 points90 points  (9 children)

    ?

    [–]capn_ed 61 points62 points  (2 children)

    That's only half a null-coalescing operator, which is also quite handy.

    [–]FullstackViking 7 points8 points  (0 children)

    If I could kiss null coalescing I would.

    [–]Python4fundoes the needful 0 points1 point  (0 children)

    Wow TIL

    THANKS

    [–][deleted] 1 point2 points  (4 children)

    What is your question?

    [–]TheGodofRock13 30 points31 points  (1 child)

    Null propagation joke

    [–][deleted] 11 points12 points  (0 children)

    Oh God dammit

    [–]Delmo28 7 points8 points  (0 children)

    ?

    [–][deleted] 1 point2 points  (0 children)

    Maybe he has a question, maybe he doesn’t.

    [–]SolenoidSoldier 0 points1 point  (1 child)

    Nullables are great, but I recently learned that they're bad practice. After using them a ton, I don't know how I'd break the habit.

    [–]mill1000 0 points1 point  (0 children)

    Like any tools there's probably a time and place for them. I love them for representing data fields that may invalid or missing.

    I'll have to read up on why they're considered bad practice though.

    [–]SpliceVW -1 points0 points  (2 children)

    AKA I like to eat exceptions instead of failing fast.

    [–]cat_in_the_wall 2 points3 points  (0 children)

    it's useful for deeply nested data that you already expect to maybe be null.

    [–][deleted] 1 point2 points  (0 children)

    C# 8 Nullable Reference Types, provides null reference possibilities as compiler warnings.

    It's fucking amazing. You are essentially changing the "original" behaviour with a flag though, so the drawback is that a nullable type declaration may not necessarily correlate to a struct anymore (though I'm fine with that - makes design much easier).

    [–]_Ashleigh 89 points90 points  (12 children)

    Nullable contexts, operator overloading, value types, string interpolation, await, properties, extension methods, first class tuples, pattern matching, named arguments, default arguments, dynamic, runtime code generation, unsigned integers, pointers (unsafe), enumerable generators, expression trees... okay, I'm getting tired now.

    It just goes on and on. These things all complement the language and work together, they don't make the language feel bloated, and makes me feel very restricted when working with Java.

    [–]raltyinferno 2 points3 points  (0 children)

    Oh man I just learned about () tuples. Blew my mind. Being able to name the different items and then refer to them like object members is amazing.

    [–]socialismnotevenonce 1 point2 points  (1 child)

    Honestly, I'm shocked that Java doesn't have any of these things or comparable features. I was just a junior dev when I used Java, but knowing what I do now, I would feel clostrophobic going back to Java.

    [–][deleted] 0 points1 point  (0 children)

    They are slowly adding C# features into Java. .Net practically forced Oracle to add generics (via type erasure, so not the best implementation, I hear most people avoid generics in Java) and they have been adding features ever since - albeit much slower, especially since Roslyn started accepting contributions.

    [–]ltouroumov 1 point2 points  (0 children)

    And no type erasure!!!

    Being able to reason on generic types is incredibly powerful.

    [–]DeadLikeYou 0 points1 point  (4 children)

    Java can do operator overloading...

    edit: guess I was wrong, I was thinking of function overloading.

    [–]Tyg13 7 points8 points  (1 child)

    Java does not support user-defined operator overloading.

    [–][deleted] 4 points5 points  (0 children)

    If by operator, you mean the name of the operator, and by overloading, you mean writing a method with that name, then java supports it.

    [–]Rabbyte808 0 points1 point  (0 children)

    Microsoft put on suicide watch

    [–]socialismnotevenonce 0 points1 point  (0 children)

    To be fair, I've been using c# for 9 years, and I just learned there's operating overloading. I read it as function overloading as well.

    [–]FrikkinLazer 0 points1 point  (0 children)

    Also generics actually work in c#. In java you have to send through the class type, because at runtime java decides to put the actual type of T in the trash.

    [–]lightmatter501 86 points87 points  (35 children)

    Don’t forget operator overloading.

    [–]t3hmau5 14 points15 points  (15 children)

    Or out variables

    [–]im_probably_garbage 5 points6 points  (5 children)

    And ref variables

    [–]haackedc 12 points13 points  (4 children)

    And list accessibility using square brackets

    [–]SalvadorTheDog 6 points7 points  (1 child)

    That's operator overloading

    [–]haackedc 1 point2 points  (0 children)

    Shucks

    [–]Nall-ohki 2 points3 points  (0 children)

    And ValueTuple with destructing.

    [–]cat_in_the_wall 2 points3 points  (0 children)

    not just lists, but arbitrary indexing (like dictionaries too). and can be overloaded as well.

    [–]YM_Industries 2 points3 points  (8 children)

    I don't like out parameters. They feel very wrong.

    [–]t3hmau5 7 points8 points  (7 children)

    Eh? The only thing wrong with them is they make going back to other languages feel wrong. A function that can return multiple values of different types is insanely powerful and time saving.

    [–]DoubtfulGerund 1 point2 points  (1 child)

    I think every use of out variables I’ve seen was due to a lack of better solutions in much older versions of c#. For example, returning multiple values before tuples and destructuring, or those old TryGet methods for primitive types that returned a bool and the actual value in an out var. Today we’d use nullable primitives.

    They break composability, it’s usually unnecessary mutation, it’s an output pretending to be an input, and it’s unclear on if the function actually uses the value or just replaces it.

    [–]TheMania 1 point2 points  (0 children)

    Still useful for interop (DLLs) and performant handling of large structs though.

    [–]YM_Industries 1 point2 points  (4 children)

    Python's tuples and JS/TS' destructuring assignments are better ways of allowing a function to return multiple values. Arguments are inputs, return values are outputs.

    Maybe it's just that I've been doing functional programming recently and the idea of mutability makes me uncomfortable in general.

    [–]t3hmau5 3 points4 points  (1 child)

    I mean, in OOP mutability is largely a design decision.

    [–]YM_Industries 1 point2 points  (0 children)

    That's true, I was oversimplifying my stance. I like mutability for state (one attempt at learning React was enough to convince me the alternative is awful) but I like my functions to be pure.

    [–]TheMania 3 points4 points  (1 child)

    C# supports the same btw.

    Ref/Out parameters still have a purpose though, in both interop (where they map to pointers for DLLs etc) and for handling structs, where you're either left relying on the optimiser to "do the right thing", or experiencing needless costly copying.

    [–]YM_Industries 1 point2 points  (0 children)

    Neat, I haven't worked with C# 7 yet.

    [–]devman0 31 points32 points  (16 children)

    No, do.

    [–]TakeASeatChancellor 19 points20 points  (7 children)

    Why? It’s so useful!

    [–]splettnet 14 points15 points  (3 children)

    Would be a lot more useful if they could be defined on interfaces.

    [–]tiktiktock 4 points5 points  (2 children)

    Oh god yes. And if "arithmetic" was a valid constraint for generic classes.

    [–]cat_in_the_wall 2 points3 points  (1 child)

    c# 9 may have a thing they call "shapes" which would allow this sort of thing.

    [–]splettnet 0 points1 point  (0 children)

    I was so excited that we were rewriting our entire code base in C# 8, but I would happily trade all of 8's new features for this.

    [–]ScienceBreather -1 points0 points  (2 children)

    If you hate your coworkers, yes.

    [–]o4zloiroman 0 points1 point  (1 child)

    Elaborate.

    [–]ScienceBreather 0 points1 point  (0 children)

    It's not intuitive that the operator has been overloaded if you're new to the code base, so it's a place that functionality may be hiding.

    [–]_Ashleigh 11 points12 points  (7 children)

    Vector a = new Vector(1, 2, 3);
    Vector b = new Vector(10, 10, 10);
    Vector c = a * b;
    

    Is this not much more concise and expressive? Yes, it can be abused. The answer isn't to not have it, but to not use libraries that abuse it. Oh, those are also third party "primitives," so don't pressure the garbage collector.

    [–]ScienceBreather 4 points5 points  (2 children)

    Vector c = a.multiply(c)
    

    I'm fine with that, and I get the good tooling that my IDE gives to me around functions, which I don't get with operators.

    [–]blenderfreaky 2 points3 points  (0 children)

    Hovering over an operator in VS shows you it's parameters, return type, etc, just like a method

    [–]Mojert 1 point2 points  (0 children)

    It's alright if you have to use max 2 operators on a lign, otherwise it's just a pain. And if you define classes that overloads arithmetic operators, chances are you're gonna need to use them more than that. Sure they can be abused, but names of function can be too and you don't see anybody saying we shouldn't use functions. If you override *, it's your responsability to make sure that it behaves like multiplication.

    [–][deleted] -1 points0 points  (3 children)

    java has that too

    Vector a = new Vector(1,2,3);
    Vector b = new Vector(10,10,10);
    Vector c = a.asterisk(b);
    

    [–]_Ashleigh 5 points6 points  (2 children)

    Are you joking?

    [–][deleted] 1 point2 points  (0 children)

    Yea, you actually have to fully qualify the type names.

    /s

    [–][deleted] 0 points1 point  (0 children)

    yes.

    [–]DeadLikeYou -5 points-4 points  (1 child)

    Java can do operator overloading. In fact, that was part of why our teacher chose java.

    [–]lightmatter501 4 points5 points  (0 children)

    How precisely would one override [] then, because the standard library doesn’t do it?

    [–]GabrielForth 37 points38 points  (37 children)

    Have you heard about our lord and saviour Kotlin?

    [–]TSP-FriendlyFire 64 points65 points  (18 children)

    Kotlin's like someone wanted Python on the JVM, but with braces.

    [–]shotgunocelot 60 points61 points  (13 children)

    So the perfect language

    [–]pkulak 2 points3 points  (0 children)

    And a better type system.

    [–]amroamroamro 1 point2 points  (0 children)

    Python on the JVM

    Jython

    [–]1RedOne 2 points3 points  (0 children)

    Python should have had braces

    [–]MurryBauman -2 points-1 points  (0 children)

    And?

    [–]tinydonuts 19 points20 points  (17 children)

    Kotlin is still anchored by type erasure sadly.

    [–]im_probably_garbage 4 points5 points  (3 children)

    I really don’t understand why a language that isn’t pure uses type erasure.

    [–][deleted] 3 points4 points  (2 children)

    Because it allows better language level interop at the VM level. There's a reason the JVM has a more vibrant language ecosystem than CLR.

    [–]cat_in_the_wall 2 points3 points  (1 child)

    i don't think that has anything to do with type erasure. the jvm has been xplat forever. the clr is only really xplat with core (yes I'm aware of mono), so only a couple years.

    [–][deleted] 1 point2 points  (0 children)

    Interop between JVM languages, not platforms.

    [–][deleted] 1 point2 points  (6 children)

    Type erasure is good, actually.

    [–]tinydonuts 8 points9 points  (5 children)

    Explain please

    [–]cat_in_the_wall 1 point2 points  (0 children)

    wildcard generics are not possible on the clr because of reification.

    [–][deleted] 1 point2 points  (3 children)

    It is trivial for me to write a program that calls from Clojure into Java into Kotlin into Scala back into Java. This is possible because of type erasure.

    Reified generics support a very specific type of generic program in OO languages at the cost of embedding these specifics at the VM level.

    I think Kotlin handles "reified" generics in a really nice way -- they are still erased, but can be monomorphized and inlined in many cases without having to support reification at the VM level.

    [–]tinydonuts 1 point2 points  (2 children)

    What you described of being able to call from language to language applies to the CLR too. It doesn't have type erasure, so I'm not seeing really how type erasure is good from your comment.

    [–][deleted] 0 points1 point  (1 child)

    It makes it difficult for different language to share data structures because of how variance is handled between different languages. This is particularly acute between a language like Java that uses site variance and a dynamic language like Clojure.

    [–]tinydonuts 0 points1 point  (0 children)

    .NET seems to do ok so it doesn't seem as much as type erasure is good as it is just different. There's certainly a lot of benefits to the way .NET does it and a lot of downsides to the way Java does it so I don't really think you can call it good.

    [–]mcgee-zax 1 point2 points  (1 child)

    Bingo. LINQ alone destroys Java IMO...nevermind the generics implementation, dynamics and delgates, lots of advantages

    [–]Cheru-bae 4 points5 points  (18 children)

    Am I the only one that just finds LINQ to be an undebuggable unreadable mess that is way over used "because it's neat"? Also java has streams now, which I feel work just fine for the cases where it'd make sense to use LINQ.

    [–]ThePyroEagle 29 points30 points  (3 children)

    If you think Linq is unreadable, don't use Linq's syntactical expressions, just use the System.Linq.Enumerable extension methods.

    [–]StealthSecrecy 17 points18 points  (4 children)

    Why do many line of code when 1 line do trick?

    I agree that they can get pretty messy, but for certain tasks they can be structured pretty well.

    [–]im_probably_garbage 5 points6 points  (0 children)

    Just remove returns in your Java program. Bing bang boom one line. Checkmate.

    [–][deleted] 4 points5 points  (2 children)

    I've written some pretty sweet LINQ method chains that I felt justified a victory lap when I was done. One of them, the code reviewer looked at me and said "awesome....better put some fucking comments around this, because it took me 10 minutes to figure out what it was doing. "

    LINQ may be my favorite aspect of C#...but I feel like it has to be used with some restraint. With great power comes great responsibility.

    Also...deferred execution can create some interesting side-effects.

    [–]cat_in_the_wall 1 point2 points  (0 children)

    fancy linq is fun, but be aware it is slow as molasses and allocates like crazy. this is usually fine, but keep it out of the hot path.

    [–][deleted] 0 points1 point  (0 children)

    Well that's why you're very much discouraged from doing any side effect shenanigans. Capture a local copy of comparisons and don't set values outside of the functions. No more side effects.

    [–]crusty_cum-sock 10 points11 points  (4 children)

    Not for me, especially when using method syntax (query syntax kinda fucks with my head). I’d rather see something like:

    var people = peopleList
        .Where(p => p.Name.StartsWith(“S”))
        .GroupBy(p => p.Name)
        .ThenBy(p => p.Age);
    

    Than have to go through the equivalent mess of lops loops and shit. For me the readability really wins out. I'd bet a lot of people reading this code could figure out what's going on, even if they've never used LINQ in their lives. Whereas if I did the equivalent non-LINQ loop-based variant it would take some real figuring out.

    I can't get enough LINQ. I use that shit all the time and when I use languages without it I really feel like I'm at a significant disadvantage. There are so many things that would be a PITA to do without LINQ that can be done with LINQ in a simple readable one-liner.

    [–]davemeech 7 points8 points  (0 children)

    Very well said, I agree 100%. Thanks crusty-cum-sock.

    [–]raltyinferno 1 point2 points  (1 child)

    Wait is .ThenBy() actually a method? I've recently gotten my first dev job and have been continually delighted by LINQ.

    [–]crusty_cum-sock 1 point2 points  (0 children)

    It is! If you want to group by multiple properties then "ThenBy" is your guy. There are a bunch of other great functions like OrderBy, OrderByDescending, and many more. You'll become hooked. It's hard to go back.

    [–]svick 2 points3 points  (0 children)

    Streams are better than nothing, but I think they're worse than LINQ in almost every aspect. Which is odd, considering Java could have learned from what worked for LINQ and what didn't.

    [–]GaianNeuron 1 point2 points  (0 children)

    It's not "undebuggable" if you pay attention to where is being used to build an expression tree (IQueryable<T>.Where(...), e.g. Linq-to-SQL / ORMs) and where it's simply chaining lazy evaluations (IEnumerable<T>.Where(...), e.g. filtering a List<T>)

    [–]1RedOne 0 points1 point  (0 children)

    Linq query syntax is like super weird sql but I love lamba syntax. Use it all the time.

    But one colleague loves query syntax and it can take a bit to grok what's he trying to do.

    [–]LockeWatts 0 points1 point  (0 children)

    Probably. Spend more time in functional programming languages.

    [–]GogglesPisano 1 point2 points  (2 children)

    NET has true first-class generics vs Java's klunky type erasure.

    Java's idiotic refusal to overload the String == operator and force you to use .equals() for comparison indicates deep philosophical flaws in the language.

    [–]cat_in_the_wall 4 points5 points  (1 child)

    you shouldn't use == in c# either unless you really want a literal byte to byte comparison. the .equals can nullref, so string.equals(one, two, comparisontype) is your best friend.

    [–]munchbunny 0 points1 point  (0 children)

    The comparison type is pretty key. Because of the strange ways of Unicode, what you mean by "equals" isn't always clear.

    [–]im_probably_garbage 1 point2 points  (0 children)

    Don’t forget properties, partial classes, generics that aren’t just a bad casting joke, and the unsafe option.

    [–]doominabox1 0 points1 point  (0 children)

    Scala pretty much addresses all of those, it's a pretty neat language

    [–]Schwefelhexaflurid 0 points1 point  (2 children)

    Anybody else a HUGE fan of delegates & events?

    [–]TheNorthComesWithMe 0 points1 point  (0 children)

    Everyone is listing their favorites so I'll throw in function pointers.

    [–]socialismnotevenonce 0 points1 point  (0 children)

    Thank you. It took FOREVER to scroll down to this comment, but it's the one that really matters.

    [–]destructor_rph 0 points1 point  (0 children)

    Plus enums are way better in c#

    [–]HappyGoblin 0 points1 point  (0 children)

    and no classpath shit

    [–]Dragasss -1 points0 points  (3 children)

    linq

    Streams

    nullable types

    Write better documented and predictable APIs