我们最近意识到我们想要将所有项目从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。
感谢。
答案 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的CodeFormatter
(https://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;
希望这有帮助