Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
148 views
in Technique[技术] by (71.8m points)

c# - How to avoid repeating typing the same name multiple times within the same scope?

I have the following enum:

public enum Event0Instance
{
    ClaimSent,
    RequestSent,
    ClaimResponseAqcuired,
    RequestResponseAqcuired,
    RequestRefusalAcquired,
}

With this enum I've made dictionary Dictionary<Event0Instance, string> where string value is the text description of each enum value:

public static Dictionary<Event0Instance, string> Event0Descriptions = 
  new Dictionary<Event0Instance, string>() 
  {
    {Event0Instance.ClaimSent, "Подана претензия" },
    {Event0Instance.RequestSent, "Подан запрос"},
    {Event0Instance.ClaimResponseAqcuired, "Получен ответ на претензию"},
    {Event0Instance.RequestResponseAqcuired, "Получен ответ на запрос"},
    {Event0Instance.RequestRefusalAcquired, "Получен отказ на запрос"}
  };

The obvious problem here is the need to repeat Event0Instance. with each entry. There are more enums, each bigger than the one in the example, if I want to make a Dictionary for each of them it's a huge code repetition.

In VBA language there is a With / End Withconstruct which you could use like this:

With Person
    .FirstName = "John"
    .LastName = "Smith"
    .Age = 23
End With

Is there somethings similar in C#?

question from:https://stackoverflow.com/questions/65643417/how-to-avoid-repeating-typing-the-same-name-multiple-times-within-the-same-scope

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In order just to skip pesky Event0Instance. prefix can you try using static construction which works roughly similar to with .. end with:

using static MyNamespace.Event0Instance;

...

public static Dictionary<Event0Instance, string> Event0Descriptions =
  new Dictionary<Event0Instance, string>() 
  {
    {ClaimSent, "Подана претензия" },
    {RequestSent, "Подан запрос"},
    {ClaimResponseAqcuired, "Получен ответ на претензию"},
    {RequestResponseAqcuired, "Получен ответ на запрос"},
    {RequestRefusalAcquired, "Получен отказ на запрос"}
  };

However, I suggest using attributes and build dictionary with a help of Linq and Reflection:

// Here we attribute each option with the desired description
public enum Event0Instance
{
    //TODO: do not hardcode the descriptions ("Подана претензия") 
    // but put resource name here
    [Description("Подана претензия")]
    ClaimSent,
    [Description("Подан запрос")]
    RequestSent,
    [Description("Получен ответ на претензию")]
    ClaimResponseAqcuired,
    [Description("Получен ответ на запрос")]
    RequestResponseAqcuired,
    [Description("Получен отказ на запрос")]
    RequestRefusalAcquired,
}

Here is the routine to inspect the enum given and returns {option, description} dictionary:

using System.Linq;
using System.Reflection;

...

// This routine inspects the enum given and return dictionary: {option, description} 
public static Dictionary<T, string> EnumDescriptions<T>() where T : Enum {
  return Enum
    .GetNames(typeof(T))
    .Select(name => new {
      name,
      value = Enum.Parse(typeof(T), name),
      member = typeof(T).GetMember(name)[0]
    })
    .ToDictionary(item => (T) (item.value),
                  item => item.member
                    .GetCustomAttributes<DescriptionAttribute>(true)
                    .FirstOrDefault()?.Description ?? item.name);
}

and then you can build the dictionaries in one line of code:

// I doubt if you want public (!) Dictionary exposed to everyone;
// I guess readonly interface will be enough
public static readonly IReadOnlyDictionary<Event0Instance, string> Event0Descriptions = 
  EnumDescriptions<Event0Instance>();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...