News for hackers. Stuff that matters.
Re:The Problem with F# Evangelism by jdmichal on Wednesday August 16, 2017 @05:14PM (#15031431)
In C# 6.0 you can also make them properties instead of fields, though I have no idea if this works with your "Record" class.

    public class TestClass
    {
        public int X { get; }
        public string Y { get; }
        public Guid Z { get; }

        public TestClass(int x, string y, Guid z)
        {
            X = x;
            Y = y;
            Z = z;
        }
    }
And C# 7.0 shortens this to:

    public class TestClass(
        int X,
        string Y,
        Guid Z);
Re:The Problem with F# Evangelism by louthy on Wednesday August 16, 2017 @08:46PM (#15032705)
> In C# 6.0 you can also make them properties instead of fields

Why would I want to? It's more boilerplate for no gain. I have never understood the obsession with properties over fields. I realise that to some serialisation or interop libraries that rely on reflection to access properties it's important, but to my mind, those solutions should also support public fields. And obviously inheritance-land with interfaces, but I find writing in a functional style that interfaces tend to be a rarity rather than the default setting.

> though I have no idea if this works with your "Record" class.

Yes, field backed properties are supported in the structural equality and ordering.

> And C# 7.0 shortens this to...

It doesn't. That maybe coming in a later release, but neither C# 7.0 nor 7.1 support the record syntax.

Re:The Problem with F# Evangelism by tjalfi on Wednesday August 16, 2017 @10:49PM (#15033409)
C# 7 does allow one to shorten that class a bit further. I saw this trick in the MEAP[0] of C# in Depth.

    public class TestClass
    {
        public int X { get; }
        public string Y { get; }
        public Guid Z { get; }

        public TestClass(int x, string y, Guid z) => (X, Y, Z) = (x, y, z);
    }
Disclaimer: I don't combine expression-bodied constructors and tuple construction/deconstruction in my code. I will use either feature but the combination seems likely to annoy my coworkers. I also haven't measured the costs of this idiom.

[0] https://www.manning.com/books/c-sharp-in-depth-fourth-editio...

Re:The Problem with F# Evangelism by pjmlp on Thursday August 17, 2017 @02:22AM (#15034210)
> I have never understood the obsession with properties over fields.

Encapsulation, allowing to change the internal representation without requiring clients to update or recompile their code.

Ensuring the class invariants are always kept valid.

Re:The Problem with F# Evangelism by naasking on Thursday August 17, 2017 @04:46AM (#15034881)
> Encapsulation, allowing to change the internal representation without requiring clients to update or recompile their code

This benefit is exaggerated. In practice, classes end up being either record-like where you need visibility on all the actual fields, or they are protocol-like/more fully encapsulated with few public members and more methods. The addition of properties was a big mistake IMO.

Read/write fields should just be part of interface specifications. There is little value beyond that.

Re:The Problem with F# Evangelism by pjmlp on Thursday August 17, 2017 @06:02AM (#15035237)
> The addition of properties was a big mistake IMO.

Properties go all the way back to Smalltalk, which doesn't expose class internal data.

> Read/write fields should just be part of interface specifications. There is little value beyond that.

No because you cannot ensure their invariants, specially if more than one field needs to change at the same time.

Re:The Problem with F# Evangelism by naasking on Thursday August 17, 2017 @06:28AM (#15035363)
> Properties go all the way back to Smalltalk, which doesn't expose class internal data.

Right, because Smalltalk doesn't conflate the use of public and internal members. Properties are second class citizens on .Net, since you can't pass them as ref or out arguments, but we can't use fields which are first class citizens because they have inadequate permissions control.

Then properties exist, but also don't really exist at the reflection level, where you have to search for getters and setters by mangled name if they're private. It's a total frickin mess.

> No because you cannot ensure their invariants, specially if more than one field needs to change at the same time

Properties don't help with changing more than one field either, so I'm not what your point is.

And you can ensure invariants with field permissions, which is what I suggested. Publicly read-only but privately writable is all you need, then the values change via method invocations. Most use of properties just add permissions to field access anyway.

Read/write with default const/init-only fields should have been the default. Then you can't pass read-only fields as ref or out arguments due to permissions, not because they're second class citizens.

Re:The Problem with F# Evangelism by pjmlp on Thursday August 17, 2017 @07:06AM (#15035591)
> Properties are second class citizens on .Net, since you can't pass them as ref or out argument

There is nothing at IL level that prevents it, they can eventually lift the restriction if they feel like it.

> Properties don't help with changing more than one field either, so I'm not what your point is.

The setter can do a cascade set of changes while keeping the invariants.

Re:The Problem with F# Evangelism by naasking on Thursday August 17, 2017 @07:46AM (#15035818)
> There is nothing at IL level that prevents it, they can eventually lift the restriction if they feel like it.

While theoretically true, it will never happen. The whole point of ref/out parameters is efficient, direct pointer access to a member. This can never be made efficient for properties. The CLR GC is carefully tuned to handle internal pointers like this, so quite a bit of engineering has gone into making this efficient and safe, which means efficiency is important.

Furthermore, properties are entirely redundant with the simple change I suggested. They literally serve no purpose once you have permissions on fields, since methods cover the remaining use cases.

> The setter can do a cascade set of changes while keeping the invariants.

And so can methods. If you have mutating this much state, you should be invoking a method anyway. Properties are not the place for sophisticated behaviour.