FC2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム »C#リファレンス
このページの記事一覧

【C#】クラスのフィールド名を文字列の配列で取得する  


 ただのメモ。クラスや構造体をデータのやり取りに使う際、フィールド名を一覧で取得したいときがある。JSONスキーマ的なものとかね。そんな時に役立つ簡単なサンプルコード。

●フィールド名を取得するクラス例
using System.Linq;
using System.Reflection;

public class Sample //※名前は任意(typeof で指定する)
{
//取得するフィールド
public const string c_value = "const value";
public static readonly string s_value = "static value";
public string pub_value = "public value";
private string pri_value = "private value";

//フィールド名を string[] で返す
public string[] GetFieldNames()
{
var bindingFlags = BindingFlags.Public //┐どちらか一方は指定する
| BindingFlags.NonPublic //┘
| BindingFlags.Instance //┐どちらか一方は指定する
| BindingFlags.Static //┘
| BindingFlags.DeclaredOnly; //このクラスのみ(継承などは含めない)

var t = typeof(Sample); //取得するクラス名
var fields = t.GetFields(bindingFlags);
return fields.Select(e => e.Name).ToArray();
}
}

●メインコード例
using System;

var sample = new Sample();
var names = sample.GetFieldNames();
Console.WriteLine($"Length = {names.Length}");
foreach (var item in names)
{
Console.WriteLine(item);
}

Length = 4
c_value
s_value
pub_value
pri_value

 BindingFlags の指定で、public や private, インスタンスや static などを選択することができる(少なくともこれらの属性は指定した方が良い)。また継承してるクラスがある場合、BindingFlags.DeclaredOnly でスーパークラスのフィールドを除外することもできる。

 ここではフィールド名が欲しかったので Type.GetFields() を使っているが、メソッドやプロパティ名を取得したいなら、Type.GetMembers() を同様に使えば良い。

 リフレクション(Reflection)関連は使いこなせれば色々と便利だが、ランタイム時の負荷はそれなりにかかるそうで、実行速度を優先するなら、先に文字列化したものをデータ化しておくなど、工夫した方が良いだろう。使い所は適切に(笑)。

BindingFlags 列挙型
Type.GetFields()
Type.GetMembers()
リフレクション





(関連記事)
【C#】【Unity】enum 型と string, int 型の相互変換など


関連記事
スポンサーサイト



category: C#

thread: プログラミング

janre: コンピュータ

tag: C#リファレンス 
tb: 0   cm: --

【C#】GUID の生成と書式  


 GUID の生成はググればすぐに出てくるのだが、生成されたオブジェクトは Guid 型なので、普段使うには文字型に変換して使うことが多い。

Guid.NewGuid メソッド

 幸いなことに文字列変換の Guid.ToString() には、いくつかのオーバーロードが定義されているので、利用方法は簡単だ。ただ「あれ?何を指定するんだっけ…?」とよく調べるので、メモ代わりに具体例を書いておくことにした(解説はマニュアル参照)。

Guid.ToString(String)

●テストコード
using System;

Console.WriteLine("(): " + Guid.NewGuid().ToString());
Console.WriteLine("N : " + Guid.NewGuid().ToString("N"));
Console.WriteLine("D : " + Guid.NewGuid().ToString("D"));
Console.WriteLine("B : " + Guid.NewGuid().ToString("B"));
Console.WriteLine("P : " + Guid.NewGuid().ToString("P"));
Console.WriteLine("X : " + Guid.NewGuid().ToString("X"));

