前提
- unity 2018.4.9f1
困ったこと、やりたいこと
-
default (SystemLanguage)
は、SystemLanguage.Afrikaans
で、SystemLanguage.Unknown
ではありません。 -
Unknown
を含む全てのSystemLanguage
値と区別可能な「Undef
」をdefault
値に持つ、SystemLanguage
の拡張型が欲しいです。
試したこと
継承して拡張する
-
SystemLanguage
は列挙型なので継承できませんでした。
Null許容型を流用する
-
SystemLanguage?
を使って、null
を未定義とみなすようにしてみました。 - 諸々の不具合が生じて断念しました。
新しい型を作る
- 上記の
Nullable<T>
での失敗から、Booleanable<Language>
という概念を考えてみました。
解決策
- 論理値も持つ
Language
構造体を作ってみたところ、取り敢えず使えそうです。
特徴
- デフォルト値は
Language.Undef
です。-
Language lang = default;
とすると、lang
にはLanguage.Undef
が入ります。 - 構造体なので、未初期化のままで使用することはできません。
-
-
Language.Undef
は、SystemLanguage
に対してSystemLanguage.Unknown
として振る舞います。-
SystemLanguage syslang = lang;
とすると、syslang
にはSystemLanguage.Unknown
が入ります。
-
-
SystemLanguage
と互換性があり、相互に代入や比較(暗黙の型変換)が可能です。-
Language lang = SystemLanguage.Japanese;
ができます。 -
SystemLanguage syslang = lang;
ができます。 -
if (lang == SystemLanguage.Japanese) { }
ができます。
-
- 論理値を持ちます。
-
if (lang) { }
のような論理値コンテキストでは、Language.Undef
以外なら真になります。 -
lang = Language.Undef;
と、lang = false;
は同じ結果です。
-
- 文字列型と相互に変換が可能です。
-
ToString ()
ができます。 -
Enum
準拠で、Language.Parse ()
,Language.TryParse ()
ができます。-
SystemLanguage
に存在しない名前は、全てLanguage.Undef
になります。
-
-
-
Nullable<T>
に似た実装です。(たぶん)-
GetValueOrDefault ()
ができます。
-
コード
BooleanableSystemLanguage.cs
using System;
using UnityEngine;
public struct Language : IEquatable<Language> {
private bool hasValue;
private SystemLanguage language;
public static readonly Language Undef = new Language (false);
public Language (bool _hasValue) {
hasValue = _hasValue;
language = _hasValue ? Application.systemLanguage : SystemLanguage.Unknown;
}
public Language (SystemLanguage _language) {
hasValue = _language != SystemLanguage.Unknown;
language = _language;
}
public static bool TryParse (string name, bool ignoreCase, out Language language) {
if (string.IsNullOrEmpty (name) || !Enum.TryParse (name, ignoreCase, out SystemLanguage syslang)) {
language = Undef;
return false;
}
language = syslang;
return true;
}
public static bool TryParse (string name, out Language language) => TryParse (name, false, out language);
public static Language Parse (string name, bool ignoreCase) { TryParse (name, ignoreCase, out var language); return language; }
public static Language Parse (string name) { TryParse (name, false, out var language); return language; }
public SystemLanguage GetValueOrDefault () => hasValue ? language : SystemLanguage.Unknown;
public SystemLanguage GetValueOrDefault (Language l) => hasValue ? language : (SystemLanguage) l;
public static implicit operator bool (Language l) => l.hasValue;
public static implicit operator SystemLanguage (Language l) => l.hasValue ? l.language : SystemLanguage.Unknown;
public static implicit operator Language (bool b) => new Language (b);
public static implicit operator Language (SystemLanguage l) => new Language (l);
public override string ToString () => hasValue ? language.ToString () : "Undef";
public static bool operator == (Language a, Language b) => (a.hasValue == b.hasValue) && (!a.hasValue || a.language == b.language);
public static bool operator != (Language a, Language b) => !(a == b);
public bool Equals (Language other) => (hasValue == other.hasValue) && (language == other.language);
public override bool Equals (object obj) => (obj == null || GetType () != obj.GetType ()) ? false : Equals ((Language) obj);
public override int GetHashCode () => hasValue ? language.GetHashCode () : int.MinValue;
}