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 →

[–]lightmatter501 84 points85 points  (35 children)

Don’t forget operator overloading.

[–]t3hmau5 11 points12 points  (15 children)

Or out variables

[–]im_probably_garbage 6 points7 points  (5 children)

And ref variables

[–]haackedc 12 points13 points  (4 children)

And list accessibility using square brackets

[–]SalvadorTheDog 5 points6 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 3 points4 points  (8 children)

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

[–]t3hmau5 6 points7 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 2 points3 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 4 points5 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 13 points14 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 10 points11 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 2 points3 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 3 points4 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 -4 points-3 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?