J'essaie de définir un Enum
et d'ajouter des séparateurs communs valides utilisés dans des fichiers CSV ou similaires. Ensuite, je vais le lier à une ComboBox
en tant que source de données afin que, chaque fois que j'ajoute ou supprime de la définition Enum, je n'ai besoin de rien modifier dans la liste déroulante.
Le problème est comment puis-je définir enum avec une représentation sous forme de chaîne, quelque chose comme:
public enum SeparatorChars{Comma = ",", Tab = "\t", Space = " "}
Vous ne pouvez pas - les valeurs énumérées doivent être des valeurs intégrales. Vous pouvez utiliser des attributs pour associer une valeur de chaîne à chaque valeur enum ou, dans ce cas, si chaque séparateur est un seul caractère, vous pouvez simplement utiliser la valeur char
:
enum Separator
{
Comma = ',',
Tab = '\t',
Space = ' '
}
(EDIT: Juste pour clarifier, vous ne pouvez pas définir char
comme type sous-jacent de l’énum, mais vous pouvez utiliser les constantes char
pour attribuer la valeur intégrale correspondant à chaque valeur enum. Le type sous-jacent de l’énumération ci-dessus est int
.)
Ensuite, une méthode d'extension si vous en avez besoin:
public string ToSeparatorString(this Separator separator)
{
// TODO: validation
return ((char) separator).ToString();
}
Autant que je sache, vous ne serez pas autorisé à attribuer des valeurs de chaîne à enum. Ce que vous pouvez faire est de créer une classe avec des constantes de chaîne.
public static class SeparatorChars
{
public static String Comma { get { return ",";} }
public static String Tab { get { return "\t,";} }
public static String Space { get { return " ";} }
}
Vous pouvez y arriver, mais cela demandera un peu de travail.
public enum Test: int { [StringValue ("a")] Foo = 1, [StringValue ("b")] Quelque chose = 2 }
Référez-vous: Enum avec les valeurs de chaîne en C #
Vous ne pouvez pas faire cela avec des enums, mais vous pouvez le faire comme ça:
public static class SeparatorChars
{
public static string Comma = ",";
public static string Tab = "\t";
public static string Space = " ";
}
Pour une simple énumération de valeurs de chaîne (ou de tout autre type):
public static class MyEnumClass
{
public const string
MyValue1 = "My value 1",
MyValue2 = "My value 2";
}
Utilisation: string MyValue = MyEnumClass.MyValue1;
Vous ne pouvez pas, car enum ne peut être basé que sur un type numérique primitif . Vous pouvez utiliser un Dictionary
à la place:
Dictionary<String, char> separators = new Dictionary<string, char>
{
{"Comma", ','},
{"Tab", '\t'},
{"Space", ' '},
};
Vous pouvez également utiliser un Dictionary<Separator, char>
ou Dictionary<Separator, string>
où Separator
est une énumération normale:
enum Separator
{
Comma,
Tab,
Space
}
ce qui serait un peu plus agréable que de manipuler les cordes directement.
Une classe qui émule le comportement enum mais en utilisant string
au lieu de int
peut être créée comme suit ...
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");
}
Usage...
GrainType myGrain = GrainType.Wheat;
PrintGrainKeyword(myGrain);
puis...
public void PrintGrainKeyword(GrainType grain)
{
Console.Writeline("My Grain code is " + grain.ToString()); // Displays "My Grain code is GT_WHEAT"
}
Il est un peu tard pour répondre, mais peut-être que cela aidera quelqu'un à l'avenir. J'ai trouvé plus facile d'utiliser struct pour ce genre de problème.
L’échantillon suivant est copié en partie à partir du code 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";
}
}
Bien qu'il ne soit vraiment pas possible d'utiliser une char
ou une string
comme base pour une énumération, je pense que ce n'est pas ce que vous aimez vraiment faire.
Comme vous l'avez mentionné, vous aimeriez avoir une liste de possibilités et en afficher une représentation sous forme de chaîne dans une liste déroulante. Si l'utilisateur sélectionne l'une de ces représentations sous forme de chaîne, vous souhaitez extraire l'énumération correspondante. Et c'est possible:
Nous devons d'abord lier une chaîne à une valeur enum. Cela peut être fait en utilisant la variable DescriptionAttribute
telle qu'elle est décrite ici ou ici .
Vous devez maintenant créer une liste de valeurs enum et les descriptions correspondantes. Cela peut être fait en utilisant la méthode suivante:
/// <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();
}
Vous aurez maintenant une liste de paires de valeurs de clé de tous les énumérations et leur description. Nous allons donc simplement assigner ceci comme source de données pour une liste déroulante.
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());
}
L'utilisateur voit toutes les représentations sous forme de chaîne de l'énum et dans votre code, vous obtenez la valeur enum souhaitée.
Bien, essayez d’abord d’attribuer des chaînes, pas des caractères, même s’ils ne sont qu’un seul caractère. utilisez ',' au lieu de ",". Ensuite, les énumérations ne prennent que des types entiers sans char
, vous pouvez utiliser la valeur unicode, mais je vous déconseille vivement de le faire . utiliserait une classe statique avec des chaînes const.
En me basant sur certaines des réponses ici, j'ai implémenté une classe de base réutilisable qui imite le comportement d'un enum mais avec string
comme type sous-jacent. Il prend en charge diverses opérations, notamment:
.Equals
, ==
et !=
C'est la classe de base dans son intégralité:
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);
}
}
}
Et voici comment vous implémenteriez votre "string enum":
[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");
}
Ce qui pourrait être utilisé comme ceci:
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;
}
}
J'espère que quelqu'un trouvera cela utile!
Pour les personnes qui arrivent ici et cherchent une réponse à une question plus générique, vous pouvez étendre le concept de classe statique si vous voulez que votre code ressemble à un enum
.
L'approche suivante fonctionne lorsque vous n'avez pas finalisé le enum names
souhaité et que le enum values
est la représentation string
du enam name
; utilisez nameof()
pour simplifier votre refactoring.
public static class Colours
{
public static string Red => nameof(Red);
public static string Green => nameof(Green);
public static string Blue => nameof(Blue);
}
Cela réalise l'intention d'une énumération qui a des valeurs de chaîne (telles que le pseudocode suivant):
public enum Colours
{
"Red",
"Green",
"Blue"
}
Nous ne pouvons pas définir l'énumération comme type de chaîne. Les types approuvés pour une énumération sont byte, sbyte, short, ushort, int, uint, long ou ulong.
Si vous avez besoin de plus de détails sur le dénombrement, veuillez suivre le lien ci-dessous, ce lien vous aidera à comprendre le dénombrement . Énumération
@ narendras1414
Ça marche pour moi..
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 { }
}
}