(): 9379a57a-eb51-431e-bf78-e2bdb96bf249
N : b11b80a4ebd54e19916d3de68cf6e548
D : f5f54a7d-b46b-4d99-a70c-dff3216f1766
B : {cc3e87ff-83a5-4eac-b465-e4b967173db7}
P : (8cc1037b-db1b-4bb0-969a-6af901719548)
X : {0xe49cb895,0xe333,0x4704,{0x81,0x25,0xa2,0x70,0x79,0x4e,0xf6,0xae}}

 GUID はハッシュ値と違い、毎回変わるので、上の例はあくまでもその実行時の結果なので注意。

 "()":引数無しと "D" は同じようだ。普段使うのは引数無し(or "D") か "N" (ハイフン無し)を使うことが多いだろう。

 他は括弧囲み "()" だったり、中括弧 "{}" だったり、16進 "0x" だったりとなるだけだ。

 GUID はセッションID や識別ID などによく使われる。内容的には以下の記事にあるように『GUID値とは、世界で重複することがない、ユニーク(=唯一)な128bit(16byte)のランダムな数値である。GUID値は必ずしも「絶対に同じID値が生成されないこと」を保証するものではないが、その数値の範囲が2の128乗、つまり「およそ3.4×(10の38乗)」(=340億の100兆倍の100兆倍)もあるので、現実的に同じIDが生成される可能性はきわめて低い。』というものだ。例えば、ブラウザやアプリなどで初めに生成→保存し、利用者を識別したりするのにも使われる(広告とか)。簡易的なユニークID として利用するにはもってこいだろう。

.NET TIPS GUID値を生成するには?





(関連記事)
【C#】MD5, SHA1, SHA256, SHA384, SHA512 等のハッシュ値を生成する
【Unity】【C#】文字列の暗号化・復号化を行う


関連記事

category: C#

thread: プログラミング

janre: コンピュータ

tag: C#リファレンス 
tb: 0   cm: --

【C#】【Unity】enum 型と string, int 型の相互変換など  


 enum 型をファイルに保存したり、UIなどのインデクスに対応させたりと、相互変換するとき確認したいことが多くあるので、備忘録的にまとめておいた。今回は通常の C# として書いているが、Unity などでも使用することは多いので、ちょっとしたトラブルシューティングなどもついでに。どちらかというとリファレンス的な使い方になると思うので、解説は少なめに凡例を列挙しておこう。


