1

I am making a simulator for simulating interactions between planets of the solar system and asteroids etc. Seeing a lot of the code I am writing is very similar to the code I already wrote for an earlier project where I simulated oil spills, I want to use generics to reuse my old code. I have several classes that form the simulator, and one class that inhabits the simulation (celestial objects in this case), which is given as a generic type parameter. The simulator needs to know how many frames it has to store for recursive formulas, which is determined by the generic parameter.

public class Sim<T> where T : IEntity 
{
     readonly int RecursionDepth;     //need to get the value from the class passed as T

     //some more code
}

public interface IEntity 
{
     //cant require a const here, it would be a default implementation instead
     //don't want a int property with get; here as there are no guarantees about the immutability
     //and different instances may have different values.

     //some code
}

It would make sense to have this value be a constant or a static readonly field of the class used in the simulation. However, neither of these two options can be required using an interface. Sure, I can add a property in the interface definition, but as far as I am aware I cannot require it being readonly, and the same for each instance of the class. I really do not want to have to resort to the situation where it is just a random integer passed to the system, and I have to trust it is going to work out.

Are there any requirements I can set to at least have reasonable confidence in the immutability of the parameter and its egality across all instances of the class?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
DimQPire
  • 21
  • 6

1 Answers1

3

It is not possible in current C# version but there is a preview feature which allows to do exactly that - static abstract members in interfaces (proposal and generic math preview feature actively using it):

[RequiresPreviewFeatures]
public interface IEntity
{
    static abstract int RecursionDepth { get; }
}

[RequiresPreviewFeatures]
class MyEntity : IEntity
{
    public static int RecursionDepth => 1;
}

[RequiresPreviewFeatures]
public class Sim<T> where T : IEntity
{
    readonly int RecursionDepth = T.RecursionDepth;
}

To become an early adopter you will need to install nuget System.Runtime.Experimental and add set EnablePreviewFeatures to true to project settings (also latest framework and VS versions are also recommended):

<PropertyGroup>
  <EnablePreviewFeatures>true</EnablePreviewFeatures>
</PropertyGroup>
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • Thank you for your answer! I am looking forward to the release of .NET 6. Am I correct in understanding that it is impossible to enforce the value being immutable, as it may have a set accessor, or return the value of a mutable field? – DimQPire Nov 23 '21 at 09:48
  • 1
    @DimQPire Glad if it helped! JFYI.NET 6 has already been released, this is preview feature in it (i.e. it should be included in one of the next releases). As for being immutable - yes it is not possible to force the implementation to be immutable (as any other implementation which I can think of from top of my head.) – Guru Stron Nov 23 '21 at 11:40
  • Ah, that's why I was confused about whether .NET 6 was released. I had a feeling .NET 6 was released, but decided I must have been wrong when you said it was a preview feature. Turns out I was not. In this case, I hope that this feature is fuly implemented in .NET 7! – DimQPire Nov 23 '21 at 15:39