Unity C# で知っておくべき演算子

Unity は、機能面で開発者に多くの"heavy-lifting"を提供し、開発者が開発プロセスに完全に集中できるようにするゲーム エンジンです。主なプログラミング言語として C# を使用します。

他のプログラミング言語と同様に、C# は一連の特殊関数、型、クラス、ライブラリなどで構成されていますが、それぞれ独自の機能を持つ特殊記号 (演算子) のリストもあります。この記事では、それらの記号をリストし、その機能について説明します。これにより、次にスクリプトを開いたときに、各部分の意味をすぐに理解できるようになります。

C# の演算子は、オペランドに対して何らかのアクションを実行する特殊な記号です。

C# には、算術演算子、比較演算子、ブール論理演算子、ビット演算子とシフト演算子、等価演算子、およびその他の演算子の 6 種類の組み込み演算子があります。これらすべてを知っていれば、すぐに優れたプログラマーになれます。

1. 算術演算子

次の演算子は、数値型のオペランドを使用して算術演算を実行します。

  • 単項演算子 ++ (増分)、-- (減分)、+ (加算)、- (減算)
  • 二項演算子 * (乗算)、/ (除算)、% (剰余)、+ (加算)、- (減算)

インクリメント演算子 ++

"add one" 演算子 (または ++) は += 1 を意味します。つまり、追加のコードを入力しなくても、数値に 1 つの整数をすばやく追加できる方法です。この演算子は、値の前または後に追加できますが、結果の動作は異なります。

//The result of x++ is the value of x before the operation, as the following example shows:
int i = 4;
Debug.Log(i);   // output: 4
Debug.Log(i++); // output: 4
Debug.Log(i);   // output: 5

//The result of ++x is the value of x after the operation, as the following example shows:
double a = 2.5;
Debug.Log(a);   // output: 2.5
Debug.Log(++a); // output: 3.5
Debug.Log(a);   // output: 3.5

デクリメント演算子 --

"subtract one" 演算子は ++ (-= 1) の反対で、数値から 1 つの整数を減算することを意味します。また、値の前後に追加することもできます。

The result of x-- is the value of x before the operation, as the following example shows:
int i = 4;
Debug.Log(i);   // output: 4
Debug.Log(i--); // output: 4
Debug.Log(i);   // output: 3

The result of --x is the value of x after the operation, as the following example shows:
double a = 2.5;
Debug.Log(a);   // output: 2.5
Debug.Log(--a); // output: 1.5
Debug.Log(a);   // output: 1.5

単項 + および - 演算子

単項 + 演算子はオペランドの値を返し、単項 - 演算子はオペランドの数値否定を計算します。

Debug.Log(+5);     // output: 5

Debug.Log(-5);     // output: -5
Debug.Log(-(-5));  // output: 5

uint a = 6;
var b = -a;
Debug.Log(b);            // output: -6
Debug.Log(b.GetType());  // output: System.Int64

Debug.Log(-double.NaN);  // output: NaN

乗算演算子 *

乗算演算子 * は、オペランドの乗算積を計算します。

Debug.Log(6 * 3);         // output: 18
Debug.Log(1.5 * 3.5);     // output: 5.25
Debug.Log(0.1m * 24.4m);  // output: 2.44

除算演算子 /

除算演算子 / は、左側のオペランドを右側のオペランドで割ります。

オペランドの 1 つが 10 進数の場合、もう 1 つのオペランドは float でも double でもかまいません。これは、float も double も暗黙的に 10 進数に変換できないためです。float または double オペランドを明示的に 10 進数型に変換する必要があります。

Debug.Log(13 / 5);    // output: 2
Debug.Log(13 / 5.0);       // output: 2.6

int a = 13;
int b = 5;
Debug.Log((double)a / b);  // output: 2.6

Debug.Log(16.8f / 4.1f);   // output: 4.097561
Debug.Log(16.8d / 4.1d);   // output: 4.09756097560976
Debug.Log(16.8m / 4.1m);   // output: 4.0975609756097560975609756098

剰余演算子 %

剰余演算子 % は、左側のオペランドを右側のオペランドで割った余りを計算します。

  • 整数型のオペランドの場合、a % bの結果はa - (a / b) * bによって生成される値になります。
Debug.Log(5 % 4);   // output: 1
Debug.Log(5 % -4);  // output: 1
Debug.Log(-5 % 4);  // output: -1
Debug.Log(-5 % -4); // output: -1
  • 小数オペランドの場合、剰余演算子 % は System.Decimal 型の剰余演算子と同等です。
Debug.Log(-5.2f % 2.0f); // output: -1.2
Debug.Log(5.9 % 3.1);    // output: 2.8
Debug.Log(5.9m % 3.1m);  // output: 2.8

