1

This is a hang over from my Delphi days where I was able to do something as follows:

  type
   TCars  = (Ford, Nissan, Toyota, Honda);     
  const
      CAR_MODELS = array[TCars] of string = ('Falcon','Sentra','Camry','Civic');

which allowed me to an enumeration declartively with some associated data. In this case a string but it could have been a record structure or similair. It meant that if I added a member to TCars and forgot to update the CAR_MODELS array I would get a compile time error.

What is the C# approach to this? I have tried:

public enum ReportFileGeneratorFileType
{
    Excel,
    Pdf,
    Word
}

string[ReportFileGeneratorFileType] myArray = {"application/vnd.ms-excel", "application/pdf", "application/vnd.ms-word"};

but that does not appear to compile.

5
  • I don't think c# has something that will give you an error if you don't update a description. Commented Jun 4, 2013 at 7:39
  • C# has no string based enumeration that will be checked on compile time. The suggestion to use a Dictionary<TKey, TValue> is probably your best bet, however this will be created at runtime Commented Jun 4, 2013 at 7:49
  • You can keep descriptions defined declaratively on the enum itself. This doesn't give compile-time errors, but minimizes such mistakes. Commented Jun 4, 2013 at 7:49
  • @JacekGorgoń Yes but if I wanted to add additional information then I would not be able to. Idea here is that I may also say want to add the file extension to the enum as well as say the mime type encoding. Commented Jun 4, 2013 at 12:51
  • Actually, this would be trivial to extend, either by extending the single attribute to hold more values or by adding a new attribute, depending on the context. In fact, it seems more extensible than the Delphi approach. Commented Jun 6, 2013 at 9:20

3 Answers 3

3

You should use Dictionary<key, value> as

var myArray = new Dictionary<ReportFileGeneratorFileType, string>();
myArray[ReportFileGeneratorFileType.Excel] = "application/vnd.ms-excel";
Sign up to request clarification or add additional context in comments.

1 Comment

Unfortunately that code has to then be maintained when I add a member to ReportFileGeneratorFileType which is what I am trying to avoid.
2

You could use an attribute (custom or built-int, such as DisplayNameAttribute) over the enum values to give them associated names/values. Example custom attribute follows:

public class ContentTypeAttribute : Attribute
{
    public string ContentType { get; set; }
    public ContentTypeAttribute(string contentType) 
    { 
         ContentType = contentType;
    }
}

public enum ReportFileGeneratorFileType
{
    [ContentType("application/vnd.ms-excel")]
    Excel,

    [ContentType("application/pdf")]
    Pdf,

    [ContentType("application/vnd.ms-word")]
    Word
}

To retrieve the content type based on an enum value, use:

...
ReportFileGeneratorFileType myType = ...
string contentType = myType.GetType()
    .GetCustomAttributes(typeof(ContentTypeAttribute))
    .Cast<ContentTypeAttribute>()
    .Single()
    .ContentType;
...

This may seem kind of complicated, but lets you keep content types (or whatever data) right on the enum itself, so you're not likely to forget adding it after adding a new type.

1 Comment

Note that the retrieval can be optimized significantly; this is just a basic approach written from scratch.
1

In c# you can use Attributes, using this namespace

using System.ComponentModel;

You can add Description attribute to your enum elements

public enum ReportFileGeneratorFileType
{
    [Description("application/vnd.ms-excel")]
    Excel,
    [Description("application/pdf")]
    Pdf,
    [Description("application/vnd.ms-word")]
    Word
}

And using these methods you can "extract" a Dictionary<ReportFileGeneratorFileType, string> from your enum and use it on your code.

5 Comments

Implementing this takes 3 minutes and gives reasonable assurance the author seeks.
Well, yes... He probably won't need this much trouble, but it can be done. For someone new to c# might consume sometime, but to use after that it will be easy :)
I've used this approach before, but I had to discard it when trying to do internationalization and localization because it gets far too fiddly then.
The actual values here suggests it's MIME-type or at least something not influenced by locale. Also, hardcoded dictionaries won't be useful when localizing either.
@BrunoLM Writing the extension methods to create the dictionary is a novel idea. And I guess extended with generics so that if I also wanted to store say FileSize (int) and FileExtension (string) I could create additional attributes I could store all of this in a struct in the dictionary. For sure adding the attributes will mean it is less easy to forget to add all the "additional info" when a new member is added. This is still however not a compile time check and would be rather cumbersome. The Delphi approach is so much cleaner, elegant and way less code :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.