I want a Type
that is "for" a certain number, and another Type
for another number. But I don't want to have to manually define a Type
for each number like Level1024
and Level1000
. I want it to be simple to instantiate an instance of the Level
class for each number, like we can do with generics where we can create a Level<string>
and a Level<int>
without needing to define a separate Level
for each of them.
Here's the idea:
Level<1024> topPlayerOf1K;
Level<1000> Abe = new Level<1000>();
topPlayerOf1K = Abe; //This should show a squiggly line in Visual Studio.
How can I achieve that or something like that?
CodePudding user response:
Numbers literals are not considered types in C# like they are in TypeScript, and cannot be used as generic parameters like template parameters in C .
At the minimum you would have to create types for each of the number literals you want to use. The approach could look like this:
interface IConstantInt { int Value { get; } }
class ConstantInt1000 : IConstantInt { public int Value => 1000; }
class ConstantInt1024 : IConstantInt { public int Value => 1024; }
class Level<TConstantInt> where TConstantInt : IConstantInt { }
var level1000 = new Level<ConstantInt1000>();
var level1024 = new Level<ConstantInt1024>();
It would be good to autogenerate this code if you're going to have many of those. This is not a great solution, but without knowing more about your program and what kind of errors you're trying to prevent, in the abstract, that's a way that you could encode number literals in the type system.
Edit: here's one way that you could access the value inside the class:
class Level<TConstantInt> where TConstantInt : IConstantInt
{
readonly int _intValue;
public Level(TConstantInt constantInt) =>
_intValue = constantInt.Value;
}
class Level
{
// Optional utility factory method, helps with type inference
public static Level<TConstantInt> Create<TConstantInt>(TConstantInt constantInt)
where TConstantInt : IConstantInt =>
new(constantInt);
}
// Now creation looks like this:
var level1000 = Level.Create(new ConstantInt1000());
var level1024 = Level.Create(new ConstantInt1024());