News for hackers. Stuff that matters.
Re:New Features in C# 7.0 by pmarreck on Thursday March 09, 2017 @11:24PM (#13836362)
> Out variables

This is pretty much a terrible language design idea. (Not the "out int x" change, but the whole idea of "out" in an argument list to begin with to indicate values coming out via the arguments.)

The path out of mutable argument bug-hell is not to declare that the values of some argument variables will intentionally get changed by the function in the scope where it is called. It is to make arguments immutable (like they are in the traditional mathy definition of "function"), period, and allow multiple assignment to the function call. What I mean is that, conceptually, ideally, values and state should only flow into the function arguments and only back out of the function call itself.

So for example instead of

> p.GetCoordinates(out int x, out int y);

I think the following would lead to reduced cognitive load and thus fewer bugs:

> int x, int y = p.GetCoordinates;

or even better (color me biased by Erlang/Elixir):

> {x, y} = p.GetCoordinates; # as a pattern match

Instead of a smoothly mentally-traceable flow of values into function arguments and out of function returns, we have this monstrosity of conflating mutable arguments (where values go in and then come back out changed in the scope of the function call) with this "out int x" business which seems to be indicating it intends to "push values upstream", as it were.

Re:New Features in C# 7.0 by louthy on Thursday March 09, 2017 @11:41PM (#13836430)
> int x, int y = p.GetCoordinates;

Obviously this can be done with the new tuple syntax, but in general I totally agree with everything you've said about 'out'. It is one of the ugliest language features ever, sometimes I wish MS would just say "To hell with backwards compatibility", and throw 'out' on the fire.

    // Function definition
    (int x, int y) GetCoordinates() =>
        (100, 200);

    // Invocation
    var (x, y) = GetCoordinates();
Re:New Features in C# 7.0 by pmarreck on Thursday March 09, 2017 @11:57PM (#13836493)
Well, to be charitable, fortunately you can use a style like you propose where values only flow as I've indicated... but you'd still have to contend with OPC (Other People's Code) and if the language allows it, you just know it will turn up somewhere and ruin your day! ;)
Re:New Features in C# 7.0 by louthy on Friday March 10, 2017 @12:05AM (#13836523)
Indeed. Although 'out' is rare, it occasionally does ruin my day. So I have created a set of extension methods [1][2] to remove them from my life (because it does physically enrage me whenever I see the need to use it).

[1] https://github.com/louthy/language-ext/blob/master/LanguageE...

[2] https://github.com/louthy/language-ext/blob/daa5a10028e9637b...

Re:New Features in C# 7.0 by mercurial on Friday March 10, 2017 @12:49AM (#13836676)
> but you'd still have to contend with OPC (Other People's Code) and if the language allows it, you just know it will turn up somewhere and ruin your day! ;)

Yes, like the standard library's Dictionary.TryGetValue()...

Re:New Features in C# 7.0 by yread on Friday March 10, 2017 @03:44AM (#13837223)
you can do

if (dict.ContainsKey(key)) return dict[key] else return null;

the only place where you can't avoid them are TryParse. And there it sort of makes sense - the value is sort of side effect

Re:New Features in C# 7.0 by louthy on Friday March 10, 2017 @06:43AM (#13837879)
> if (dict.ContainsKey(key)) return dict[key] else return null;

Which isn't thread-safe. So it's not always a better option.

Re:New Features in C# 7.0 by ygra on Friday March 10, 2017 @08:54AM (#13838546)
But Dictionary<TKey,TValue> isn't thread-safe anyway, unless not modified.
Re:New Features in C# 7.0 by louthy on Friday March 10, 2017 @09:04AM (#13838612)
Calling TryGetValue will either return a value or not. Calling ContainsKey, followed by an index read can lead to a race condition that means the value isn't there any more.
Re:New Features in C# 7.0 by ygra on Friday March 10, 2017 @10:21AM (#13839219)
If I'm reading the source correctly you could still get the bucket index and before you return true and the value, have that value removed from the dictionary. There is no synchronization going on, so concurrent modifications are just as much a problem with TryGetValue as with other approaches. TryGetValue is not atomic either.
Re:New Features in C# 7.0 by louthy on Friday March 10, 2017 @01:06PM (#13840642)
Ok, fair enough. My mistake. Glad I don't use the BCL collection types any more and stick to immutable maps, lists, and sets :)
Re:New Features in C# 7.0 by pmarreck on Friday March 10, 2017 @10:04AM (#13839076)
This is correct (and unfortunate).
Re:New Features in C# 7.0 by mrits on Friday March 10, 2017 @12:39AM (#13836645)
I feel like out was important for marshalling into C++ code?
Re:New Features in C# 7.0 by tdestan on Thursday March 09, 2017 @11:36PM (#13836409)
Did you read far enough to see the tuple return value syntax?

  var (first, middle, last) = LookupName(id1);
