/ReadonlyStructGenerator

A source generator of readonly struct.

Primary LanguageC#

ReadonlyStructGenerator

A source generator of readonly struct.

Usage

  1. Declare the structure with partial and add the properties with the init accessor.
  2. Add the ReadonlyStructGenerator.ReadonlyStructAttribute to the struct.
[ReadonlyStructGenerator.ReadonlyStruct]
public partial struct Point
{
    public int X { get; init; }
    public int Y { get; init; }
}

After the build, the following code will be generated.

  • Struct declaration with the readonly keyword.
  • Definition of a primary constructor.
  • Implement the IEquatable<T> interface.
  • Override object.Equals(), object.GetHashCode() and object.ToString().
  • Define operator overloading (==, !=).
#nullable enable
using System;
namespace SampleConsoleApp
{
    readonly partial struct Point : IEquatable<Point>
    {
        public Point(int x,int y) => (X,Y) = (x,y);
        public bool Equals(Point other) => (X,Y) == (other.X,other.Y);
        public override bool Equals(object? obj) => (obj is Point other) && Equals(other);
        public override int GetHashCode() => HashCode.Combine(X,Y);
        public static bool operator ==(Point left, Point right) => left.Equals(right);
        public static bool operator !=(Point left, Point right) => !(left == right);
        public override string ToString() => $"{nameof(Point)}({X},{Y})";
    }
}
  • Properties that do not have an init accessor are not subject to initialization in the constructor or to equivalence comparisons.
  • If you write a constructor, it will not be generated by the SourceGenerator.
[ReadonlyStructGenerator.ReadonlyStruct]
public partial struct Vector3
{
    public float X { get; init; }
    public float Y { get; init; }
    public float Z { get; init; }

    public float Norm { get; }

    public Vector3(float x, float y, float z)
    {
        (X, Y, Z) = (x, y, z);
        Norm = (float)Math.Sqrt(X * X + Y * Y + Z * Z);
    }
}
#nullable enable
using System;
namespace SampleConsoleApp
{
    readonly partial struct Vector3 : IEquatable<Vector3>
    {
        public bool Equals(Vector3 other) => (X,Y,Z) == (other.X,other.Y,other.Z);
        public override bool Equals(object? obj) => (obj is Vector3 other) && Equals(other);
        public override int GetHashCode() => HashCode.Combine(X,Y,Z);
        public static bool operator ==(Vector3 left, Vector3 right) => left.Equals(right);
        public static bool operator !=(Vector3 left, Vector3 right) => !(left == right);
        public override string ToString() => $"{nameof(Vector3)}({X},{Y},{Z})";
    }
}