[Unity] C#7 を使う

最後はC#7

C#4C#5、C#6と続きまして最後のC#7編となります。
タプルが一番のメインかも?

タプル(Tupple)

変数の宣言を型の代わりにタプルというもので宣言できます。
関数の戻り値で2つ以上の値を戻したいときは超有能の機能となります。
(int count, int sum) Tally(IEnumerable items)
この場合だと、2つのintを返すことができます。
これまでだと構造体やクラスを作らないといけなかったのが、その必要がなくなりますよ。すごい。
もちろん戻り値だけではなく、普通に変数としてつかえます。

型スイッチ

switch~case文のcase文で、型を判別したら条件式をつけたりすることができるみたいです。
case int n when n > 0:
この場合だと、int型で0より大きい値だったら合格になります。

数値リテラルの改善

byte bitMask = 0b1100_0000;
uint magicNumber = 0xDEAD_BEEF;
2進数表記や、"_"で区切ることができるようになりました。
見やすい。

タプルの ==, != 比較 (c# 7.3)

(int a, (int x, int y) b) t2 = (2, (1, 2));
Debug.Log(t2 == (1, (2, 3)));
// False
タプルの比較がC#7.3からできるようになりました。
UnityもC#7.3まで使えない時期が少しありました。懐かしい。

ref 再代入 (c# 7.3)

int x = 1;
ref var r = ref x;
これは、rの値を変えるとxも値がかわります。

ref readonly

int x5 = 0;
ref readonly var readonlyX = ref x5;
読み取り専用のref、みたいな?

is 式

int x7 = 3;
if (x7 is int val)
変数の型を簡単に調べることができるようになりました。
地味に使える場面はありますよ。

値の破棄

var (q, _) = DivRem(123, 11);
これはタプルの例ですが、いらないものには"_"にするとないものにすることができます。

参照戻り値と参照ローカル変数

static ref int Max(ref int x, ref int y)
なんかすごい宣言です。サンプルでは、ref xかref yのどちらかをrefします。

ローカル関数

int f(int n) => n >= 1 ? n * f(n - 1) : 1;
Debug.Log(f(10));
// 3628800
関数の中で関数を簡単に宣言できます。
一回しか使わない単純な関数とかこれで十分ですね。
まれによくある。


ながながとサンプルpiyo
#if UNITY_EDITOR
#if CSHARP_7_OR_LATER
using System;
using System.Collections.Generic;
using UnityEngine;
public class CS7Test : MonoBehaviour
{
private void Start()
{
TestFunc001();
TestFunc002();
TestFunc003();
}
static void TestFunc001()
{
#region タプル(Tupple)
// タプルを使って2つの戻り値を返す
(int count, int sum) Tally(IEnumerable<int> items)
{
var count = 0;
var sum = 0;
foreach (var x3 in items)
{
sum += x3;
count++;
}
return (count, sum);
}
var data = new[] { 1, 2, 3, 4, 5 };
var t = Tally(data);
Debug.Log($"{t.sum}/{t.count}");
// 15/5
#endregion
#region 型スイッチ
object obj = 5;
if (obj is string s)
{
Debug.Log("string #" + s.Length);
}
switch (obj)
{
case 7:
Debug.Log("7の時だけここに来る");
break;
case int n when n > 0:
Debug.Log("正の数の時にここに来る " + n);
// 上から順に判定するので 7の時には来なくなる
break;
case int n:
Debug.Log("整数の時にここに来る" + n);
// 0 以下の時にしか来ない
break;
default:
Debug.Log("その他");
break;
}
// 正の数の時にここに来る 5
#endregion
#region 数値リテラルの改善
byte bitMask = 0b1100_0000;
Debug.Log(bitMask);
// 192
uint magicNumber = 0xDEAD_BEEF;
Debug.Log(magicNumber);
// 3735928559
Debug.Log(magicNumber.ToString("X"));
// DEADBEEF
#endregion
#region 先頭区切り文字
// C# 7.0 から書ける
var b1 = 0b1111_0000;
var x1 = 0x0001_F408;
// C# 7.2 から書ける
// b, x の直後に _ 入れてもOKに
var b2 = 0b_1111_0000;
var x2 = 0x_0001_F408;
Debug.Log(b1);
// 240
Debug.Log(x1);
// 128008
Debug.Log(b2);
// 240
Debug.Log(x2);
// 128008
#endregion
#region タプルの ==, != 比較 (c# 7.3)
// c# 7.3
(int a, (int x, int y) b) t2 = (2, (1, 2));
Debug.Log(t2 == (1, (2, 3)));
// False
#endregion
#region ref 再代入 (c# 7.3)
// c# 7.3
int x = 1;
int y = 2;
ref var r = ref x;
r = 10;
// x が 10になる
r = ref y;
r = 20;
// y が 20 になる
Debug.Log((x, y));
// (10, 20)
#endregion
#region ref readonly
int x5 = 0;
ref readonly var readonlyX = ref x5;
Debug.Log(readonlyX);
// 0
#endregion
#region is 式
int x7 = 3;
if (x7 is int val)
x7 += val;
Debug.Log(x7);
// 6
#endregion
}
#region 値の破棄
static (int quotient, int remainder) DivRem(int dividend, int divisor)
=> (Math.DivRem(dividend, divisor, out var remainder), remainder);
static void Deconstruct()
{
var (q, _) = DivRem(123, 11);
(_, var r) = DivRem(123, 11);
}
#endregion
#region 参照戻り値と参照ローカル変数
static void TestFunc002()
{
var x = 10;
var y = 20;
ref var m = ref Max(ref x, ref y);
m = 0;
Debug.Log($"{x}, {y}");
// 10, 0
}
static ref int Max(ref int x, ref int y)
{
if (x < y) return ref y;
else return ref x;
}
#endregion
#region ローカル関数
static void TestFunc003()
{
// 関数の中で、ローカル関数 f を定義
int f(int n) => n >= 1 ? n * f(n - 1) : 1;
Debug.Log(f(10));
// 3628800
}
#endregion
}
#region 参照渡しの拡張メソッド
/// <summary>
/// 参照渡しの拡張メソッド
/// </summary>
public static class QuarternionExtensions
{
/// <summary>
///
/// </summary>
/// <param name="q"></param>n
public static void Conjugate(ref this Quaternion q)
{
var norm = q.w * q.w + q.x * q.x + q.y * q.y + q.z * q.z;
q.w = q.w / norm;
q.x = -q.x / norm;
q.y = -q.y / norm;
q.z = -q.z / norm;
}
/// <summary>
/// コピーを避けたい場合に in 引数が使える
/// </summary>
/// <param name="p"></param>
/// <param name="q"></param>
/// <returns></returns>
public static Quaternion Rotate(in this Quaternion p, in Quaternion q)
{
var qc = q;
qc.Conjugate();
return q * p * qc;
}
}
#endregion
#endif
#endif
view raw CS7Test.cs hosted with ❤ by GitHub

c#7シリーズでは癖のある使える機能がたくさん実装されました。
なんかこんな機能あったなと覚えておくだけでもいいと思います。


CITY 8巻
僕のヒーローアカデミア 24巻
メイドインアビス(8)
ハクメイとミコチ 7巻

0 件のコメント :

コメントを投稿