如何编写单个类以使用不同的数字类型进行多次编译?

时间:2011-07-01 15:44:45

标签: c# .net conditional-compilation

我正在尝试编写处理不同数字类型的类。我知道C#(和我一般认为.Net)没有INumber接口,所以我不能使用以下内容:

    public class Adder<T> where T:INumber
    {
        public T Add(T a, T b)
        {
            return a + b;
        }
    }

但是,没关系,因为我想避免我的每个号码的装箱/拆箱。但是,我可以为我想支持的每种类型使用条件编译:

#if FLOAT 
    public class AdderF
    {
        public float Add(float a, float b)
#else
    public class Adder
    {
        public int Add(int a, int b)
#endif
        {
            return a + b;
        }
    }

这意味着我需要编译不同的Library.dllLibraryF.dll。有没有更优雅的解决方案?

显然,在我的例子中,我可以简单地编写代码两次。但是,我想使用此过程来创建具有整数版本和浮点版本的大型复杂数据结构,因此在更新结构时不希望出现复制粘贴错误的可能性。我也不希望速度损失将浮点结构包装在一个整数包装器中,并且不必要地将所有输入转换为更宽松的数据类型。

3 个答案:

答案 0 :(得分:3)

我想这取决于你想要的严格程度。你想要一个Add方法只需要两个完全相同类型的参数(int和int,float和float)......?如果没有,并且性能不是非常重要,那么您可以使用decimal实现您的解决方案,它将全部有效。

如果必须严格,并且您需要每种类型的特定版本,您可能需要查看T4代码生成。它类似于C ++的模板(有些人认为C ++模板和C#泛型是相同的,但它们不是)。

Scott Hanselman写了an interesting article关于它。

答案 1 :(得分:3)

也许这可能有用:Is there a C# generic constraint for "real number" types?

似乎你所说的并不是直接可能的。拥有它会很有用。

答案 2 :(得分:2)

这里的主要挑战是抖动必须发出不同的操作码,具体取决于你是否添加了浮点数或整数,因此,即使代码看起来相似,它实际上也是在幕后完全不同。这在C ++中是可行的(因为模板是针对每个类型定义单独编译的),但.NET泛型的工作方式不同。看看T4 templates作为一种可能的解决方案(如果你真的需要能够分别编译为float或int。)