8

I have a Direction Enum:

Public Enum Direction
    Left
    Right
    Top
    Bottom
End Enum

And Sometimes I need to get the inverse, so it seems nice to write:

SomeDirection.Inverse()

But I can't put a method on an enum! However, I can add an Extension Method (VS2008+) to it.

In VB, Extension Methods must be inside Modules. I really don't like modules that much, and I'm trying to write a (moderately) simple class that I can share in a single file to be plugged into other projects.

Modules can only reside in the file/namespace level so I have one in the bottom of the file now:

Public Class MyClass
    '...'
End Class

Public Module Extensions
    <Extension()> _
    Public Function Inverse(ByVal dir As Direction) As Direction
        '...'
    End Function
End Module

It works, and "if it ain't broke, don't fix it", but I'd love to know if I'm doing it wrong and there's a better way with less boilerplate. Maybe in .NET 4?

Finally, I know I could write a structure that behaves like an enum, but that seems even more backwards.

Camilo Martin
  • 37,236
  • 20
  • 111
  • 154
  • 1
    what you are doing is absolutely correct. Microsoft also proposes the same: http://msdn.microsoft.com/en-us/library/bb383974.aspx. – VinayC Oct 27 '10 at 05:16
  • I see (good find!), so it must be the right way. Still, I don't see why we can't put a method on an enum, it doesn't seem like it would break anything. – Camilo Martin Oct 27 '10 at 06:14

2 Answers2

7

That is indeed the only way to add (the appearance of) a method to an enum.

Note that in C# the extension method would be defined on a static class, but that is a trivial difference, largely one of nomenclature.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • in VB a class can't be declared shared (static). AFAIK they're equivalent to modules. But since an extension method is just sintactic sugar for a static one, I don't understand the need to put it in a different class (since a static method can reside in a non-static class) – Camilo Martin Oct 27 '10 at 06:21
  • An *extension* method cannot (in C#) reside in a non-static class, note. – Marc Gravell Oct 27 '10 at 07:32
  • I know it can't, but I don't understand the reason behind this. – Camilo Martin Oct 27 '10 at 09:42
  • In my opinion, the reason is that it forces clarity of purpose. Static methods within an instance class should be related to the class at hand. (Doesn't have to be, but it would be a very poor idea to have a static method that did not relate in some way to the instance class in which it resides.) An extension method, by design, can only modify a *different* class. So it would not be sensible to allow instance methods within a class that also contains extension methods -- by design, such a class would have unrelated methods. – Mike Rosenblum Dec 11 '10 at 19:28
  • As for the enum capabilities of C#, I would agree. As John Skeet comments within C# Programming Language Fourth Edition (http://www.amazon.com/Programming-Language-Covering-Microsoft-Development/dp/0321741765/ref=sr_1_1?s=books&ie=UTF8&qid=1292096345&sr=1-1) "This is one of the *very* few areas where Java is more expressive than C#. In Java, enums have a lot more power: An enum can declare methods and then override them for specific values... C# language (and framework) support in a future version would be extremely welcome." – Mike Rosenblum Dec 11 '10 at 19:42
1

You can make a class that behaves like an enum, in the sense that it has static readonly properties that return an instance of the class that contains that value.

The System.Drawing.Color structure for example works this way (although the internal value is not an enum); it has static properties like Color.Redand Color.White, as well as instance properties and methods.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Well, that would be way more boilerplate than just a module. Even a class is not necessary to emulate an enum - the same could be done in a structure. But it really looks weird to see a structure pretending to be an enum. – Camilo Martin Oct 27 '10 at 05:52
  • @Camilo Martin: Yes, as structure can also be used, but the reason that I suggested a class is that a structure is more complicated to implement correctly. It may seem weird to use a class intead of an enum, but on the other hand you get the methods in the class itself instead of in a separate module. – Guffa Oct 27 '10 at 06:26
  • Why complicated? This answer's code looks simple: http://stackoverflow.com/questions/1395401/enum-extension-method-todatasource/1395439#1395439 – Camilo Martin Oct 27 '10 at 09:47
  • 1
    @Camilo Martin: Well, that's an example why structures are more complicated to implement; that code doesn't compile. When fixed, it still doesn't support things that you take for granted, like the `==` operator. If you change it to a class, it works just fine (with only changing the private static properties to public). – Guffa Oct 27 '10 at 10:21