(※) mono-4.2.1 (C#6, CLI4.5)[paiza.io] / Unity 5.6.3p1 - 2018.1.5f1 / Windows10(x64) で確認



■enum → string 変換
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

//enum → string 変換
BloodType bloodType = BloodType.A;
string str = bloodType.ToString();

Console.WriteLine(str);

A

 または以下のようにも書ける。
string str = Enum.GetName(typeof(BloodType), bloodType);

Console.WriteLine(str);

A




■string → enum 変換
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

//string → enum 変換
string str = "B"; //"b" でも可
BloodType bloodType = (BloodType)Enum.Parse(typeof(BloodType), str, true); //true = IgnoreCase

Console.WriteLine(bloodType);

B

 ちょっと試しに IgnoreCase のオプションを外して小文字にしてみると、System.ArgumentException が出る。
string str = "b";
//↓このコードはエラーが出ます。
BloodType bloodType = (BloodType)Enum.Parse(typeof(BloodType), str); //System.ArgumentException

Console.WriteLine(bloodType);

System.ArgumentException




■enum → int 変換
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

//enum → int 変換
BloodType bloodType = BloodType.AB;
int i = (int)bloodType;

Console.WriteLine(i);

3




■int → enum 変換
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

//int → enum 変換
int i = 3;
BloodType bloodType = (BloodType)Enum.ToObject(typeof(BloodType), i);

Console.WriteLine(bloodType);

AB

 試しに範囲外の値を入れてみると、そのまま整数値が出てくる。
//int → enum 変換
int i = 4; //範囲外の値
BloodType bloodType = (BloodType)Enum.ToObject(typeof(BloodType), i);

Console.WriteLine(bloodType);

4




■enum の名前の配列を取得
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

string[] names = Enum.GetNames(typeof(BloodType));

Console.WriteLine(string.Join(", ", names));

A, B, O, AB




■enum の値(enum)の配列オブジェクト(Array)を取得
using System;

enum BloodType //※enum 型は任意
{
A, B, O, AB
}

Array values = Enum.GetValues(typeof(BloodType));

foreach (var item in values) {
Console.WriteLine(item + " = " + (int)item);
}

A = 0
B = 1
O = 2
AB = 3




■enum を long 型で使う
using System;

enum LongRange : long //※enum 型は任意
{
Min = long.MinValue,
Num = 123456789L,
Max = long.MaxValue,
}

long min = (long)LongRange.Min; //キャストが必要
long num = (long)LongRange.Num; //キャストが必要
long max = (long)LongRange.Max; //キャストが必要

Console.WriteLine(min);
Console.WriteLine(num);
Console.WriteLine(max);

-9223372036854775808
123456789
9223372036854775807




■enum の値割当と Unity インスペクタのずれを直す(Unity トラブルシューティング)

 例えば以下のような列挙型があったとき、途中から "Banana" を削除したくなったとしよう。しかし、コメントアウトで消したとするとそれぞれに割り当てられれた値がずれ、インスペクタでの表示(名前)も変わってしまう。

public enum Hoge  //※enum 型は任意
{
Apple,
//Banana,
Cat,
Dog,
}
public Hoge hoge;

 これは、コメントアウト前は {Apple = 0, Banana = 1, Cat = 2, Dog = 3} であったのに対し、コメントアウト後は {Apple = 0, Cat = 1, Dog = 2} になるために出る症状なので、以下のように値を直接割り当てれば、元の並びと同じになる。

public enum Hoge  //※enum 型は任意
{
Apple,
//Banana,
Cat = 2,
Dog,
}
public Hoge hoge;

 また列挙型はデフォルトでは0からの整数連番だが、値は自由に割り当てられるので、飛び番号や負の値なども使える。色々やってみると良いだろう。



■enum の PlayerPrefs 保存と読み込み(Unity)

 Unity でユーザーデータとして enum 型の保存と読み込みをやってみよう。といっても内容的には先に述べた「enum←→stringの相互変換」をやっているだけである。ここでは Load と Save の機能を持ったメソッドを2つ作ったとする。シーンに UI-Button を2つ置いて、それぞれの OnClick() で呼び出すなどすれば、簡単に確認できるだろう。

using System;
using UnityEngine;

public enum Hoge { //※enum 型は任意
Apple,
Banana,
Cat,
Dog,
}
public Hoge hoge = Hoge.Apple;

string prefsName = "hoge";

public void LoadHoge() //UI-Button の OnClick に登録する等
{
string str = PlayerPrefs.GetString(prefsName, hoge.ToString());
hoge = (Hoge)Enum.Parse(typeof(Hoge), str);

Debug.Log("Loaded : " + hoge);
}

public void SaveHoge() //UI-Button の OnClick に登録する等
{
PlayerPrefs.SetString(prefsName, hoge.ToString());
PlayerPrefs.Save();

Debug.Log("Saved : " + hoge);
}

(インスペクタで「Banana」を選んで保存・読み込みをした場合)
Saved : Banana
Loaded : Banana

 ちなみに int 型で保存と読み込みをする場合には以下のように書ける。

・・・(略)・・・
public void LoadHoge()
{
int i = PlayerPrefs.GetInt(prefsName, (int)hoge);
hoge = (Hoge)Enum.ToObject(typeof(Hoge), i);

Debug.Log("Loaded : " + hoge + " (" + i + ")");
}

public void SaveHoge()
{
PlayerPrefs.SetInt(prefsName, (int)hoge);
PlayerPrefs.Save();

Debug.Log("Saved : " + hoge + " (" + (int)hoge + ")");
}
・・・(略)・・・

(インスペクタで「Banana」を選んで保存・読み込みをした場合)
Saved : Banana (1)
Loaded : Banana (1)

 stringint のどちらでも良いが、後から値の割当を変えたくなったときにも対応できるように、string 型で保存しておいた方が無難ではあるだろう(※public で宣言してる場合、後から変更するとインスペクタでの名前表示のずれが発生するので注意)。





(関連記事)
【Java】enum を int で取得する
【Java】文字列を enum 型に変換する
【Unity】色形式:Unity の Color と Android の ARGB(int32) の相互変換をする


関連記事

category: C#

thread: プログラミング

janre: コンピュータ

tag: C#リファレンス  Unityトラブルシューティング 
tb: 0   cm: --


プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR