有什么方法可以在C#中模拟C ++值模板参数?
template<bool flag>
void Method()
{
// Do some work
if constexpr(flag)
{
// Do something specific
}
// Do some more work
}
这样它将生成方法的两个版本,可以这样调用:
Method<false>();
Method<true>();
这是出于性能方面的考虑,因此最好不要在Method
内进行其他调用。 Method
是性能至关重要的部分,被称为数十亿次,因此从中压缩每个CPU周期非常重要。
另一方面,它的逻辑比较复杂,所以我宁愿没有两个副本。
我认为我可以对泛型做一些事情,但这并不是性能的最佳选择。因此,现在我唯一能想到的方法就是为其创建某种模板代码生成器。但是也许还有其他选择? 也许可以使用Roslyn编译该方法的两个版本,以便使用特定参数创建该方法的两个优化版本?
void Method(bool flag)
{
// Do some work
if (flag)
{
// Do something specific
}
// Do some more work
}
以便我可以将其编译为:
void Method_false(false)
{
// Do some work
// Do some more work
}
和:
void Method_true(true)
{
// Do some work
// Do something specific
// Do some more work
}
有可能吗?
答案 0 :(得分:2)
在C#中无法进行元编程。在以下SO问题中以代码转换工具的形式寻找可能的替代方法:Is metaprogramming possible in C#?
答案 1 :(得分:1)
您不能直接从语言中执行此操作,但这是可能的,因为JIT足够聪明。创建一个接口和两个结构:
public interface IBool
{
bool IsTrue();
}
public struct True : IBool
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsTrue()
{
return true;
}
}
public struct False : IBool
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsTrue()
{
return false;
}
}
请注意,IsTrue
的实现标记有MethodImpl
属性。现在,将您的Method
改写为通用的
public static void Method<T>(ref T flag) where T : struct, IBool
{
if (flag.IsTrue())
{
Console.WriteLine(42);
}
else
{
Console.WriteLine(24);
}
}
有一件很重要的事情:T
有struct
约束,因此JIT意识到没有T
的继承类型,没有人可以覆盖IsTrue
的返回值。此外,由于将内联此方法,因此JIT用常量替换对IsTrue
的调用。而当您拥有
if (false)
{
// some code
}
这意味着将删除整个代码块。结果,JIT将创建Method
的两个实现:首先是if
部分的内容,而seconf是else
部分的内容。您可以在反汇编窗口中进行检查: