关于c#:扩展.NET类型系统,以便编译器在某些情况下强制执行原始值的语义含义

Extending the .NET type system so the compiler enforces semantic meaning of primitive values in certain cases

我现在正在开发一个系统,它处理具有相同基本.NET类型(double/string/int)的语义不同的值之间的大量转换。这意味着,通过不转换或转换太多次,您可能会对正在使用的"语义类型"感到困惑。理想情况下,如果我试图使用一个在语义上没有意义的值,我希望编译器发出一个警告/错误。

一些例子表明我所指的是:

  • 角度可以用度数或弧度表示,但两者都用double表示。
  • 矢量位置可以是局部/全局坐标,但两者都由Vector3D结构表示。
  • 假设一个SQL库接受各种查询参数作为字符串。最好有一种方法来强制只允许在运行时传入干净的字符串,而获得干净字符串的唯一方法是通过一些防止SQL注入攻击的逻辑。

我相信F有一个编译时的解决方案(称为度量单位),我想在C中做一些类似的工作,尽管我不需要F中度量单位提供的维度分析。

我相信C++可以用EDCOX1 2来实现这一点(虽然我不是C++专家)。

显而易见的解决方案是将double/string/无论如何包装成一个新的类型,以提供编译器需要的类型信息。我很好奇是否有人有其他的解决方案。如果您确实认为包装是唯一/最好的方法,那么请探讨模式的一些缺点(以及我没有提到的任何优点),我特别关注运行时计算中抽象的原始数字类型的性能,因此无论我提出什么解决方案,无论是在内存分配方面,都必须是轻量级的。呼叫调度。


我想您可以创建两个不同的结构来强制类型检查。在下面的代码中,我添加了一个从弧度到double的隐式强制转换和一个从degress到弧度的显式强制转换。您可以使用您喜欢的任何一组隐式和显式操作符,但是我认为我在这里定义的那些操作符会很好地工作,因为弧度结构可以直接传递到Math函数中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;    
  }
}


我真的很感兴趣编译器在混合弧度和度数时如何给出警告。它们都是双份的吗?你在OOP世界,所以你应该走这条路。两个建议:

  • 内部只使用一个单位,我认为弧度更好。然后只在输入/输出时转换。
  • 创建结构DegreeRadian并定义转换规则。或者创建类"angle",并在那里保存有关单位和转换的所有信息。

  • 我从来没有在C中找到一个令人满意的解决方案。似乎类型系统不是为这个用例设计的。如果我现在有同样的需求,我会研究f度量单位方法。