Seems like what you're suggesting, no?
Re:New Features in C# 7.0 by pmarreck on Thursday March 09, 2017 @11:39PM (#13836424)
Better. But the id1 argument can still be mutated by LookupName in this scope, no?
Re:New Features in C# 7.0 by tdestan on Thursday March 09, 2017 @11:46PM (#13836450)
Depends.

Based on my hazy memory of C#, if id is a struct/value type it is copied, but if it is a class type, there's nothing preventing the method call from mutating it.

Which is unfortunate, I agree.

Re:New Features in C# 7.0 by louthy on Thursday March 09, 2017 @11:59PM (#13836504)
> here's nothing preventing the method call from mutating it.

There is, the class could be immutable.

    public class Vector
    {
        public readonly int X;
        public readonly int Y;

        public Vector(int x, int y) 
        {
            X = x;
            Y = y;
        }

        public Vector With(int? X = null, int? Y = null) =>
            new Vector(X ?? this.X, Y ?? this.Y);
    }
I believe record-types are proposed for the next release of C#.
Re:New Features in C# 7.0 by benaadams on Friday March 10, 2017 @04:41AM (#13837446)
Mutable class with immutable struct wrapper would be better on allocations; then pass in the struct wrapper.
Re:New Features in C# 7.0 by ttd on Friday March 10, 2017 @05:21AM (#13837589)
This is correct. One of the things I miss coming from C++ is the ability to pass const references. Then you have the advantage of passing a reference instead of copying an object, and the compiler enforces immutability in the function using the reference.

On a similar note, I also really miss the ability to define const class methods (i.e. instance methods which do not modify the instance on which they are invoked). Although, perhaps get-only accessors fill part of that niche in C#.

Re:New Features in C# 7.0 by divanvisagie on Thursday March 09, 2017 @11:56PM (#13836482)
This language is called C# because you know... C. out variables are there because people were used to coding like this and now that it's there it would just break things to remove it from the language, so you might as well just make it a bit cleaner.
Re:New Features in C# 7.0 by pmarreck on Friday March 10, 2017 @12:01AM (#13836507)
Fair enough.

But people should stop coding like this. For the love of all that is good and binary, don't use arguments to mutate values in the same scope. Just return them and reassign them. That way, state flow is always in via the arguments and out via the return value(s). Without this discipline, you will have a hodgepodge of "value flows" and that complexity will kill you when debugging. When new values can be spit out both by function returns and function arguments... Hold on, I have to take an aspirin

I know that a lot of OO/procedural languages permit you to do this (unfortunately). Don't!

Re:New Features in C# 7.0 by divanvisagie on Friday March 10, 2017 @12:40AM (#13836649)
Yeah , I get you , this coding style is horrible. I personally try to avoid mutating things as much as possible. I wonder how long we will have these old artifacts around before we decide that things need to move to newer langs like F# instead of tacking new features onto the existing lingua franca of .NET.
Re:New Features in C# 7.0 by gokhan on Friday March 10, 2017 @01:42AM (#13836831)
Been using c# since the day 1, almost never seen someone designing from the ground up with out parameters for the last 10 years. They're not that common. I guess it looks like a favorite feature in the document because it takes the largest part of it, it's not.
Re:New Features in C# 7.0 by tigershark on Friday March 10, 2017 @10:54PM (#13844126)
Never used a concurrent dictionary or an IDictionary trying to be sanely efficient using TryGetValue instead of ContainsKey followed by a call to the accessor? I can't really believe that you started using c# from the day one and you never encountered an hot code path with a TryGetValue. Of course it gets much worse when you have millions of objects, but even with hundred of thousands it is kind of noticeable. Unless you don't care about caching at all, but that is a complete different kind of dragons'lair...
Re:New Features in C# 7.0 by mercurial on Friday March 10, 2017 @12:52AM (#13836686)
> out variables are there because people were used to coding like this

This does not invalidate OP's point that it is terrible design. You do not need to take every bad idea in older languages in the name of familiarity.

Re:New Features in C# 7.0 by olavk on Friday March 10, 2017 @02:29AM (#13836975)
I believe it is for interoperability with code in these languages, not just familiarity. That said, the BCL also use out parameters in a few places (the TryParse methods) which arguable set a bad precedent.