Enum
を定義し、CSVまたは同様のファイルで使用される有効な共通セパレーターを追加しようとしています。次に、データソースとしてComboBox
にバインドするので、Enum定義に追加または削除するたびに、コンボボックスで何も変更する必要はありません。
問題は、次のような文字列表現で列挙型をどのように定義できるかです。
public enum SeparatorChars{Comma = ",", Tab = "\t", Space = " "}
できません-列挙値は整数値でなければなりません。属性を使用して文字列値を各列挙値に関連付けることができます。この場合、すべての区切り文字が単一の文字である場合は、単にchar
値を使用できます。
enum Separator
{
Comma = ',',
Tab = '\t',
Space = ' '
}
(編集:明確にするために、char
を列挙型の基本型にすることはできませんが、char
定数を使用して各列挙値に対応する整数値を割り当てることができます。上記の列挙型の基本型はint
です。)
次に、必要な場合は拡張メソッド:
public string ToSeparatorString(this Separator separator)
{
// TODO: validation
return ((char) separator).ToString();
}
私の知る限り、文字列値を列挙型に割り当てることはできません。できることは、文字列定数を含むクラスを作成することです。
public static class SeparatorChars
{
public static String Comma { get { return ",";} }
public static String Tab { get { return "\t,";} }
public static String Space { get { return " ";} }
}
あなたはそれを達成することができますが、少しの作業が必要になります。
public enum Test:int { [StringValue( "a")] Foo = 1、 [StringValue( "b")] 何か= 2 }
参照: C#の文字列値を持つ列挙
列挙型でこれを行うことはできませんが、次のように行うことができます。
public static class SeparatorChars
{
public static string Comma = ",";
public static string Tab = "\t";
public static string Space = " ";
}
文字列値(またはその他の型)の単純な列挙型の場合:
public static class MyEnumClass
{
public const string
MyValue1 = "My value 1",
MyValue2 = "My value 2";
}
使用法:string MyValue = MyEnumClass.MyValue1;
列挙型はプリミティブな数値型にのみ基づいているため、できません。代わりに Dictionary
を使用してみてください:
Dictionary<String, char> separators = new Dictionary<string, char>
{
{"Comma", ','},
{"Tab", '\t'},
{"Space", ' '},
};
または、Dictionary<Separator, char>
またはDictionary<Separator, string>
を使用できます。ここで、Separator
は通常の列挙型です。
enum Separator
{
Comma,
Tab,
Space
}
これは、文字列を直接処理するよりも少し快適です。
列挙型の動作をエミュレートするが、string
の代わりにint
を使用するクラスは、次のように作成できます...
public class GrainType
{
private string _typeKeyWord;
private GrainType(string typeKeyWord)
{
_typeKeyWord = typeKeyWord;
}
public override string ToString()
{
return _typeKeyWord;
}
public static GrainType Wheat = new GrainType("GT_WHEAT");
public static GrainType Corn = new GrainType("GT_CORN");
public static GrainType Rice = new GrainType("GT_RICE");
public static GrainType Barley = new GrainType("GT_BARLEY");
}
使用法...
GrainType myGrain = GrainType.Wheat;
PrintGrainKeyword(myGrain);
その後...
public void PrintGrainKeyword(GrainType grain)
{
Console.Writeline("My Grain code is " + grain.ToString()); // Displays "My Grain code is GT_WHEAT"
}
答えに少し遅れていますが、将来誰かを助けるかもしれません。この種の問題にはstructを使用する方が簡単だとわかりました。
次のサンプルは、MSコードから貼り付けられた部分をコピーしたものです。
namespace System.IdentityModel.Tokens.Jwt
{
//
// Summary:
// List of registered claims from different sources http://tools.ietf.org/html/rfc7519#section-4
// http://openid.net/specs/openid-connect-core-1_0.html#IDToken
public struct JwtRegisteredClaimNames
{
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Actort = "actort";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Typ = "typ";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Sub = "sub";
//
// Summary:
// http://openid.net/specs/openid-connect-frontchannel-1_0.html#OPLogout
public const string Sid = "sid";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Prn = "prn";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Nbf = "nbf";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Nonce = "nonce";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string NameId = "nameid";
}
}
より一般的な質問への回答を求めてここに来ている人のために、コードをenum
のように見せたい場合は、静的クラスの概念を拡張できます。
以下のアプローチは、必要なenum names
を確定しておらず、enum values
がenam name
のstring
表現である場合に機能します。 nameof()
を使用して、リファクタリングを簡単にします。
public static class Colours
{
public static string Red => nameof(Red);
public static string Green => nameof(Green);
public static string Blue => nameof(Blue);
}
これにより、文字列値(次の擬似コードなど)を持つ列挙型の意図が達成されます。
public enum Colours
{
"Red",
"Green",
"Blue"
}
char
またはstring
をenumのベースとして使用することは実際には不可能ですが、これはあなたが本当にやりたいことではないと思います。
あなたが述べたように、可能性の列挙を持ち、コンボボックス内にこれの文字列表現を表示したいと思います。ユーザーがこれらの文字列表現のいずれかを選択した場合、対応する列挙型を取得します。そして、これは可能です:
まず、文字列を列挙値にリンクする必要があります。これは、 here または here で説明されているようにDescriptionAttribute
を使用して実行できます。
次に、列挙値と対応する説明のリストを作成する必要があります。これは、次の方法を使用して実行できます。
/// <summary>
/// Creates an List with all keys and values of a given Enum class
/// </summary>
/// <typeparam name="T">Must be derived from class Enum!</typeparam>
/// <returns>A list of KeyValuePair<Enum, string> with all available
/// names and values of the given Enum.</returns>
public static IList<KeyValuePair<T, string>> ToList<T>() where T : struct
{
var type = typeof(T);
if (!type.IsEnum)
{
throw new ArgumentException("T must be an enum");
}
return (IList<KeyValuePair<T, string>>)
Enum.GetValues(type)
.OfType<T>()
.Select(e =>
{
var asEnum = (Enum)Convert.ChangeType(e, typeof(Enum));
return new KeyValuePair<T, string>(e, asEnum.Description());
})
.ToArray();
}
これで、すべての列挙型とその説明のキーと値のペアのリストができました。したがって、これをコンボボックスのデータソースとして単純に割り当てましょう。
var comboBox = new ComboBox();
comboBox.ValueMember = "Key"
comboBox.DisplayMember = "Value";
comboBox.DataSource = EnumUtilities.ToList<Separator>();
comboBox.SelectedIndexChanged += (sender, e) =>
{
var selectedEnum = (Separator)comboBox.SelectedValue;
MessageBox.Show(selectedEnum.ToString());
}
ユーザーには列挙型のすべての文字列表現が表示され、コード内で目的の列挙型値を取得できます。
まず、文字が1文字であっても、文字ではなく文字列を割り当てようとします。 「、」の代わりに「、」を使用します。次に、enumはchar
のない整数型のみを取ります。Unicode値を使用できますが、そうしないことを強くお勧めします。これらの値が異なる文化や言語で同じままであることを確信している場合、私はconst文字列を持つ静的クラスを使用します。
ここでいくつかの答えに基づいて、列挙型の動作を模倣する再利用可能な基本クラスを実装しましたが、基になる型はstring
です。以下を含むさまざまな操作をサポートします。
.Equals
、==
、および!=
を介した他のインスタンスとの比較これは、全体の基本クラスです。
public abstract class StringEnumBase<T> : IEquatable<T>
where T : StringEnumBase<T>
{
public string Value { get; }
protected StringEnumBase(string value) => this.Value = value;
public override string ToString() => this.Value;
public static List<T> AsList()
{
return typeof(T)
.GetProperties(BindingFlags.Public | BindingFlags.Static)
.Where(p => p.PropertyType == typeof(T))
.Select(p => (T)p.GetValue(null))
.ToList();
}
public static T Parse(string value)
{
List<T> all = AsList();
if (!all.Any(a => a.Value == value))
throw new InvalidOperationException($"\"{value}\" is not a valid value for the type {typeof(T).Name}");
return all.Single(a => a.Value == value);
}
public bool Equals(T other)
{
if (other == null) return false;
return this.Value == other?.Value;
}
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj is T other) return this.Equals(other);
return false;
}
public override int GetHashCode() => this.Value.GetHashCode();
public static bool operator ==(StringEnumBase<T> a, StringEnumBase<T> b) => a?.Equals(b) ?? false;
public static bool operator !=(StringEnumBase<T> a, StringEnumBase<T> b) => !(a?.Equals(b) ?? false);
public class JsonConverter<T> : Newtonsoft.Json.JsonConverter
where T : StringEnumBase<T>
{
public override bool CanRead => true;
public override bool CanWrite => true;
public override bool CanConvert(Type objectType) => ImplementsGeneric(objectType, typeof(StringEnumBase<>));
private static bool ImplementsGeneric(Type type, Type generic)
{
while (type != null)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == generic)
return true;
type = type.BaseType;
}
return false;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken item = JToken.Load(reader);
string value = item.Value<string>();
return StringEnumBase<T>.Parse(value);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is StringEnumBase<T> v)
JToken.FromObject(v.Value).WriteTo(writer);
}
}
}
そして、これは「文字列列挙」を実装する方法です。
[JsonConverter(typeof(JsonConverter<Colour>))]
public class Colour : StringEnumBase<Colour>
{
private Colour(string value) : base(value) { }
public static Colour Red => new Colour("red");
public static Colour Green => new Colour("green");
public static Colour Blue => new Colour("blue");
}
これは次のように使用できます:
public class Foo
{
public Colour colour { get; }
public Foo(Colour colour) => this.colour = colour;
public bool Bar()
{
if (this.colour == Colour.Red || this.colour == Colour.Blue)
return true;
else
return false;
}
}
誰かがこれが役に立つと思うことを願っています!
列挙を文字列型として定義することはできません。列挙型の承認されたタイプは、byte、sbyte、short、ushort、int、uint、long、またはulongです。
列挙の詳細が必要な場合は、以下のリンクに従ってください。そのリンクは列挙を理解するのに役立ちます。 列挙
しゅう
わたしにはできる..
public class ShapeTypes
{
private ShapeTypes() { }
public static string OVAL
{
get
{
return "ov";
}
private set { }
}
public static string SQUARE
{
get
{
return "sq";
}
private set { }
}
public static string RECTANGLE
{
get
{
return "rec";
}
private set { }
}
}