产生大量具有相同的功能浮动结构类型(System.Single)

问题描述 投票:3回答:2

我创建了一个代码库,我在很大程度上依赖于float结构。但是浮动可能意味着什么。秒,米,弧度,基洛级潜艇,米每秒,每秒等弧度....正确的命名会有所帮助,但它仍然很容易混为一谈。于是,我开始写这结构包裹的浮动,每个单位。但它变得越来越繁琐的编写结构如下:

  • 存储他们的底层浮点值
  • 所有的操作者(<,<=,>,> =,==,=,! - ,+,*,/)
  • 一个适当的Equals,GetHashCode的,和ToString方法
  • 在IEquatable接口的实现

什么是产生这样的结构,这样我就不必维护这么多的代码最简单的方法?

奖金的问题:在这样一种方式,我,仍然能够增加一些特殊的运营商。例如,我想补充一点,变成Meters / SecondsMetersPerSecond操作。

编辑:我在.Net框架4.7和C#语言水平7.3

这里是我的榜样Seconds结构。正如你能想象的仪表结构看起来完全一样。

public struct Seconds : IEquatable<Seconds>
{
    public Seconds(float value)
    {
        this.Value = value;
    }

    public float Value { get; }

    public static implicit operator Seconds(float value) => new Seconds(value);

    public static implicit operator Seconds(TimeSpan value) => new Seconds((float)value.TotalSeconds);

    public static Seconds operator +(Seconds a, Seconds b) => new Seconds(a.Value + b.Value);

    public static Seconds operator -(Seconds a, Seconds b) => new Seconds(a.Value - b.Value);

    public static bool operator >(Seconds a, Seconds b) => a.Value > b.Value;

    public static bool operator <(Seconds a, Seconds b) => a.Value < b.Value;

    public static bool operator >=(Seconds a, Seconds b) => a.Value >= b.Value;

    public static bool operator <=(Seconds a, Seconds b) => a.Value <= b.Value;

    public static bool operator ==(Seconds a, Seconds b) => a.Equals(b);

    public static bool operator !=(Seconds a, Seconds b) => !a.Equals(b);

    public override int GetHashCode() => this.Value.GetHashCode();

    public override bool Equals(object obj)
    {
        if (obj is Seconds)
        {
            return this.Equals((Seconds)obj);
        }

        return false;
    }

    public bool Equals(Seconds other) => other.Value == this.Value;

    public override string ToString() => $"{this.Value.ToString("F2", CultureInfo.InvariantCulture)}s";
}   
c# code-generation
2个回答
1
投票

尝试在F#Units of Measure功能。它强制措施的单位在编译时,不会影响性能。在F#制成组件可如果公共表面保持简单容易地从C#使用。量度拍打到浮动单位汇总于IL到System.Double。

至于奖金而言,计量单位是维护和编译器验证。如果米被秒之分,其结果将是在米每秒。


1
投票

如果你想留在C#中,你可以使用一个简单的Yellicode模板来生成样板代码(使用位打字稿的)。下面是产生子结构(struct-types.template.ts)的模板。

import { Generator, TextWriter } from '@yellicode/templating';
import { CSharpWriter } from '@yellicode/csharp';

var structNames = ['Seconds', 'Meters']; // add more names here 

Generator.generate({ outputFile: './structs.cs' }, (output: TextWriter) => {
    var csharp = new CSharpWriter(output);
    structNames.forEach(structName => {     
        const struct: StructDefinition = { name: structName, accessModifier: 'public', isPartial: true, implements: [`IEquatable<${structName}>`] } as StructDefinition;
        csharp.writeStructBlock(struct, () => {
            // Ctor            
            csharp.writeMethodBlock({ isConstructor: true, name: structName, accessModifier: 'public', parameters: [{ typeName: 'float', name: 'value' }] }, () => {
                csharp.writeLine('this.Value = value;');
            });
            csharp.writeLine();
            // Value            
            csharp.writeAutoProperty({ typeName: 'float', name: 'value', accessModifier: 'public', hasGetter: true });
            csharp.writeLine();
            // Operators 
            csharp.writeLine(`public static implicit operator ${structName}(float value) => new ${structName}(value);`);
            csharp.writeLine();
            // ... other operators omitted for brevity, type-specific conversion operators would be in a partial file
            // Methods
            csharp.writeLine('public override int GetHashCode() => this.Value.GetHashCode();');
            csharp.writeLine();
            // ... other methods omitted for brevity
        })
        csharp.writeLine();
    })
}); 

配置文件(codegenconfig.json)应如下所示:

{
    "compileTypeScript": true,
    "templates": [
        {
           "templateFile": "struct-types.template.ts"
        }
    ]
}

快速启动(请确保您已经安装NPM,然后打开命令提示符):

  1. npm install @yellicode/cli -g
  2. 创建上述文件的目录,并运行npm init -y
  3. npm install --save-dev @yellicode/templating @yellicode/csharp
  4. 运行yellicode --watch可以生成代码。

如果你想为每一个结构单独的输出文件,开始与structNames.forEach(..循环,并呼吁Generator.generate(...每个结构。

© www.soinside.com 2019 - 2024. All rights reserved.