通过自定义结构类型校对原语.NET值类型:值得努力吗?

sta*_*ica 14 c# struct primitive-types type-safety implicit-conversion

我正在考虑通过将它们包装在自定义中来使原始.NET值类型更加类型安全并且更"自我记录" struct.但是,我想知道它是否真的值得在现实世界的软件中付出努力.

(这种"努力"可以在下面看到:必须一次又一次地应用相同的代码模式.我们声明structs,因此不能使用继承来删除代码重复;并且由于必须声明重载的运算符static,因此必须定义它们对于每种类型单独.)

拿这个(公平地说是微不足道的)例子:

struct Area
{
    public static implicit operator Area(double x) { return new Area(x); }
    public static implicit operator double(Area area) { return area.x; }

    private Area(double x) { this.x = x; }
    private readonly double x;
}

struct Length
{
    public static implicit operator Length(double x) { return new Length(x); }
    public static implicit operator double(Length length) { return length.x; }

    private Length(double x) { this.x = x; }
    private readonly double x;
}
Run Code Online (Sandbox Code Playgroud)

双方AreaLength基本上都是double,但有特定的含义扩大它.如果你定义了一个方法,比如...

    Area CalculateAreaOfRectangleWith(Length width, Length height)
Run Code Online (Sandbox Code Playgroud)

......不可能直接通过Area.到现在为止还挺好.

但是:你可以很容易简单地通过铸造回避这个明显改善类型安全Areadouble,或通过临时存储Area在一个double变量中,然后通过该入其中的方法Length预计:

    Area a = 10.0;

    double aWithEvilPowers = a;
    … = CalculateAreaOfRectangleWith( (double)a, aWithEvilPowers );
Run Code Online (Sandbox Code Playgroud)

问题:这里有没有人有struct在现实世界/生产软件中广泛使用此类自定义类型的经验?如果是这样:

  • 自定义structs 中原始值类型的包装是否直接导致更少的错误,或更易于维护的代码,或给予任何其他主要优势?

  • 或者定制struct的好处太小,无法在实践中使用?


PS:自从我提出这个问题以来已经过了大约5年.我发布了自那时以来作为单独答案的一些经验.

Joh*_*hnD 11

几年前我在一个项目中做到了这一点,结果好坏参半.就我而言,它有助于跟踪不同类型的ID,并在使用错误类型的ID时产生编译时错误.而且我可以回想起它在很多时候会阻止实际的错误.所以,这是好的一面.从消极方面来说,对于其他开发人员来说这并不是非常直观 - 这种方法并不常见,我认为其他开发人员对所有这些新类型的混淆感到困惑.另外,我似乎记得我们在序列化方面遇到了一些问题,但我记不起细节了(对不起).

所以,如果你要走这条路,我会推荐几件事:

1)确保先与团队中的其他人交谈,解释你想要完成的事情,看看你是否可以从每个人那里得到"买进".如果人们不理解这个价值,那么你将不断地与"所有这些额外代码的重点是什么"的心态作斗争?

2)考虑使用像T4这样的工具生成样板代码.它将使代码的维护更加容易.在我的例子中,我们有大约十几种这样的类型,并且代码生成路由使得更改变得更容易,更不容易出错.

那是我的经历.祝好运!

约翰