2 added 142 characters in body
source | link

You can enforce consistency to a certain degree if you putby making the Segment constructor internal, and putting the Path and Segment classes in a different DLL than your main application code:

// In one DLL
public class Path
{
    private List<Segment> segments;

    public IEnumerable<Segment> Segments => segments;

    public Segment AddSegment(int property)
    {
        var segment = new Segment(this, property);

        segments.Add(segment);

        return segment;
    }
}

public class Segment
{
    public int Property { get; private set; }
    public Path Path { get; private set; }

    internal Segment(Path path, int property)
    {
        Path = path ?? throw new ArgumentNullException(nameof(path));
        Property = property;
    }
}

Then use the Path class in another DLL file:

// In another DLL

var path = new Path();
var segment1 = path.AddSegment(42);   // Compiles
var segment2 = new Segment(path, 56); // Does not compile. Constructor is internal

Because the Segment constructor is marked internal you must go through the Path.AddSegment method to create new Segment objects.

The Segment constructor is free of side effects, because the Path.AddSegment method adds the new segment to the Path's collection.

You can enforce consistency to a certain degree if you put the Path and Segment classes in a different DLL:

// In one DLL
public class Path
{
    private List<Segment> segments;

    public IEnumerable<Segment> Segments => segments;

    public Segment AddSegment(int property)
    {
        var segment = new Segment(this, property);

        segments.Add(segment);

        return segment;
    }
}

public class Segment
{
    public int Property { get; private set; }
    public Path Path { get; private set; }

    internal Segment(Path path, int property)
    {
        Path = path ?? throw new ArgumentNullException(nameof(path));
        Property = property;
    }
}

Then use the Path class in another DLL file:

// In another DLL

var path = new Path();
var segment1 = path.AddSegment(42);   // Compiles
var segment2 = new Segment(path, 56); // Does not compile

Because the Segment constructor is marked internal you must go through the Path.AddSegment method to create new Segment objects.

You can enforce consistency to a certain degree by making the Segment constructor internal, and putting the Path and Segment classes in a different DLL than your main application code:

// In one DLL
public class Path
{
    private List<Segment> segments;

    public IEnumerable<Segment> Segments => segments;

    public Segment AddSegment(int property)
    {
        var segment = new Segment(this, property);

        segments.Add(segment);

        return segment;
    }
}

public class Segment
{
    public int Property { get; private set; }
    public Path Path { get; private set; }

    internal Segment(Path path, int property)
    {
        Path = path ?? throw new ArgumentNullException(nameof(path));
        Property = property;
    }
}

Then use the Path class in another DLL file:

// In another DLL

var path = new Path();
var segment1 = path.AddSegment(42);   // Compiles
var segment2 = new Segment(path, 56); // Does not compile. Constructor is internal

Because the Segment constructor is marked internal you must go through the Path.AddSegment method to create new Segment objects.

The Segment constructor is free of side effects, because the Path.AddSegment method adds the new segment to the Path's collection.

1
source | link

You can enforce consistency to a certain degree if you put the Path and Segment classes in a different DLL:

// In one DLL
public class Path
{
    private List<Segment> segments;

    public IEnumerable<Segment> Segments => segments;

    public Segment AddSegment(int property)
    {
        var segment = new Segment(this, property);

        segments.Add(segment);

        return segment;
    }
}

public class Segment
{
    public int Property { get; private set; }
    public Path Path { get; private set; }

    internal Segment(Path path, int property)
    {
        Path = path ?? throw new ArgumentNullException(nameof(path));
        Property = property;
    }
}

Then use the Path class in another DLL file:

// In another DLL

var path = new Path();
var segment1 = path.AddSegment(42);   // Compiles
var segment2 = new Segment(path, 56); // Does not compile

Because the Segment constructor is marked internal you must go through the Path.AddSegment method to create new Segment objects.