C#float或double选择预编译

时间:2017-03-04 17:06:29

标签: c# .net types mono monodevelop

我们最近意识到我们想要将所有项目从double替换为float,同时仍然保存有时使用double的选项。

问题是:这样做的最佳做法是什么?

我们认为别名是正确的做法,但我们发现C#不支持全局别名。 以下是我们所做的别名的示例:

#if USE_FLOAT
using mFloatType = System.Single;
using mComplexType = CenterSpace.NMath.Core.FloatComplex;
using mComplexVector = CenterSpace.NMath.Core.FloatComplexVector;
using mComplexMatrix = CenterSpace.NMath.Core.FloatComplexMatrix;
using mHermitianMatrix = CenterSpace.NMath.Matrix.FloatHermitianMatrix;
#else
using mFloatType = System.Double;
using mComplexType = CenterSpace.NMath.Core.DoubleComplex;
using mComplexVector = CenterSpace.NMath.Core.DoubleComplexVector;
using mComplexMatrix = CenterSpace.NMath.Core.DoubleComplexMatrix;
using mHermitianMatrix = CenterSpace.NMath.Matrix.DoubleHermitianMatrix;
#endif

虽然USE_FLOAT是定义符号。

但是,将这段代码放在项目的每个文件中(超过500个文件)似乎完全错误,特别是在面向对象编程中。

有关如何进行此转换的任何想法吗?

如果有帮助,我们使用monodevelop 6.3和Mono 4.0。

感谢。

2 个答案:

答案 0 :(得分:0)

由于您正在处理密封类型,因此可以使用类型工厂,以便#if/#else/#endif块仅在一个文件中。

举个例子,有几种方法可以做到这一点:

using System;
#region USING_FLOAT
#if USE_FLOAT
using mFloatType = System.Single;
using mComplexType = CenterSpace.NMath.Core.FloatComplex;
using mComplexVector = CenterSpace.NMath.Core.FloatComplexVector;
using mComplexMatrix = CenterSpace.NMath.Core.FloatComplexMatrix;
using mHermitianMatrix = CenterSpace.NMath.Matrix.FloatHermitianMatrix;
#else
using mFloatType = System.Double;
using mComplexType = CenterSpace.NMath.Core.DoubleComplex;
using mComplexVector = CenterSpace.NMath.Core.DoubleComplexVector;
using mComplexMatrix = CenterSpace.NMath.Core.DoubleComplexMatrix;
using mHermitianMatrix = CenterSpace.NMath.Matrix.DoubleHermitianMatrix;
#endif
#endregion

namespace TypeFactory
{
    public static class CenterLineFactory
    {
       public static mFloatType Double { get { return new mFloatType(); } }
       public static mComplexType ComplexType { get { return new  mComplexType(); } }
       ~~~ etc ~~~
    }
}

用法:

var aFloat = CenterLineFactory.Double;
var aComplexType = CenterLineFactory.ComplexType;

但是由于事实上这是你的双重/浮动选择的事后想法,所以要求所有500个文件都需要更新,无论如何创建这5种类型......

个人:

我会使用Microsoft的CodeFormatterhttps://github.com/dotnet/codeformatter)一次批量转换所有文件,并将#if USE_FLOAT/#else/#endif块插入#region USING_FLOAT/#endregion

我通常从不使用地区,但愿意这样做。这样,您可以自动折叠USING_FLOAT区域,并将其从创建 视觉代码异味中移除。

答案 1 :(得分:0)

一种方法可能是使用组合而不是继承,并创建一个SingleOrDouble结构,如下所示,它根据构建符号模仿Single或Double的行为。

您仍需要更新所有500个文件,但只需查找所有 System.Single 并替换为 SingleOrDouble

    #if USE_FLOAT

public struct SingleOrDouble : IComparable
    , IComparable<Single>, IEquatable<Single> {

    public Single Value;

    private SingleOrDouble(float f) {
        Value = f;
    }

    public static implicit operator float(SingleOrDouble s) {
        return s.Value;
    }
    public static implicit operator SingleOrDouble(float f) {
        return new SingleOrDouble(f);
    }

    public int CompareTo(float other) {
        return Value.CompareTo(other);
    }

    public bool Equals(float other) {
        return Value.Equals(other);
    }

    public static bool IsInfinity(float f) {
        return Single.IsInfinity(f);
    }



    #else

public struct SingleOrDouble : IComparable
   , IComparable<Double>, IEquatable<Double> {

    public Double Value { get; set; }

    private SingleOrDouble(double d) {
        Value = d;
    }

    public static implicit operator double(SingleOrDouble d) {
        return d.Value;
    }
    public static implicit operator SingleOrDouble(double d) {
        return new SingleOrDouble(d);
    }

    public int CompareTo(double other) {
        return Value.CompareTo(other);
    }

    public bool Equals(double other) {
        return Value.Equals(other);
    }


    #endif
    public int CompareTo(object obj) {
        return Value.CompareTo(obj);
    }

    public TypeCode GetTypeCode() {
        return Value.GetTypeCode();
    }

    public static bool IsInfinity(double d) {
        return Double.IsInfinity(d);
    }


}

请注意,上述课程尚未完成,但您明白了。

类变量可以初始化如下

    SingleOrDouble s = 100.5;

与初始化普通双重没有区别

    double d = 100.5;

希望这有帮助