C#, immutability and public readonly fields

拜拜、爱过 提交于 2019-12-02 23:26:38
Mark Byers

It is an obvious omission from properties that you cannot write something like:

public T2 Item2 { get; readonly set; } 

I'm not even sure readonly is the best word to use to mean "can only be set in the constructor", but that's what we're stuck with.

This is actually a feature that many people have requested, so let's hope that it will be introduced in a hypothetical new version of C# some time soon.

See this related question.

C# 6.0 now supports auto-property initializers.

The auto-property initializer allows assignment of properties directly within their declaration. For read-only properties, it takes care of all the ceremony required to ensure the property is immutable.

You can initialize read-only properties in constructor or using auto-initializer

public class Customer
{
    public Customer3(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
    public string FirstName { get; }
    public string LastName { get; }
    public string Company { get; } = "Microsoft";
}

var customer = new Customer("Bill", "Gates");

You can read more about auto-property initializers here

You may not need to add any logic to a setter in the future, but you may need to add logic to a getter.

That's a good-enough reason enough for me to use properties rather than exposing fields.

If I'm feeling rigorous then I'd go for full immutability (explicit readonly backing fields with exposed getters and no setters). If I'm feeling lazy then I'd probably go for "agreed immutability" (auto-properties with exposed getters and private setters).

As a standard practice I follow your 2nd example only using 'readonly' when the object is public or vulnerable to inadvertent tampering. I am using the 'agreed immutability' model in a current project building a plugin framework. Obviously, with agreed immutability, the readonly protection is removed.

Only in rare circumstances do I expose a field - public, internal, or otherwise. It just doesn't feel right unless writing a property {get;} takes more time than I'm willing to give.

The idea behind properties is that, even if you don't intend to chang them now or later, mabye you might need to in some unforseen way. Let's say you need to change the getter to do some kind of calculation, or logging. Maybe you need to add exception handling. Lots of potential reasons.

Also consider semantics. if T1 is a value type rather than a reference type, then accessing obj.Item1 returns a copy of _Item1 in the getter, while accessing Item1 without a getter would not retrieve a copy. This means that while Item1 may be immutable internally, the returned value type object isn't. I can't think of a reason why that would be a good thing, but it is a difference.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!