6

In Visual Basic, you can use a module as a place to store 'loose' code which can be methods and variables that are accessible from elsewhere in the application without having to first initialize something, and the variable states can be set or changed and will continue to keep that value throughout.

The closest I have found, is static methods in C# as part of a public class, however this has the drawback of variables which are not globally accessible, or internally settable/gettable if the variables are made static.

Take for example the following simple code in VB stored in a blank module.

Private iCount as Integer = 0

Public Sub Increment()
  iCount = iCount + 1
End Sub

Public CheckModulus() As Boolean
  If iCount % 6 == 0 Then
    Return True
  Else
    Return False
  End If
End Sub

Now, you have a class, and from that class, you can then call CheckModulus() as such

Public Class Fruits

   Public Static Function ExactBunches() As String
      If CheckModulus() Then
         Return "You have an exact amount of bunches"
      Else
         Return "You need more fruits to make a bunch"
      End If
   End Function

End Class

Now I realize with some hack and slash, that you could move iCount to 'settings', and reset it on application launch, etc, but please bear in mind this is a very simple example to illustrate the convenience of being able to have a set of global code. Where I have found this most useful in the past is when creating UserControls or custom classes. In addition, the intent is not to make everything globally accessable, but to have certain methods and variables globally accessable while others remain ONLY accessible from within the module. For example, while CheckModulus() and Increment() (global methods) both have access to modify and obtain the iCount value, iCount is not accessible globally, as would the way be with private defined methods in the module.

So the big pickle is this :

What is the functionally equivalent code type in C# to VB & VB.NET's module ?

Due to the complex nature of this simple question, I feel I should impose a boolean for a 'just in case there is no answer' answer as follows.

If, there is nothing functionally equivalent, then what sort of clever hack or workaround (aside from using settings, or external storage like the registry, database, files, etc), to make this happen or something VERY very close ?