加算演算子 +

加算演算子 + は、そのオペランドの合計を計算します。また、文字列の連結やデリゲートの組み合わせにも + 演算子を使用できます。

Debug.Log(6 + 5);       // output: 11
Debug.Log(6 + 5.3);     // output: 11.3
Debug.Log(6.1m + 5.2m); // output: 11.3

減算演算子 -

減算演算子 - は、右側のオペランドを左側のオペランドから減算します。 - 演算子はデリゲートの削除にも使用できます。

Debug.Log(48 - 4);      // output: 44
Debug.Log(6 - 5.3);     // output: 0.7
Debug.Log(8.5m - 3.3m); // output: 5.2

2. 比較演算子

< (less than), > (greater than), <= (less than or equal), and >= (以上) 比較 (関係演算子とも呼ばれます) は、オペランドを比較します。これらの演算子は、すべての整数および浮動小数点数値型でサポートされています。

小なり演算子 <

< 演算子は、左側のオペランドが右側のオペランドより小さい場合は true を返し、それ以外の場合は false を返します。

Debug.Log(8.0 < 6.1);   // output: False
Debug.Log(6.1 < 6.1);   // output: False
Debug.Log(1.0 < 6.1);   // output: True

Debug.Log(double.NaN < 6.1);   // output: False
Debug.Log(double.NaN >= 6.1);  // output: False

より大きい演算子 >

> 演算子は、左側のオペランドが右側のオペランドより大きい場合は true を返し、それ以外の場合は false を返します。

Debug.Log(8.0 > 6.1);   // output: True
Debug.Log(6.1 > 6.1);   // output: False
Debug.Log(1.0 > 6.1);   // output: False

Debug.Log(double.NaN > 6.1);   // output: False
Debug.Log(double.NaN <= 6.1);  // output: False

以下演算子 <=

<= 演算子は、左側のオペランドが右側のオペランド以下の場合は true を返し、それ以外の場合は false を返します。

Debug.Log(8.0 <= 6.1);   // output: False
Debug.Log(6.1 <= 6.1);   // output: True
Debug.Log(1.0 <= 6.1);   // output: True

Debug.Log(double.NaN > 6.1);   // output: False
Debug.Log(double.NaN <= 6.1);  // output: False

より大きいか等しい演算子 >=

>= 演算子は、左側のオペランドが右側のオペランド以上の場合は true を返し、それ以外の場合は false を返します。

Debug.Log(8.0 >= 6.1);   // output: True
Debug.Log(6.1 >= 6.1);   // output: True
Debug.Log(1.0 >= 6.1);   // output: False

Debug.Log(double.NaN < 6.1);   // output: False
Debug.Log(double.NaN >= 6.1);  // output: False

3. ブール論理演算子

次の演算子は、bool オペランドを使用して論理演算を実行します。

  • 単項 ! (論理否定) 演算子。
  • バイナリ & (論理 AND)、| (論理 OR)、および ^ (論理排他的 OR) 演算子。これらの演算子は常に両方のオペランドを評価します。
  • バイナリ && (条件付き論理 AND) 演算子と || (条件付き論理 OR) 演算子。これらの演算子は、必要な場合にのみ右側のオペランドを評価します。

論理否定演算子 !

単項接頭辞 ! 演算子は、そのオペランドの論理否定を計算します。つまり、オペランドが false と評価された場合は true を生成し、オペランドが true と評価された場合は false を生成します。

bool passed = false;
Debug.Log(!passed);  // output: True
Debug.Log(!true);    // output: False

論理積演算子 &

& 演算子は、オペランドの論理積を計算します。x と y の両方が true と評価された場合、x & y の結果は true になります。それ以外の場合、結果は false になります。

& 演算子は、左側のオペランドが false と評価された場合でも両方のオペランドを評価するため、右側のオペランドの値に関係なく、演算結果は false になります。

bool SecondOperand()
{
    Debug.Log("Second operand is evaluated.");
    return true;
}

bool a = false & SecondOperand();
Debug.Log(a);
// Output:
// Second operand is evaluated.
// False

bool b = true & SecondOperand();
Debug.Log(b);
// Output:
// Second operand is evaluated.
// True

論理排他的OR演算子 ^

^ 演算子は、そのオペランドの論理排他的論理和 (論理 XOR とも呼ばれる) を計算します。x が true と評価され、y が false と評価される場合、または x が false と評価され、y が true と評価される場合、x ^ y の結果は true になります。それ以外の場合、結果は false になります。つまり、bool オペランドの場合、^ 演算子は不等号演算子 != と同じ結果を計算します。

Debug.Log(true ^ true);    // output: False
Debug.Log(true ^ false);   // output: True
Debug.Log(false ^ true);   // output: True
Debug.Log(false ^ false);  // output: False

