Extension Methods in Vb.Net and C#


My world shattered today (not really, but it came close to). You see, I am a C# developer. I don’t like VB too much at all (though when I have to I can code in it). So, it was to my horror when I found out that there was this one thing that I could do in Vb.Net but had no way of doing in C#. This involves Extension Methods of course (as the title says).

I was trying to create an extension method for the enum type. Just like you can convert an enum variable to it’s string representation by calling the inbuilt ToString() method, I wanted to add a method which would set an enum variable’s value from a given string. I was going to call this method FromString(). Here’s where it started going downhill.

Vb.Net and C# have different ways of defining extension methods. Take a look below:

In C#:

public static class Extensions
{
  public static void FromString(this Enum theEnum, 
                                string fromString)
  {
    theEnum = (Enum)Enum.Parse(theEnum.GetType(), 
                               fromString);
  }
}

In Vb.Net, the same thing:

Public Module Extensions
  <Extension()>_
  Public Sub FromString(ByRef theEnum As System.Enum, 
                        ByVal fromString As String)
    theEnum = System.Enum.Parse(theEnum.GetType(), _
                                fromString, ignoreCase)
  End Sub
End Module

Notice that other than the syntactical differences in the two declarations, there is one major difference. The method in C#, will never work. The reason is that the enum is passed into it by Value and not by reference. And the C# compiler doesn’t allow you to pass in that particular method parameter by ref (for that matter you can’t put any other keyword next to it other than ‘this’).

While in VB.Net, I am allowed to pass in that particular parameter by ref (as you can see in the code). The extension method works exactly as expected in Vb.Net, but not in C#.

What’s more, if I define this extension method in a Vb.Net class library, and I import that library into my C# project, I still can’t use this extension method on my Enum, like I would use a C# extension method.

This wasted a lot of my time and caused me a lot of grief. Here’s one thing that Vb.Net developers have that I have no way of doing. Aarrghhh.