Kraang Prime
  • 9,981
  • 10
  • 58
  • 124
  • 3
    You can use a [static class](https://msdn.microsoft.com/en-us/library/79b3xss3.aspx). – DavidG Jun 16 '15 at 14:28
  • 2
    The problem I am having with static classes is accessibility levels. – Kraang Prime Jun 16 '15 at 14:30
  • In what way are they a problem? – DavidG Jun 16 '15 at 14:30
  • A static class with static members. Although if you need a lot of stuff to be "global", then you should really think about your design a bit more. – Matt Burland Jun 16 '15 at 14:30
  • 2
    possible duplicate of [What would be considered a VB.NET module in C#?](http://stackoverflow.com/questions/5331695/what-would-be-considered-a-vb-net-module-in-c) – cbr Jun 16 '15 at 14:30
  • Not sure what you mean by "however this has the drawback of variables which are not globally accessible, or internally settable/gettable if the variables are made static." - if you create a public static class with public static fields/properties - these will be accessible. – PaulF Jun 16 '15 at 14:30
  • First, static variables are not pre-definable, or constant, especially in private context, what I mean is that I can not initialize the values of private static variables at run time, and have those values persist. – Kraang Prime Jun 16 '15 at 14:31
  • 2
    I'm confused now. What do you mean by "pre-definable"? Also, why do you want your variables to be constant!? – DavidG Jun 16 '15 at 14:33
  • @cubrr - Not a duplicate of that as I am looking for a different response that doesn't sway to the easy choice of `static` classes as mentioned above in my question, I have already had trouble (various limitations) in using static classes as the work-around. – Kraang Prime Jun 16 '15 at 14:35
  • @DavidG - really tough to explain, but will try. First off, the above code would not work in a static class as the value of iCount would not persist through 'static' method calls. Second, to understand this, you need a more complex example, so for example `private List MyObjects { get; set; }` will not work as a static variable since it can never be initialized using `MyObjects = new List();` – Kraang Prime Jun 16 '15 at 14:38
  • @SanuelJackson: It's not clear what "limitations" you think you have with a static class that you don't have with a module. Can you elaborate with an example of something you can do with a module that you can't do with a static class? Because the behavior of the module you have in your question can be exactly duplicated with a static class. – Matt Burland Jun 16 '15 at 14:38
  • 2
    @SanuelJackson You can initialise it, see my answer. – DavidG Jun 16 '15 at 14:39
  • 1
    Perhaps a singleton would be an idea? It does mean the object needs to initialize. But it will do so automatically if needed so you don't have to worry about it and you can set the value of your properties in the constructor. Make the set property private and no one else then the class itself would be able to (re)set it. – Nick Otten Jun 16 '15 at 14:41
  • @NickOtten - What is a singleton, as that sounds reasonable. Can it persist set data, can those values be changed after the ctor as well (other methods etc), and can the whole thing be locked so it's only visible inside a usercontrol to itself (global), but not, for example by calling UserControl. ? – Kraang Prime Jun 16 '15 at 14:49
  • PS -- Not sure who voted this down, but seriously, if this is an issue, could you please comment as to what in my question was so terrible to warrant a "i think this is shit" action. thanks ;) – Kraang Prime Jun 16 '15 at 14:50
  • 1
    @SanuelJackson: I didn't downvote, but if you hover over the down arrow, one of the suggested reason is "unclear". I suspect that is the reason as your question isn't the most clear as to what you are actually trying to achieve and you do appear to be moving the goal posts as you go along. Also, don't take down votes personally. – Matt Burland Jun 16 '15 at 14:56
  • @MattBurland - Thank you, I didn't realize that i could hover for notes. Regarding the scope of this, unless I presented thousands of examples (really who has time for that), there really was no other way for me to try and represent the issue at hand in a concise manner. I did make one assumption that I hoped the code itself would be overlooked as the solution is not a verbatim translation to C#, but more a contextual concept of the methodology in place. I truly wish I could compact more data and examples without bloating the hell out of this question. :S – Kraang Prime Jun 16 '15 at 15:03
  • To everyone, really appreciated the insight on this. It seems the solution is there is no direct replacement for a vb module in C#, however through specific adjustments to the scopes of a static class, you can come close to emulating the core functionality aside for inheritance directly to the root namespace... unless someone knows how to do that too ... o.0 – Kraang Prime Jun 16 '15 at 15:22
  • Times like this I wish I could accept multiple answers as both had their strengths in assisting towards a solution Both Dave's and Matt's solutions demonstrated different aspects of this loaded question. I really like the demonstration via fiddle in matts solution, as well as a short memory read loop to demonstrate async, however the conciseness of Dave's solution had me lean towards him. I have upvoted you both in any case :) – Kraang Prime Jun 17 '15 at 17:27
  • @Sanuel Jackson: I'm sorry for the late replay, I was out on a vacation. A example of a singleton can be found here: https://msdn.microsoft.com/en-us/library/ff650316.aspx . Basically its a static class that exists in your ram and can only construct itself. You can expose it as much as you like by making it (for example) sealed. You can also write your own setters and getters like you would with any class. And you could make those functions static so you can always use them. If you make them static check for instance == null though so you don't end up with a null pointer (see linked example) – Nick Otten Jun 23 '15 at 12:14

2 Answers2

10

You can use a static class. You can also initialise these using a static constructor.

public static class MyStuff
{
    //A property
    public static string SomeVariable { get; set; }

    public static List<string> SomeListOfStuff { get; set; }
    //Init your variables in here:
    static MyStuff()
    {
        SomeVariable = "blah";
        SomeListOfStuff = new List<string>();
    }

    public static async Task<string> DoAThing()
    {
        //Do your async stuff in here
    }

}

And access it like this:

MyStuff.SomeVariable = "hello";
MyStuff.SomeListOfStuff.Add("another item for the list");
DavidG
  • 113,891
  • 12
  • 217
  • 223
  • Just a note, I respect this answer, and I feel with all the information here combined, I am getting closer to at least a workaround. For example, using the above in an internal scope would work, however there is still the problem of losing other functionality such as `async` methods since they must be static if in a static scope, but they can not be because C# doesn't support `static async` or even reverse it `async static`, as one case that poses a problem. – Kraang Prime Jun 16 '15 at 15:00
  • 2
    What makes you think static methods can't be async? I've added an example. – DavidG Jun 16 '15 at 15:05
  • this is really strange XD .... when trying to do async in a static class today, it is actually working. It did remain black and with the standard class or method `async` doesn't exist, want to create it lol.... then it just went away after dropping the async verb on the form (test class is in the same file). Will have to see as I know this has given me compile issues in the past, but not gonna complain if it does work. Past failed compiles on attempts to do this are the reason I believed this. – Kraang Prime Jun 16 '15 at 15:12
7

A static class like this would be equivalent to your VB code:

public static class MyModule
{
    private static int iCount = 0;   // this is private, so not accessible outside this class

    public static void Increment()
    {
        iCount++;
    }

    public static bool CheckModulus()
    {
        return iCount % 6 == 0;
    }

    // this part in response to the question about async methods
    // not part of the original module
    public async static Task<int> GetIntAsync()
    {
        using (var ms = new MemoryStream(Encoding.ASCII.GetBytes("foo"))) 
        {
            var buffer = new byte[10];
            var count = await ms.ReadAsync(buffer, 0, 3);
            return count;
        }
    }
}

You would then call it like this (and the value of iCount does persist because it's static):

    // iCount starts at 0
    Console.WriteLine(MyModule.CheckModulus());   // true because 0 % 6 == 0
    MyModule.Increment();                         // iCount == 1
    Console.WriteLine(MyModule.CheckModulus());   // false
    MyModule.Increment();                         // 2
    MyModule.Increment();                         // 3
    MyModule.Increment();                         // 4
    MyModule.Increment();                         // 5
    MyModule.Increment();                         // 6
    Console.WriteLine(MyModule.CheckModulus());   // true because 6 % 6 == 0
    Console.WriteLine(MyModule.GetIntAsync().Result);   // 3

A fiddle - updated with an async static method

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
  • How can the scope be narrowed to be accessible to only a particular set of calling classes and UserControls ? For example, I do not want this accessible from Form1, but I would like it accessible from within `UserControl` – Kraang Prime Jun 16 '15 at 14:41
  • Note that `Static` classes are *not* equivalent to Modules in VB. There are the closest thing to them however. – Matt Wilko Jun 16 '15 at 14:49
  • @MattWilko: Want to explain *why*? – Patrick Hofman Jun 16 '15 at 14:50
  • VB.NET adds methods in a Module to the global (unnamed) namespace so you don't have to prefix the (module) name to use public methods, fields in it – Matt Wilko Jun 16 '15 at 14:52
  • 1
    @SanuelJackson: You wanted it to be global, but now you want it restricted? You can restrict it some by careful positioning of your static class in relation to the classes intended to access it. For example, if it was `internal` in an assembly with your UserControls then it wouldn't be accessible outside. – Matt Burland Jun 16 '15 at 14:52
  • I gave "that" vb module as a very simplistic example to demonstrate one possibility of the dilemma. I do appreciate the re-write, however I know that one could be re-written as is in C# in many different ways. My real issue is getting past the sight of what that code does, and more what it represents. For example, there is no such thing as `private async static` . But there is `private async` .... as you know, I can't call just `private async` if within a `static` scope. – Kraang Prime Jun 16 '15 at 14:53
  • @MattWilko: That's an extremely minor point (and not necessarily a good thing either IMHO). So you have to preface a class to a method in a static class with the name of the class. I'll give you that much. – Matt Burland Jun 16 '15 at 14:54
  • 2
    A point nevertheless and I didn't say it was a good thing :-) – Matt Wilko Jun 16 '15 at 14:59
  • 1
    @SanuelJackson: Not sure where you get that idea from. See this updated [fiddle](https://dotnetfiddle.net/yeaT5r). I've added an `async static` method and it compiles just fine. Although I would again suggest you really rethink your design if you need this many static classes and static methods. – Matt Burland Jun 16 '15 at 15:07
  • Just noticing that in my compiler now as well. This is quite strange as my past attempts to do static async have resulted in failed compiles, and (as you can see in fiddler) the async keyword being black. I like both of your answers, and very much appreciate all of the help from everyone here. I will need some time to contemplate who to award to, and will have to be satisfied with this combined effort as the closest possibility there is in c# to a vb module. :) – Kraang Prime Jun 16 '15 at 15:18
  • I think the icing on the cake, would be if either you, or David (or someone else even), were able to supply how this combined effort could be somehow adjusted to work off the root namespace, but this is unnecessary. The key was to emulate as much of what a module does as possible in c#. :) – Kraang Prime Jun 16 '15 at 15:24