An extension of a .NET type system, so the compiler in certain cases provides the semantic meaning of primitive values

I'm working on system development right now, when it comes to many conversions between semantically different values ​​that have the same primitive .NET type (double / string / int). This means that you can get confused about which "semantic type" you use, either without converting or converting too many times. Ideally, I would like the compiler to give a warning / error if I try to use a value in which it semantically makes no sense.

Some examples to indicate what I mean:

  • Angles can be in degrees or radians, but both are represented by double .
  • Vector positions can be in local / global coordinates, but both of them are represented by the Vector3D structure.
  • Imagine a SQL library that accepts various query parameters as strings. It would be nice to have a way of ensuring that only clean lines are allowed at run time, and the only way to get a clean line was to go through some SQL attack prevention logic.

I believe that F # has a compilation solution for this (called units.) I would like to do something similar in C #, although I do not need dimensional analysis, which offers units in F #.

I believe that C ++ can achieve this using typedef (although I am not an expert in C ++).

The obvious solution is to wrap double / string / whatever in the new type to provide it with the type information needed by the compiler. I am curious if anyone has an alternative solution. If you think packaging is the only / best way, then please go to some of the drawbacks of the template (and any changes that I haven't mentioned as well.) I'm particularly concerned about the performance of abstract primitive numeric types on my run-time calculations , therefore, any solution I came up with should be easy both in terms of memory allocation and sending a call.

+6
performance c # type-systems
source share
3 answers

I'm really curious how the compiler warns when you mix radians and degrees. Do they both double? You are in the OOP world, so you should go this route. Two suggestions:

  • Use only one block inside, I think radians are better. Then convert only input / output. \
  • Create Degree , Radian structures and define conversion rules. Or create the "Angle" class and save all information about devices and conversions.
+3
source share

I think you could create two different structures to force type checking. In the following code, I added implicit selection from radians to a double and explicit cast from degress to radians. You can use any set of implicit and explicit operators that you like, but I think those that I defined here will work well, since the Radians structure can be passed directly to the Math functions.

 public struct Degrees { private double m_Value; public static explicit operator Radians(Degrees rhs) { return rhs.m_Value * (Math.Pi / 180); } } public struct Radians { private double m_Value; public static implicit operator double(Radians rhs) { return rhs.m_Value; } } 
+3
source share

I have never found a satisfactory solution to this problem in C #. It just seems that the type system was not designed for this use case. If I had the same need now, I would consider the F # units approach.

0
source share

All Articles