配列の末尾要素を取得する時,array[array.Length - 1]
といった回りくどい記述になると思います。
今回はこれをarray.GetLastElement()
という,明瞭な表現で実行できる拡張メソッドを作りました。
本稿では,LINQ のメソッドである Last()
も交えて御説明いたします。
(Unity 2018.3.0f2)
スクリプトの用意
まずは,拡張メソッド用のスクリプトを用意します。
これで,System.Collections.Generic
のインターフェースであるIReadOnlyList<T>
にGetLastElement()
というメソッドを追加できました。
IReadOnlyList<T>
はあらゆる型の配列やリストを包括しているため,これだけでint[]
やList<Vector3>
などにも使用できます。
使用例
NewBehaviourScript.cs
using UnityEngine; // 拡張メソッド GetLastElement を使うため using static LastElement; public class NewBehaviourScript : MonoBehaviour { void Start() { // 整数配列 var ints = new int[] { 0, 1, 2 }; Debug.Log(ints.GetLastElement()); // 小数配列 var floats = new float[] { 0.1f, 1.1f, 2.1f }; Debug.Log(floats.GetLastElement(0)); // 文字列リスト var strings = new System.Collections.Generic.List<string> { "a", "b", "c" }; Debug.Log(strings.GetLastElement(-1)); // ベクトルリスト var vectors = new System.Collections.Generic.List<Vector3> { Vector3.zero, Vector3.one, Vector3.one * 2 }; Debug.Log(vectors.GetLastElement(1)); } }
解説
まずは拡張メソッドクラスであるLastElement
を,using static
ディレクティブで指定します。
これはLastElement
を拡張クラスとするうえで,静的(static
)にする必要があったためです。
/// <summary> /// コンテナの末尾要素を取得する静的クラス /// </summary> [Obsolete("This class is obsolete. Call TsuGames.Last instead.")] public static class LastElement
例外メッセージを定義していますが,const
ではなくstatic readonly
修飾子を使用しています。
これは定数のように扱いたいものの,後に変更する可能性が有る場合の対処法です。
// shift の例外メッセージ static readonly string ShiftExceptionMessage = "\"shift\" must be opposite of a count in container to 0.";
GetLastElement()
メソッドにはジェネリック型パラメーターT
を使用することで,複数の型に対応しています。
/// <summary> /// コンテナの末尾要素を取得 /// </summary> /// <typeparam name="T">コンテナの型</typeparam> /// <param name="objects">コンテナ</param> /// <param name="shift">末尾インデックスからのシフト(0以下)</param> /// <returns>指定したインデックスの要素</returns> [Obsolete("This method is obsolete. Call TsuGames.Last.LastElement instead.")] public static T GetLastElement<T>(this IReadOnlyList<T> objects, int shift = 0)
整数型int
の引数shift
によって「最後から-shift
番目の要素」も取得できるよう,オーバーロードメソッドを定義しています。
/// <summary> /// コンテナの末尾要素を取得 /// </summary> /// <typeparam name="T">コンテナの型</typeparam> /// <param name="objects">コンテナ</param> /// <param name="shift">末尾インデックスからのシフト(0以下)</param> /// <returns>指定したインデックスの要素</returns> [Obsolete("This method is obsolete. Call TsuGames.Last.LastElement instead.")] public static T GetLastElement<T>(this IReadOnlyList<T> objects, int shift)
shift
の値が範囲外だった時に例外メッセージを表示するため,try-catch
キーワードを使います。
引数が範囲外だった場合の操作は,ArgumentOutOfRangeException
クラスで行います。
catch
ブロック内で明示的にthrow
キーワードを使うと,専用の例外メッセージを表示できます。
// 例外が生じるおそれのある命令 try { // 指定したインデックスの要素を返す return objects[LastIndexNumberOf(objects) + shift]; } // 引数の例外をキャッチした場合 catch (ArgumentOutOfRangeException) { // 例外を投げる throw new ArgumentOutOfRangeException(nameof(shift), ShiftExceptionMessage); }
オーバーロードで共通する部分は,LastIndexNumberOf<T>()
メソッドとして独立させています。
/// <summary> /// コンテナの末尾インデックス番号 /// </summary> /// <typeparam name="T">コンテナの型</typeparam> /// <param name="objects">コンテナ</param> /// <returns>末尾インデックス番号</returns> static int LastIndexNumberOf<T>(IReadOnlyList<T> objects)
Enumerable.Last メソッドとの違い
LINQ のLast()
メソッドでも末尾要素を取得できますが,GetLastElement<T>()
メソッドは「末尾から○番目の要素」を選べます。
短所は,Last()
メソッドにあるような「条件に該当する要素の中で最後の物」という指定が出来ない点です。
可読性の補助が目的であるため,機能は絞った物となりました。
御要望がございましたら,機能の追加や変更も検討いたします。
以上,配列やリストの末尾要素を取得する拡張メソッドの御紹介でした。
同じように文字列の末尾文字を取得する方法については,以下の記事をご覧くださいませ。
上記の機能と統合した拡張メソッドも,以下の記事にて紹介しております。