我知道这个问题已经问了很多,但仅针对C/C++和Java。
这个问题与使用常量表达式的性能优势有关:
当我仅以常量作为参数调用静态函数时,有没有办法告诉编译器它应该在编译时评估该调用并将该调用替换为结果?
例子:
const double pi = Math.PI; //works as Math.PI is a constant
const double spi = Math.Sin(Math.PI); //compiler error, because expression must be constant
没有指令(更好的是:Attributes)明确地告诉编译器,诸如Math.Sin()之类的静态方法没有在内部修改或读取任何数据,因此从技术上讲,可以在编译时评估调用吗?
哦,请不要回答“只是做
const double spi = 0
” :),因为我的示例只是我遇到的问题的简化版本:在保持最大性能的同时提高代码的可维护性。感谢您的帮助-非常感谢!
最佳答案
对于数值常量,我看到两个选择:
选项一:使用静态只读(在启动时计算一次):
class MyCalc
{
private static readonly double spi = Math.Sin(Math.PI);
private static readonly double pi = Math.PI;
public void Execute()
{
// .. whatever
}
}
方法二:用袖珍计算器执行计算,并对这些常数进行硬编码:
class MyCalc
{
// Math.Sin(Math.Pi)
private const double spi = 0;
// Math.Pi
private const double pi = 3.141592653589793;
public void Execute()
{
// .. whatever
}
}
我不确定,编译器是否可以在计算中完全优化掉选项一,但这应该是最易读和可维护的方式。
如果您希望在编译时做更多的事情,事情会变得越来越难。在C++下,您有模板。我发现他们写起来很麻烦,但是人们用它完成了amazing things。 compile time functions似乎变得更容易,但是我还没有尝试过。 D有CTFE,它非常强大。但是D是一个利基市场,我会避免在其中编写任何严肃的代码。我不了解其他具有明显的预编译评估的语言,但是我敢肯定有一些。
如今,编译器非常聪明。编译器可能会发现有机会在没有提示的情况下内联优化函数调用的机会。使用DotNet 4.5,我们有了AggressiveInlining -attribute,因此我们可能能够迫使编译器向正确的方向发展。 C/C++有类似的东西,并且有problems。我这边的一般建议是,除非您完全知道自己在做什么,否则应避免使用
inline
。如果您真的不想从C#中走出来,在我看来,最好的选择是使用提到的功能在C++中编写您的功能,编写一个易于使用的C接口(interface),并通过PInvoke进行调用。但是,如果真的值得,请在做之前帮自己一个忙,并采取措施。永远不要忘记优化的两个规则:
关于c# - 在编译时评估表达式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33518474/