最後はC#7
タプル(Tupple)
変数の宣言を型の代わりにタプルというもので宣言できます。関数の戻り値で2つ以上の値を戻したいときは超有能の機能となります。
(int count, int sum) Tally(IEnumerableこの場合だと、2つのintを返すことができます。items)
これまでだと構造体やクラスを作らないといけなかったのが、その必要がなくなりますよ。すごい。
もちろん戻り値だけではなく、普通に変数としてつかえます。
型スイッチ
switch~case文のcase文で、型を判別したら条件式をつけたりすることができるみたいです。case int n when n > 0:この場合だと、int型で0より大きい値だったら合格になります。
数値リテラルの改善
byte bitMask = 0b1100_0000;2進数表記や、"_"で区切ることができるようになりました。
uint magicNumber = 0xDEAD_BEEF;
見やすい。
タプルの ==, != 比較 (c# 7.3)
(int a, (int x, int y) b) t2 = (2, (1, 2));タプルの比較がC#7.3からできるようになりました。
Debug.Log(t2 == (1, (2, 3)));
// False
UnityもC#7.3まで使えない時期が少しありました。懐かしい。
ref 再代入 (c# 7.3)
int x = 1;これは、rの値を変えるとxも値がかわります。
ref var r = ref x;
ref readonly
int x5 = 0;読み取り専用のref、みたいな?
ref readonly var readonlyX = ref x5;
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
一回しか使わない単純な関数とかこれで十分ですね。
まれによくある。
#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 |
c#7シリーズでは癖のある使える機能がたくさん実装されました。
なんかこんな機能あったなと覚えておくだけでもいいと思います。
CITY 8巻
僕のヒーローアカデミア 24巻
メイドインアビス(8)
ハクメイとミコチ 7巻
0 件のコメント :
コメントを投稿