Enum
CSV 또는 유사한 파일에 사용되는 유효한 공통 구분 기호 를 정의 하고 추가 하려고 합니다. 그런 다음 ComboBox
Enum 정의에서 추가하거나 제거 할 때마다 콤보 상자에서 아무것도 변경할 필요가 없도록 데이터 소스로 바인딩 할 것입니다.
문제는 다음과 같이 문자열 표현으로 열거 형을 정의하는 방법입니다.
public enum SeparatorChars{Comma = ",", Tab = "\t", Space = " "}
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();
}
내가 아는 한 enum에 문자열 값을 할당 할 수 없습니다. 당신이 할 수있는 일은 그 안에 문자열 상수가있는 클래스를 만드는 것입니다.
public static class SeparatorChars
{
public static String Comma { get { return ",";} }
public static String Tab { get { return "\t,";} }
public static String Space { get { return " ";} }
}
separator
대신 문자열 (무엇이든 될 수 있음) 이기 때문에 컴파일 시간 동안 특정 값을 적용하는 데 도움이되지 않습니다 Separator
.
당신은 그것을 달성 할 수 있지만 약간의 작업이 필요합니다.
공개 열거 형 테스트 : int { [StringValue ( "a")] Foo = 1, [문자열 값 ( "b")] 무언가 = 2 }
참조 : C #에서 문자열 값이있는 열거 형
열거 형으로는 이것을 할 수 없지만 다음과 같이 할 수 있습니다.
public static class SeparatorChars
{
public static string Comma = ",";
public static string Tab = "\t";
public static string Space = " ";
}
comboBox.DataSource = Enum.GetValues(typeof(myEnum));
.이 경우 와 동등한 것이 무엇인지 말할 수 있습니까?
switch-case
블록 내에서 사용할 수 없기 때문에 이것이 거의 정답이라고 생각합니다 . 필드는 const
순서가 있어야합니다 . 그러나 원하는 경우 여전히 도움이 될 수 없습니다 Enum.GetValues(typeof(myEnum))
.
const
대신에 static
. 상수는 읽기 전용 일뿐만 아니라 정적이며 생성자에서 서명 할 수 없습니다 (읽기 전용 필드 제외).
enum은 원시 숫자 유형에만 기반 할 수 있기 때문에 불가능합니다. Dictionary
대신 a 를 사용해 볼 수 있습니다 .
Dictionary<String, char> separators = new Dictionary<string, char>
{
{"Comma", ','},
{"Tab", '\t'},
{"Space", ' '},
};
또는 a Dictionary<Separator, char>
또는 Dictionary<Separator, string>
where Separator
is a normal enum을 사용할 수 있습니다 .
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"
}
GrainType myGrain = "GT_CORN"
예를 들어 할 수 없다는 것입니다 .
대답하기에는 다소 늦었지만 미래에 누군가에게 도움이 될 수도 있습니다. 이런 종류의 문제에 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";
}
}
너무 늦었을 수도 있지만 여기에 있습니다.
EnumMember 속성을 사용하여 Enum 값을 관리 할 수 있습니다.
public enum EUnitOfMeasure
{
[EnumMember(Value = "KM")]
Kilometer,
[EnumMember(Value = "MI")]
Miles
}
이렇게하면 EUnitOfMeasure의 결과 값이 KM 또는 MI가됩니다. 이것은 Andrew Whitaker 대답 에서도 볼 수 있습니다 .
좀 더 일반적인 질문에 대한 답을 찾고있는 사람들을 위해 코드가 enum
.
다음 접근 방식은 enum names
원하는 것을 완료하지 않았고 enum values
의 string
표현이 될 때 작동 합니다 enam name
. 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"
}
.NET에서 문자열 값 열거 형을 만들기위한 기본 클래스를 만들었습니다. 프로젝트에 복사하여 붙여 넣거나 StringEnum 이라는 NuGet 패키지를 통해 설치할 수있는 단 하나의 C # 파일입니다 .
///<completionlist cref="HexColor"/>
class HexColor : StringEnum<HexColor>
{
public static readonly HexColor Blue = New("#FF0000");
public static readonly HexColor Green = New("#00FF00");
public static readonly HexColor Red = New("#000FF");
}
// Static Parse Method
HexColor.Parse("#FF0000") // => HexColor.Red
HexColor.Parse("#ff0000", caseSensitive: false) // => HexColor.Red
HexColor.Parse("invalid") // => throws InvalidOperationException
// Static TryParse method.
HexColor.TryParse("#FF0000") // => HexColor.Red
HexColor.TryParse("#ff0000", caseSensitive: false) // => HexColor.Red
HexColor.TryParse("invalid") // => null
// Parse and TryParse returns the preexistent instances
object.ReferenceEquals(HexColor.Parse("#FF0000"), HexColor.Red) // => true
// Conversion from your `StringEnum` to `string`
string myString1 = HexColor.Red.ToString(); // => "#FF0000"
string myString2 = HexColor.Red; // => "#FF0000" (implicit cast)
<completitionlist>
. (C # 및 VB 모두에서 작동) : 예어느 한 쪽:
.Net Standard 1.0
.Net Core
.Net Framework
Mono
public abstract class StringEnum<T> : IEquatable<T> where T : StringEnum<T>, new()
{
protected string Value;
private static IList<T> valueList = new List<T>();
protected static T New(string value)
{
if (value == null)
return null; // the null-valued instance is null.
var result = new T() { Value = value };
valueList.Add(result);
return result;
}
public static implicit operator string(StringEnum<T> enumValue) => enumValue.Value;
public override string ToString() => Value;
public static bool operator !=(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value != o2?.Value;
public static bool operator ==(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value == o2?.Value;
public override bool Equals(object other) => this.Value.Equals((other as T)?.Value ?? (other as string));
bool IEquatable<T>.Equals(T other) => this.Value.Equals(other.Value);
public override int GetHashCode() => Value.GetHashCode();
/// <summary>
/// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else throws InvalidOperationException.
/// </summary>
/// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
/// <param name="caseSensitive">If true, the strings must match case sensitivity.</param>
public static T Parse(string value, bool caseSensitive = false)
{
var result = TryParse(value, caseSensitive);
if (result == null)
throw new InvalidOperationException((value == null ? "null" : $"'{value}'") + $" is not a valid {typeof(T).Name}");
return result;
}
/// <summary>
/// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else returns null.
/// </summary>
/// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
/// <param name="caseSensitive">If true, the strings must match case sensitivity.</param>
public static T TryParse(string value, bool caseSensitive = false)
{
if (value == null) return null;
if (valueList.Count == 0) System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle); // force static fields initialization
var field = valueList.FirstOrDefault(f => f.Value.Equals(value,
caseSensitive ? StringComparison.Ordinal
: StringComparison.OrdinalIgnoreCase));
// Not using InvariantCulture because it's only supported in NETStandard >= 2.0
if (field == null)
return null;
return field;
}
}
Newtonsoft.Json
직렬화 지원, 대신이 확장 버전을 복사합니다. StringEnum.cs이 코드가 Ben의 대답과 비슷하다는 사실을 깨달았습니다. 처음부터 진심으로 썼습니다. 그러나 <completitionlist>
해킹 과 같은 몇 가지 추가 사항이 있다고 생각합니다 . 결과 클래스는 Enum, Parse ()에 대한 리플렉션 사용 안 함, NuGet 패키지 및 들어오는 문제와 피드백을 해결하기를 바라는 리포지토리처럼 보입니다.
여기에 몇 가지 답변을 기반으로 열거 형의 동작을 모방하지만 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;
}
}
누군가 이것이 유용하다고 생각하기를 바랍니다!
a char
또는 a string
를 열거 형의 기반으로 사용하는 것은 실제로 불가능하지만 이것이 당신이 정말로 좋아하는 것이 아니라고 생각합니다.
당신이 언급했듯이 당신은 가능성의 열거 형을 갖고 콤보 상자 내에 이것의 문자열 표현을 보여주고 싶습니다. 사용자가 이러한 문자열 표현 중 하나를 선택하면 해당 열거 형을 가져 오려고합니다. 그리고 이것은 가능합니다 :
먼저 일부 문자열을 열거 형 값에 연결해야합니다. 여기 또는 여기에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());
}
사용자는 열거 형의 모든 문자열 표현을 볼 수 있으며 코드 내에서 원하는 열거 형 값을 얻을 수 있습니다.
Enumaration 클래스
public sealed class GenericDateTimeFormatType
{
public static readonly GenericDateTimeFormatType Format1 = new GenericDateTimeFormatType("dd-MM-YYYY");
public static readonly GenericDateTimeFormatType Format2 = new GenericDateTimeFormatType("dd-MMM-YYYY");
private GenericDateTimeFormatType(string Format)
{
_Value = Format;
}
public string _Value { get; private set; }
}
에 누마 레이션 소비
public static void Main()
{
Country A = new Country();
A.DefaultDateFormat = GenericDateTimeFormatType.Format1;
Console.ReadLine();
}