Udostępnij za pośrednictwem


C# 7 Series, Part 6: Read-only structs

C# 7 Series

Part 1: Value Tuples
Part 2: Async Main
Part 3: Default Literals
Part 4: Discards
Part 5: Private Protected
Part 6: (This article) Read-only structs

Background

In .NET world, there are two basic types: reference types and value types. To be short, Reference types are classes that can be inherited/extended, when passing reference type objects, a “pointer” is passed; value types are structs that cannot be inherited/extended, when passing value type objects, a “copy” is passed.

A struct in C# is a value type, and it is “internally inherited” from System.ValueType. (I said no inheritance between structs.)

When use structs in arguments, a copy of the struct is generated, using structs may be efficient because it reduces the times for heap object allocation.

In many scenarios, developers use structs as an efficient way to pass values, such as a return object from a method, or a basic data structure that would be used across the application.

Read-only structs

A read-only struct is a struct whose public members are read-only, as well as the “this” parameter.

Take a look at the following declaration:

 public struct S
{
    public int Age { get; set; }
    public string Name { get; set; }

    public S(int age, string name)
    {
        this.Age = age;
        this.Name = name;
    }

    public S(S other)
    {
        this = other;
    }

    public S Replace(S other)
    {
        S value = this;
        this = other;
        return value;
    }
}

As you can see, I get full access to the declared property Age and Name, I also get access to this parameter so I can replace the instance with another instance of S.

If I add the readonly modifier to the declaration, My access will be limited:

  • All members (properties, fields) must be read-only;
  • I’ll need to initialize the members in the public parameterized constructor;
  • “this” parameter will be read-only in other place except in constructor.
  • You cannot define “field-like” events;

The below screenshot shows what things need to be fixed for the readonly struct.

image

Below is the fixed code:

 public readonly struct S
{
    public int Age { get; }
    public string Name { get; }

    public S(int age, string name)
    {
        this.Age = age;
        this.Name = name;
    }

    public S(S other)
    {
        this = other;
    }
}

You can initialize new instances of S as you usually do. But then you cannot modify any members with any instance. You should always call the parameterized (not parameterless) constructor in order to initialize the instance object properly, otherwise you will get a default initialization of the instance (all members are defaulted to initial values of the member type.)

 private static void Test()
{
    S s = new S(18, "Anna");
    ref S other = ref s;
    other = new S(other);
    bool equal = s.Equals(other); // true.
}

Conclusion

Read-only structs is a convenient feature that can help to protect your values from unintended modifications outside of your control; in combination with other new features (for example, ref structs and in parameters,) it will make your C# code targeting to low level programming easier. In the next few posts, I will explain all these new things. Please note that you will need C# 7.2 to work with this feature, which is available in Visual Studio 2017.5 Preview 4 or later.

Comments

  • Anonymous
    November 22, 2017
    Is C# 7.2 'ready to go'? I thought the idea going forwards with C# was that it was release out-of-band, i.e. separate from the Visual Studio releases...?
  • Anonymous
    November 27, 2017
    I guess it is fair to say that structs are properly inherited from System.ValueType and it does not count as an "inheritance between structs" - ironically enough, System.ValueType is a reference type :)