41 thoughts on “Extension Methods in Vb.Net and C#”

  1. Interesting article. I like learning about these little differences. I do have a question about what you are trying to accomplish with your extension method though:

    Why would you want this extension method to return void? If I am understanding correctly You want the usage to look something like:

    MyEnum e = MyEnum.Val1;
    e.FromString(“Val2″);

    So on the first like you set the value and then you change it on the second line using the FromString extension methods.

    This doesn’t feel right to me. Wouldn’t you want to do something like:

    MyEnum e = “Val2″.ToEnum();

    Am I missing something?

  2. Can you please post an example usage of how you use this in VB.NET? I’m still not clear what target usage is and why you’d want this in the first place.

    You said: “there are times when you might want to convert a string into a specific enum value”

    And you can do that without the ByRef stuff, so I guess, like Luke, I’m confused as to what the issue is here.

  3. Like others, I’m a bit confused as to what you are truly trying here. You seem to be trying to use an Enum where a Struct should be, perhaps. Then again I’ve never seen any examples of where you would attempt to instantiate an enum type variable so I could be wrong.

    For your extension method, I would see it not returning void but the value of the enum for the label you are providing it.

    For example:

    public enum FooBarEnum { Foo = 1, Bar }
    public static int FromLable(this FooBarEnum fbEnum, string myLabel)
    {

    }

    This isn’t setting the Enum’s value for it to be used throughout, it’s returning the value of the Enum to be stored in a different int variable for managing or to be called directly from methods that use this enum.

    If this was a struct, then I can see it working the way you have it; where you are passing the instance by ref into an extension and setting values with it. Then again, you’d only really need to create an extension method for the struct if you dont’ have access to the struct’s code in the first place. The same holds true for this enum example too.

    The more I think about this, it almost feels you are using extension methods just to use them or using them to cover up a different issue. – Sorry, but I just don’t get it.

  4. Okay, here’s a fictional but representative example. Let’s say I have a class Person, which has a property MaritalStatus. Let’s say the property MaritalStatus is an enum {Single, Married, Divorce}.

    Further, let’s say that I have a flat file from where I am reading records where each record represents an instance of Person. In this flat file, the MaritalStatus is represented by one of these strings: “Single”, “Married”, “Divorced”.

    If I am reading the file and loading the values into instances of Person class through a Load method in the Person class, then it would be very simple from within it to call _maritalStatus.FromString(status); here status would be a string representing the marital status just read from the flat file.

    I am trying to replace the usual clunky Enum.Parse routine that you would otherwise have to call (and then specify type information and then cast the output).

    Maybe it will be more clear if instead of FromString(), I call this method SetFromString()?

  5. It still seems like you would just want to call:

    _maritalStatus = status.ToEnum();

    inside of your load method. That is much more straight forward and easier to understand. Is there a reason that won’t work in your scenario?

  6. Hi Luke,

    yes, you are right there as well. it will definitely work.

    I just was trying to see if I can extend an Enum, as it seems natural that each Enum should have a way of initializing itself from a String.

    And I wasn’t trying to solve a problem. I was just working on trying out that thought.

    Thanks for all the comments, everyone.

  7. I gotta side with the other guys too :) Typically I don’t expect extension methods to make changes to the object I’m calling them on. I’l be much happier with this:

    _maritalStatus = status.ToEnum();

    …where ‘status’ is the string. Even nicer would be a generic extension method like this:

    public static class Extensions
    {
    public static T ToEnum( this string str ) where T : enum
    {
    return (T)Enum.Parse( typeof( T ), str );
    }
    }

    …Then you could use it like this:

    public enum MaritalStatus { Single, Married, Divorced };

    _maritalStatus = status.ToEnum();

    I didn’t test this though, so sorry if it’s not quite right.

  8. Shame – looks like angle brackets get removed from your blog’s comments :(

    Think the only thing that was messed up was the usage example:

    _maritalStatus = status.ToEnum<>();

    …or if that still gets trimmed, just pretend the squiggles below are angle brackets:

    _maritalStatus = status.ToEnum{MaritalStatus}();

    …one of those should work. If not, it’s close enough :)

  9. @Chris :D

    thanks for trying :)

    Well yes, the example you give is definitely an alternative. But for argument’s sake, to me it doesn’t make as much sense for a ‘string’ to be worried about how to convert itself into an enum as compared for an enum to know how to convert itself from a string.

    But the point is moot, as I can’t do it anyway.

  10. You all are missing the point. The point is that C# can’t do something VB can. Making excuses why he doesn’t need to do it in this case doesn’t matter. It’s hard but you curly bracket guys will just have to live with it.

  11. I’m a little late to the discussion, but here’s two cents:

    Although yes, VB can do something C# can’t (it does occasionally happen! ;) ), in this particular case I would argue along with the others that you shouldn’t do things the way you initialy wanted to do them.

    Enumerations are designed to be read-only value types, similar to integers (which they are, under the covers), booleans, and floats. Extension methods to enumerations should follow that paradigm — they should not modify the underlying value, they should return a new, updated value. Although you would always know that the method operates on the instance itself, the average person maintaining your code would expect different execution.

    I would argue that the method you linked to in your first reply is the best method of parsing an enumeration, even though it extends string rather than Enums. It has problems though; you cannot constrain a generic method against the type Enum. I don’t quite know *why* you can’t do it, but the C# compiler balks with “Constraint cannot be special class ‘System.Enum’” for some reason. That means the linked method has to check the type and throw an ArgumentException, and that just doesn’t make sense, in my opinion. I mean, is the generic type actually an argument to the method call?

  12. Hi Randolpho,

    Let me put it this way. Enums aside, I can’t pass any type by Refernce in an extension method in C#, while in Vb.Net I can. So, while I agree with all of you that maybe an enum is not the best example of demonstrating this and my original goal was probably not the best of ideas (my defense aside), the main point is the significant difference in the two languages when it comes to extension methods.

    That is my only point of contention. Actually, it’s not the only one. There is one more thing that I tried which left me even more exasperated (and I mention it at the end of my post). When I declared extension methods in a VB class library project, and imported it in a C# application, the extension methods did not attach to their types. I had to call them explicitly (ModuleName.MethodName(type_extended)).

    While if I do the opposite (extension methods created in # and imported in VB) they work as expected.

    Well, life’s tough I guess :)

  13. Yeah, the ByVal/ByRef at will thing is pretty much the biggest selling point for me for VB. That and the My namespace. :)

    It’s not enough for me to overcome the nasty VB syntax, though. :D

    That VB importation thing worries me, though. VB extension methods should work in C#. Let me go test that and get back to you.

  14. I’m afraid Peter’s wrong; it *can* be called just like a normal extension method — I’ve just successfully tested it.

    I ran into problems trying to test it, though, so let me give you a walkthrough of my successful test:

    1) First, I created a VB.Net project in a scratch solution called “Extenders” with a default namespace of “Extenders”
    2) Next, I created a module which I didn’t bother renaming “Module1″
    3) Within that, I created a simple extension method that adds the phrase “Hello World!” to a string. Here is the full code:

    Imports System.Runtime.CompilerServices

    Public Module Module1
    <Extension()> Public Function AddHello(ByVal val As String) As String
    Return val + “Hello World!”
    End Function
    End Module

    4) Finally, I created a simple C# application to call it, adding a reference to the Extenders project. Here’s the complete code:

    using System;
    using Extenders;
    namespace ExtenderTest
    {
    public class TestExtender
    {
    public static string TestAddHello()
    {
    string test = “Test”;
    return test.AddHello();
    // returns “TestHello World!”
    }
    }
    }

    I mentioned trouble; the trouble was my natural C#-oriented inclination to add a namespace declaration to my code.

    I had noticed that Visual Studio hadn’t added a namespace declaration to Module1.vb when I had created it, so I had inserted it myself, like this:

    Imports System.Runtime.CompilerServices

    Namespace Extenders
    Public Module Module1
    <Extension()> Public Function AddHello(ByVal val As String) As String
    Return val + “Hello World!”
    End Function
    End Module
    End Namespace

    My test code (as shown in step 4 above) failed to compile. After confirming that I *should* be able to do it via google, I started messing around, and eventually got my C# code to compile as follows:

    using System;
    using Extenders.Extenders; // <– the difference is here!
    namespace ExtenderTest
    {
    public class TestExtender
    {
    public static string TestAddHello()
    {
    string test = “Test”;
    return test.AddHello();
    // returns “TestHello World!”
    }
    }
    }

    I pointed out the difference with a comment, since it’s a little subtle. It turns out that VB implicitly adds the default namespace specified in the project properties to any namespace declarations in code. Freaky, that — I’m too used to explicit declarations. Now, I don’t know if that’s the problem you ran into, but I have verified that once you get the namespace using statement correct, the extension methods do, in fact, attach to the proper types.

  15. Randolpho, yes that was the problem, and I guess I was too quick to write it off (I was already frustrated at the ByRef problem).

    Incidentally, here’s a new thing: If I have used ByRef in the VB Extension method, I still can’t use it from C#, because I get an error message saying “Argument one must be passed with the “ref” keyword”. And since I am calling this as an extension method, I can’t qualify the parameter :)

    I think, it’s never meant to be ByRef, and it’s a VB flaw that allows it to be ByRef.

    Cheers.

  16. “I think, it’s never meant to be ByRef, and it’s a VB flaw that allows it to be ByRef”

    Typical of a C# guy to think it’s a flaw in VB. Why can’t it be a flaw in C#? Which it is! C# programmers make mistakes too, even if they don’t think so.

    Having learned many languages over my career, I always find the arrogance of C# guys funny.

  17. Principle of Least Surprise. The VB automatic ByRef semantics can be a nightmare. I pass in my value for x and suddenly x is a totally different object reference. I didn’t specify ‘ref’, it just automagically happened.

    Likewise with x.SomeExtMethod() causing x to be a pointer/reference to totally different object is horrible for code clarity and solubility.

    Magic pointers are bad and lead to instability and surprises in code. I’m not saying VB is bad, but I *AM* saying that magic pointers are bad. This problem existed in C/C++ and it was bad there too.

    C# doesn’t have this bug for precisely the reasons I mentioned above.

  18. @Rick.. Well, I don’t want to say that I am totally a C# guy. I like it a lot better than VB. I have worked on VB at work.

    Incidentally, the reason I describe it as a flaw in VB is because of what I read on the VB Team Blog (http://blogs.msdn.com/vbteam/archive/2007/01/05/extension-methods-part-2.aspx). Here they talk about making a design change while implementing extension methods in VB to bring the behavior at a parity with what it is in C#.

    If there needs to be consistency in this approach, then allowing ByRef, which is something that is not possible to do in C# (even if you are using an extension method defined in a VB module), would break such a parity.

    It’s not just a language thing. Imagine (for argument’s sake) how an API developed in VB.Net that makes use of extension methods would break if consumed from C# because it used a ByRef parameter.

    There are differences in VB and C#, and most of them are style differences, but one like this doesn’t make sense at all. At their core, the languages are supposed to be the same, and it shouldn’t matter which one I develop in. But a difference like this can make it matter, right? (given my API example above).

    Cheers.

    @Chad… yes, I agree.

  19. I agree both languages should work the same and both be capable of the same thing. However the real world just doesn’t work that way. So while both languages are extremely close, there will always be some scenarios/features that will favor one over the other. This particular example is probably a bug that will be addressed in the future

    For me I prefer the readability and self documenting. If you have ever had to come back to something you wrote 10+ years ago and try to figure out what you did. You will greatly appreciate those features. Granted you can do a lot of that in C# too with a little extra effort, but it’s not as natural as in VB. VB reads more like English, while C# reads more like math to me. I use both, but I prefer VB for the vast majority of my projects.

  20. I am glad that you see it the same way Rick (the first part).

    I always liked Maths better than literature in High School, so I guess that’s why I like C# better :)

    Thanks for all your comments.

  21. @John, I didn’t realize that… thanks for pointing that out though… of course, I was being a bit melodramatic back there, but it does make it a little better :D

  22. This is an old article. I know this isn’t true because I have a few extension methods off of system.object.

  23. Well I found this site after running into the same problem. I am using a Matrix struct that is a part of the XNA framework in c#. I was porting over some C++ code that was using nested arrays to describe a matrix such as:

    a[0][0] = Matrix.m11

    Now, the Matrix struct is awesome and used in alot of places but the one thing that I can’t do with it is access the rows and columns by indexer like myMatrix[0][0]. I figured I could just make an extender like Matrix.SetValueByRowAndColumn(this Matrix m, int rowindex, int colindex, float value) or something but seeing that Matrix m is passed over byVal and not byRef, you can’t change any of the values!

    And I NEED to write it this way, I have nested loops that run through the rows and columns of my matrix (from the ported code) that would be very sloppy if I broke them out.

    So what was my simple solution? I just changed the “this” into a “ref” and now instead of an extender, I’ve got a static method that looks like:
    MyNamespace.MyClass.SetValueByRowAndColumn(ref myMatrix, (int)row, (int)col, (float)val);

    It’s not as pretty and completely defeats the purpose, but after reading through this page and all of the comments I was ready to shove my head in the oven. Figuring out that there was a simple fix made me ecstatic!

  24. I defense of the OP. I completely understand what he is trying to do. If you had ownership of the code for System.String, you wouldn’t build a method on that class to convert it to some random enum. That has nothing to do with the natural behaviour that should be encapsulated within that class. It’s not the responsibility of String to know about all the enums out there. But adding an extension to the enum itself is like encapsulating that behaviour within the type (in this case an enum) itself. It’s very natural. But making a string covert itself to an enum is wicked evil.

  25. Look Cosmo and others. You miss the point!
    Please read the thread before attempting to be “smart”.

    Do like Oboma – “When I open my mouth, I like to know what I’m talking about.”

  26. Seriously, I saw this post and I cannot believe it was never resolved.

    Here’s your solution:

    public static Enum FromString(this Enum theEnum, string fromString)
    {
    return (Enum)Enum.Parse(theEnum.GetType(), fromString);
    }

  27. Now the C# developers decide to take the high road about not using mutable objects? What ever happened to less is more? Come on admit it, you are just jealous that you can’t do this. :)

Comments are closed.