编译到不同目标时如何临时用另一种原始类型替换一种原始类型?

发布于 2024-08-02 19:10:44 字数 616 浏览 6 评论 0原文

如何轻松/快速地将浮点数替换为双精度数(例如),以便使用这两种特定的基元类型选择编译为两个不同的目标?

讨论: 我有大量正在开发的 C# 代码,需要根据目标程序集的用例进行编译,以选择性地使用浮点型、双精度型或小数型。

使用“class MYNumber : Double”之类的东西只需要更改一行代码是行不通的,因为 Double 是密封的,而且显然 C# 中没有 #define。 在代码中添加 #if #else 语句也不是一种选择,有太多支持使用这些特定基元类型的数学运算符/相关代码。

我不知道如何完成这个看似简单的任务,谢谢!

编辑:只是关于凯尔斯回复中提到的拳击的快速评论:不幸的是,我需要避免拳击,主要是因为在需要最大速度时选择浮点数,而在需要最大精度时选择小数(并且采用 20 倍以上的性能命中是可以接受)。拳击可能会排除小数作为有效选择,并在某种程度上达不到目的。

Edit2:作为参考,那些建议泛型作为这个问题的可能答案的人注意到,有很多问题将泛型排除在外(至少对于我们的需要而言)。有关概述和更多参考,请参阅使用泛型进行计算

How to easily/quickly replace float's for doubles (for example) for compiling to two different targets using these two particular choices of primitive types?

Discussion:
I have a large amount of c# code under development that I need to compile to alternatively use float, double or decimals depending on the use case of the target assembly.

Using something like “class MYNumber : Double” so that it is only necessary to change one line of code does not work as Double is sealed, and obviously there is no #define in C#.
Peppering the code with #if #else statements is also not an option, there is just too much supporting Math operators/related code using these particular primitive types.

I am at a loss on how to do this apparently simple task, thanks!

Edit: Just a quick comment in relation to boxing mentioned in Kyles reply: Unfortunately I need to avoid boxing, mainly since float's are being chosen when maximum speed is required, and decimals when maximum accuracy is the priority (and taking the 20x+ performance hit is acceptable). Boxing would probably rules out decimals as a valid choice and defeat the purpose somewhat.

Edit2: For reference, those suggesting generics as a possible answer to this question note that there are many issues which count generics out (at least for our needs). For an overview and further references see Using generics for calculations

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

话少心凉 2024-08-09 19:10:44

最好的方法是使用 #if,正如 Andrew 上面所说的。然而,一个有趣的想法是这样的:

#if USE_FLOAT
using Numeric = System.Single;
#endif

#if USE_DOUBLE
using Numeric = System.Double;
#endif

#if USE_DECIMAL
using Numeric = System.Decimal;
#endif

public class SomeClass
{
    public Numeric MyValue{get;set;}
}

编辑:

我仍然非常喜欢这个解决方案,它允许您做一些其他非常酷的事情,例如:

Numeric.Parse();
Numeric.TryParse();

这适用于所有三种类型

The best way to do this would be using #if as Andrew stated above. However, an interesting idea to think about would be something like this:

#if USE_FLOAT
using Numeric = System.Single;
#endif

#if USE_DOUBLE
using Numeric = System.Double;
#endif

#if USE_DECIMAL
using Numeric = System.Decimal;
#endif

public class SomeClass
{
    public Numeric MyValue{get;set;}
}

EDIT:

I still really like this solution, it allows you to do some other really cool things such as:

Numeric.Parse();
Numeric.TryParse();

Which will work for all three types

树深时见影 2024-08-09 19:10:44

最坏的情况是我认为你可以使用拳击和类似的东西:

#if USE_FLOAT
public float OutputValue(object input)
{
    return (float)input;
}
#endif

#if USE_DOUBLE
public double OutputValue(object input)
{
    return (double)input;
}
#endif

并调用OutputValue(1.5);让它为你转换它。

At worst I think you could use boxing and something like this:

#if USE_FLOAT
public float OutputValue(object input)
{
    return (float)input;
}
#endif

#if USE_DOUBLE
public double OutputValue(object input)
{
    return (double)input;
}
#endif

and call OutputValue(1.5); to get it to convert it for you.

阳光①夏 2024-08-09 19:10:44

一种方法是围绕您需要的基本类型创建一个泛型。然后,您在单独的 .cs 文件中声明一个继承该泛型的特定实例的类,并为您需要的每个基类型创建该类的三个副本。然后,您可以根据构建配置更改 .csproj 以包含正确的 .cs 文件。

请注意,我还没有真正尝试过这一点,所以可能有一些问题需要解决。

One approach would be to have a generic around the base type you need. Then you declare a class that inherits specific instance of that generic in a separate .cs file and you create three copies of this class for each base type you need. Then you change your .csproj to include the proper .cs file based on the build configuration.

Note that I have not really tried this, so there might be couple of kinks to iron out.

蘸点软妹酱 2024-08-09 19:10:44

你可以这样做:

public struct NumberContainer<T> 
{
    T _number;

    // accessor, and possibly: operators, cast methods, etc.
}

然后:

#if USE_FLOAT
public struct MyNumber : NumberContainer<float>
#else
public struct MyNumber : NumberContainer<double>
#endif
{
}

You could do this:

public struct NumberContainer<T> 
{
    T _number;

    // accessor, and possibly: operators, cast methods, etc.
}

And then:

#if USE_FLOAT
public struct MyNumber : NumberContainer<float>
#else
public struct MyNumber : NumberContainer<double>
#endif
{
}
听,心雨的声音 2024-08-09 19:10:44

这很困难,因为基本类型不实现 IArithmetic 之类的东西。 Connect 上已多次建议。不幸的是,这是众所周知的泛型限制

有一些解决方法,使用“计算器”结构类 。如果所做的数学计算不是太繁重,那么这会非常非常有效。

然而,它很笨重。这是泛型不如 C++ 模板灵活的地方。

另一种方法可能是使用类似 文本模板转换工具包 (T4)< /a> 生成适用于任何类型的模板,并为每种类型编译单独的模板。

This is difficult, since the basic types do not impelment something like IArithmetic. This has been suggested many times on Connect. Unfortunately, this is a well known limitation of generics.

There are some workarounds, using a "calculator" struct class. If the math isn't too onerous that's being done, this works very, very well.

However, it's clunky. This is one place where generics are not as flexible as C++ templates.

One other approach could be to use something like the Text Template Transformation Toolkit (T4) to generate a template that would work with any type, and compile separate ones per type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文