使用泛型在编译时强制执行有效的结构

时间:2012-06-23 00:10:51

标签: c# generics types

通过滥用c#中的类型系统,我可以创建代码,编译器将强制执行规则,以确保不执行不可能的操作。在下面的代码中,它特定于矩阵乘法。

显然,下面的内容完全不切实际/错误,但是我们之所以在c#中有这样的原因,我可以在其中定义类似Matrix< 2,2>的类型。并让编译器确保安全吗?

此外,在任何主流语言中都存在这样的事情吗?我怀疑使用C ++中的元编程可以实现这样的事情吗?

public abstract class MatrixDimension { }

public class One : MatrixDimension { }
public class Two : MatrixDimension { }
public class Three : MatrixDimension { }

public class Matrix<TRow, TCol>
    where TRow : MatrixDimension
    where TCol : MatrixDimension
{

// matrix mult. rule. N×M * M×P  = N×P 
    public Matrix<TRow, T_RHSCol> Mult<T_RHSCol>(Matrix<TCol, T_RHSCol> rhs)
        where T_RHSCol : MatrixDimension
    { return null;}
}

public class TwoByTwo : Matrix<Two, Two> { }

public void Main()
{
    var twoByTwo = new Matrix<Two, Two>();
    var oneByTwo = new Matrix<One, Two>();
    var twoByThree = new Matrix<Two, Three>();
    var threeByTwo = new Matrix<Three, Two>();
    var _twoByTwo = new TwoByTwo();

    var _2x2 = twoByTwo.Mult(twoByTwo);
    var _1x2 = oneByTwo.Mult(twoByTwo);
    var _3x3 = twoByThree.Mult(threeByTwo);

    var _2x2_ = _twoByTwo.Mult(twoByTwo);

    var invalid = twoByThree.Mult(twoByThree); // compile fails, as expected
}

1 个答案:

答案 0 :(得分:2)

F#支持语言中内置的units of measure - 基本上在CLR类型之上创建一个更丰富的类型系统,就像你开始使用泛型一样。

一种不同的,我认为是补充的方法来构建一个更丰富的类型系统(我在我自己的软件中使用以确保核心模块的高可靠性和正确性)是将编译器与< em> theorem prover 保证满足方法和属性(以及类不变量)的前后条件。

这在主流语言中很有名,例如SPARKAdaJava (via JML extensions) - 由于Microsoft Research对Code Contracts功能的研究,它也适用于C#。 (我正在大量使用。我强烈建议您观看MSR页面上链接的视频,这是开始使用这些工具的最佳方式。)

来自MSR的 cccheck 静态检查程序可以在Visual Studio的后台运行,并且会在代码编辑器中为您提供错误和信息性消息以及(我认为紫色)波浪形。

如果您想沿着这条路走下去,请查看Code Contracts MSDN forum以获取支持 - 这是大多数用户似乎都会在这里停留的地方。