1

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#?

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
Igor Cheglakov
  • 525
  • 5
  • 11
  • Does this help? https://stackoverflow.com/questions/1175334/whats-the-c-sharp-equivalent-to-the-with-statement-in-vb – squillman Jan 09 '21 at 13:53
  • 1
    Is there any reason as to why you are not using `DisplayAttribute`? – Anup Sharma Jan 09 '21 at 13:56
  • 1
    Modern IDE provide plenty of features to copy/paste values in many different ways ;) – Fabio Jan 09 '21 at 13:59
  • @AnupSharma I decided it's too much of a hack for my skills right now, besides, I'm not entirely sure wheither to associate every enum value with just a string, or an entire class. – Igor Cheglakov Jan 09 '21 at 14:01
  • Actually it is a good practice that you type all the name of Enum and as it have been told earlier, IDE help you to rename all accurances with one shot. But as for me, use method with new "case" syntax instead of dictionary, because you will 100% code additional method for utilixing your dictionary. The only good idea to use dictionary is when you perform data as json config file for example, but don't forget about validation. – Ivan Khorin Jan 09 '21 at 14:04

1 Answers1

4

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>();
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • The solution with the attribute is nice, but doesn't scale well. If you have several languages to support, that's going to cause quite a mess in your code, besides that you'll probably don't want to have all the translations in the source, anyway. – PMF Jan 09 '21 at 15:35
  • PMF, right, the solution is nice. As for the translations - attributes can contain references to entries in a resource file. – serge.karalenka Jan 09 '21 at 15:38
  • @PMF: if we want to support many a language (say, English, Russian as in the question, German, French etc.) we can store in the attribute not a description name itself, but *resource name*. Then all we have to do is to modify slightly `EnumDescriptions` routine – Dmitry Bychenko Jan 09 '21 at 15:39