論理 OR 演算子 |

| 演算子は、そのオペランドの論理和を計算します。 x または y のいずれかが true と評価された場合、x | y の結果は true になります。それ以外の場合は、結果は false になります。

| 演算子は、左側のオペランドが true と評価された場合でも両方のオペランドを評価するため、右側のオペランドの値に関係なく、演算結果は true になります。

bool SecondOperand()
{
    Debug.Log("Second operand is evaluated.");
    return true;
}

bool a = true | SecondOperand();
Debug.Log(a);
// Output:
// Second operand is evaluated.
// True

bool b = false | SecondOperand();
Debug.Log(b);
// Output:
// Second operand is evaluated.
// True

条件付き論理 AND 演算子 &&

条件付き論理 AND 演算子 && は、"short-circuiting" 論理 AND 演算子とも呼ばれ、オペランドの論理 AND を計算します。x と y の両方が true と評価された場合、x && y の結果は true になります。それ以外の場合は、結果は false になります。x が false と評価された場合、y は評価されません。

bool SecondOperand()
{
    Debug.Log("Second operand is evaluated.");
    return true;
}

bool a = false && SecondOperand();
Debug.Log(a);
// Output:
// False

bool b = true && SecondOperand();
Debug.Log(b);
// Output:
// Second operand is evaluated.
// True

条件付き論理 OR 演算子 ||

条件付き論理 OR 演算子 || は、"short-circuiting" 論理 OR 演算子とも呼ばれ、オペランドの論理 OR を計算します。x または y のいずれかが true と評価された場合、x || y の結果は true になります。それ以外の場合、結果は false になります。x が true と評価された場合、y は評価されません。

bool SecondOperand()
{
    Debug.Log("Second operand is evaluated.");
    return true;
}

bool a = true || SecondOperand();
Debug.Log(a);
// Output:
// True

bool b = false || SecondOperand();
Debug.Log(b);
// Output:
// Second operand is evaluated.
// True

4. ビット演算子とシフト演算子

次の演算子は、整数型または char 型のオペランドを使用してビット演算またはシフト演算を実行します。

  • 単項 ~ (ビット補数) 演算子
  • 二項 << (left shift) and >> (右シフト) シフト演算子
  • バイナリ & (論理 AND)、| (論理 OR)、^ (論理排他的 OR) 演算子

ビット補数演算子 ~

~ 演算子は、各ビットを反転してオペランドのビット単位の補数を生成します。

uint a = 0b_0000_1111_0000_1111_0000_1111_0000_1100;
uint b = ~a;
Debug.Log(Convert.ToString(b, toBase: 2));
// Output:
// 11110000111100001111000011110011

左シフト演算子 <<

<< 演算子は、左側のオペランドを右側のオペランドで定義されたビット数だけ左にシフトします。右側のオペランドがシフト数を定義する方法については、シフト演算子のセクションの「シフト数」を参照してください。

uint x = 0b_1100_1001_0000_0000_0000_0000_0001_0001;
Debug.Log($"Before: {Convert.ToString(x, toBase: 2)}");

uint y = x << 4;
Debug.Log($"After:  {Convert.ToString(y, toBase: 2)}");
// Output:
// Before: 11001001000000000000000000010001
// After:  10010000000000000000000100010000

右シフト演算子 >>

>> 演算子は、左側のオペランドを右側のオペランドで定義されたビット数だけ右にシフトします。

uint x = 0b_1001;
Debug.Log($"Before: {Convert.ToString(x, toBase: 2), 4}");

uint y = x >> 2;
Debug.Log($"After:  {Convert.ToString(y, toBase: 2), 4}");
// Output:
// Before: 1001
// After:    10

上位の空きビット位置は、左側のオペランドの型に基づいて次のように設定されます。

  • 左側のオペランドが int 型または long 型の場合、右シフト演算子は算術シフトを実行します。つまり、左側のオペランドの最上位ビット (符号ビット) の値が、上位の空きビット位置に伝播されます。つまり、左側のオペランドが負でない場合は上位の空きビット位置は 0 に設定され、負の場合は 1 に設定されます。
int a = int.MinValue;
Debug.Log($"Before: {Convert.ToString(a, toBase: 2)}");

int b = a >> 3;
Debug.Log($"After:  {Convert.ToString(b, toBase: 2)}");
// Output:
// Before: 10000000000000000000000000000000
// After:  11110000000000000000000000000000
  • 左側のオペランドが uint または ulong 型の場合、右シフト演算子は論理シフトを実行します。つまり、上位の空ビット位置は常にゼロに設定されます。
