概要
最近C#に入門していて、ConditionalAttribute
なるものの存在を知りました。
例えば、[Conditional("AAA")]
という属性をメソッドに与えている場合において、シンボルのAAAが定義されていなければ、そのメソッドを呼び出している箇所がコンパイルされなくなるというものです(メソッド自体はコンパイルされます)。
using System;
using System.Diagnostics;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
// シンボルAAAが定義されていないため、下のHello()の呼び出しはコンパイルされない
Hello();
Console.WriteLine("Main()");
}
[Conditional("AAA")]
static void Hello()
{
Console.WriteLine("Hello()");
}
}
}
実行結果
Main()
シンボルのAAAが定義されていないため、Hello()
メソッドが呼び出されてないことが確認できます。
そこで、1つ疑問が浮かびました。
ConditionalAttribute
のメソッドの引数に副作用のある式を書いたらどうなるのでしょうか。これは、C/C++のassert()
において、意図せず副作用のある式を書いてしまい、挙動がDebugとReleaseのときで異なりバグが発生することがよくある?ことであり気になったからです。
例えば、C++でassert()に副作用のある式を書いてしまったソースコードは下記です。
#include <iostream>
#include <cassert>
using namespace std;
int main()
{
int a = 10;
assert(++a);
cout << a << endl;
return 0;
}
NDEBUGを定義するかしないかで、a
の値が変化してしまいます。
$ clang++ main.cpp && ./a.out
11
$ clang++ -DNDEBUG main.cpp && ./a.out
10
検証
検証用のソースコードは下記です。
using System;
using System.Diagnostics;
namespace ConsoleApplication
{
class Program
{
static int a = 10;
static void Main(string[] args)
{
Hello(++a);
Console.WriteLine("Main():{0}", a);
}
[Conditional("AAA")]
static void Hello(int x)
{
Console.WriteLine("Hello():{0}", x);
}
}
}
実行結果
Main():10
というわけで、Hello(++a);
がコンパイルされなくなっているので、++a
は実行されず、aが11になることはありませんでした。
結論としては、ConditionalAttribute
のメソッドの引数に副作用のある式を書くのは、あまり良いことでは無いかもしれません。
参考文献
ConditionalAttribute Class (System.Diagnostics) | Microsoft Docs