3 ms·
Yes. Especially annoying when looking up something in a const& map. The alternative approach could have been to make operator[]= and operator[] different.
by meindnoch 4y ago
Yes.
Especially annoying when looking up something in a const& map.
The alternative approach could have been to make operator[]= and operator[] different.
- tialaramex 4y agoYou couldn't quite do that, because C++ has compound operators, and they can of course be overloaded, so: foo[bar] += baz; ... needs to provide operator+= with a mutable reference to foo[bar], and a maybe immutable reference to baz.
- int_19h 4y agoSo does C#, and it simply desugars the above into (foo[bar] = foo[bar] + baz), except that "foo" and "bar" are only evaluated once.
- tialaramex 4y agoIn what version of C# do you believe C# gained overloading for the compound assignment operators ? The latest Microsoft documentation I could find claims these operators cannot be overloaded.
- int_19h 4y agoIt was always present. The reason for the claim in the docs is because they cannot be overloaded by themselves, only indirectly via overloading the binary operators that they're syntactic sugar for. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#11193-compound-assignment https://learn.microsoft.com/en-us/dotnet/csharp/language-ref... Which is actually better than C++ in more than one way. As a library author, you overload a+b, and you get a+=b for free. As a user, you know that a+=b always means the same thing as a=a+b (except for side effects) regardless of the library. Similarly, you can't overload && and || in C# directly like you can in C++, but instead you overload "operator true" and "operator false", and you get the boolean ops consistently derived from that (which means that they can short-circuit properly when overloaded, unlike in C++).
- tialaramex 4y agoI agree that the consistency is nice, but it does mean we would end up paying twice for a hash lookup in this context, the sub-expressions are only evaluated once but the actual lookup must be performed both by the getter and the setter. salaries["Jim Bob"] += 10_000; Calls the getter on salary to look up "Jim Bob", it finds maybe he's currently on 80_000, returns 80_000, we add 10_000 to that, getting 90_000 and then we call the setter on salary asking it to write 90_000 to "Jim Bob". Two lookup operations. It's also deeply unfortunate here that C# thinks "null" is both a plausible value for common types and a good way to distinguish lookup failure. So it's possible either that Jim Bob's salary literally is null for some insane reason or that Jim Bob wasn't on the payroll, and the effects here are identical. The extra lookup would not be acceptable in C++ or Rust, though that feels much more reasonable in a language like C# or Go -- paying a little performance to buy nicer ergonomics. The needlessly dangerous API shape on the other hand is very C++ and ought not to exist in C#.
- int_19h 4y agoC# does not attach any special meaning to null in the context of lookup, nor does it allow it by default even for reference types (assuming that you're compiling with nullability checks on, which has been the default for years), so I'm not quite sure what you're referring to. The standard way to indicate a failed lookup in C# is to throw an exception. But, yes, it is true that you end up needing double lookup when combining compound assignment with indexing.
- tialaramex 4y ago> C# does not attach any special meaning to null in the context of lookup Lots of C# APIs do, in fact return null from Index (ie the [] operator) for "Not found", you're clearly writing much newer .NET code and so you're using a modern generic container which can't do this (because its return type can't be null) > nor does it allow it by default even for reference types (assuming that you're compiling with nullability checks on, which has been the default for years) My emphasis. I believe the default you're talking about starts in .NET 6 in late 2021. I don't think "since late 2021" qualifies as "for years". C# Code I write from scratch does have nullability checks because I'd prefer to be in a language where "Null reference" isn't a thing, and this is as close as C# gets - but I maintain tonnes of code that was written three, five, even ten years ago.