uint c = 0b_1000_0000_0000_0000_0000_0000_0000_0000;
Debug.Log($"Before: {Convert.ToString(c, toBase: 2), 32}");

uint d = c >> 3;
Debug.Log($"After:  {Convert.ToString(d, toBase: 2), 32}");
// Output:
// Before: 10000000000000000000000000000000
// After:     10000000000000000000000000000

論理積演算子 &

& 演算子は、整数オペランドのビット単位の論理積を計算します。

uint a = 0b_1111_1000;
uint b = 0b_1001_1101;
uint c = a & b;
Debug.Log(Convert.ToString(c, toBase: 2));
// Output:
// 10011000

論理排他的OR演算子 ^

^ 演算子は、整数オペランドのビット単位の論理排他的論理和 (ビット単位の論理 XOR とも呼ばれます) を計算します。

uint a = 0b_1111_1000;
uint b = 0b_0001_1100;
uint c = a ^ b;
Debug.Log(Convert.ToString(c, toBase: 2));
// Output:
// 11100100

論理 OR 演算子 |

| 演算子は、整数オペランドのビット単位の論理和を計算します。

uint a = 0b_1010_0000;
uint b = 0b_1001_0001;
uint c = a | b;
Debug.Log(Convert.ToString(c, toBase: 2));
// Output:
// 10110001

5. 等価演算子

== (等価) 演算子と != (不等価) 演算子は、オペランドが等しいかどうかをチェックします。

等価演算子 ==

等価演算子 == は、オペランドが等しい場合は true を返し、そうでない場合は false を返します。

int a = 1 + 2 + 3;
int b = 6;
Debug.Log(a == b);  // output: True

char c1 = 'a';
char c2 = 'A';
Debug.Log(c1 == c2);  // output: False
Debug.Log(c1 == char.ToLower(c2));  // output: True

不等号演算子 !=

不等式演算子 != は、オペランドが等しくない場合は true を返し、そうでない場合は false を返します。組み込み型のオペランドの場合、式 x != y は、式 !(x == y) と同じ結果を生成します。

int a = 1 + 1 + 2 + 3;
int b = 6;
Debug.Log(a != b);  // output: True

string s1 = "Hello";
string s2 = "Hello";
Debug.Log(s1 != s2);  // output: False

object o1 = 2;
object o2 = 2;
Debug.Log(o1 != o2);  // output: True

6. その他の演算子

一般的なその他の演算子としては、条件チェック用の ?:、エイリアス名前空間のメンバーにアクセスするための::、文字列補間用の $ などがあります。

?: 演算子

条件演算子 ?: (三項条件演算子とも呼ばれます) は、ブール式を評価し、ブール式が true と評価されるか false と評価されるかに応じて、2 つの式のいずれかの結果を返します。次に例を示します。

bool condition = true;
Debug.Log(condition ? 1 : 2); // output: 1

:: 演算子

エイリアスされた名前空間のメンバーにアクセスするには、名前空間エイリアス修飾子:: を使用します。:: 修飾子は 2 つの識別子の間でのみ使用できます。左側の識別子は、次のエイリアスのいずれかになります。

  • using alias ディレクティブを使用して作成された名前空間エイリアス:
using forwinforms = System.Drawing;
using forwpf = System.Windows;

public class Converters
{
    public static forwpf::Point Convert(forwinforms::Point point) => new forwpf::Point(point.X, point.Y);
}
  • 外部エイリアス。
  • グローバル エイリアスは、グローバル名前空間エイリアスです。グローバル名前空間は、名前付き名前空間内で宣言されていない名前空間と型を含む名前空間です。:: 修飾子とともに使用すると、ユーザー定義のグローバル名前空間エイリアスがある場合でも、グローバル エイリアスは常にグローバル名前空間を参照します。
namespace MyCompany.MyProduct.System
{
    class Program
    {
        static void Main() => global::System.Console.WriteLine("Using global alias");
    }

    class Console
    {
        string Suggestion => "Consider renaming this class";
    }
}

$ 演算子

特殊文字 $ は、文字列リテラルを補間文字列として識別します。補間文字列は、補間式を含む可能性のある文字列リテラルです。補間文字列が結果文字列に解決されると、補間式を含む項目は、式の結果の文字列表現に置き換えられます。

補間文字列では、ドル記号 ($) を使用して、その後の文字列が補間文字列として解釈されることを C# コンパイラに伝えます。中括弧は、テキストに含める値 (変数の値) をカプセル化します。

文字列リテラルを挿入文字列として識別するには、先頭に $ 記号を付加します。文字列リテラルを開始する $ と " の間には空白文字を入れることはできません。

string name = "John";
var date = DateTime.Now;
Debug.Log($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now.");
// Output:
// Hello, John! Today is Wednesday, it's 19:40 now.