Results 1 to 17 of 17

Thread: Where to put general procedures in C#

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2010
    Posts
    791

    Where to put general procedures in C#

    I have some C# procedures that are needed in several forms in the project.
    So I cannot put them in the code of a specific form.
    Where do I put them?

    In VB6, I could easily add these procedures in a bas module.
    But, what is the equivalent of that in C#?
    And how do I add it to the project?
    And where (in what file) do I save it?

    Also, what if there are some procedures that are so generic that all projects may need to call them?
    Where do I put those ones?

    Please advise.
    Thanks.

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,603

    Re: Where to put general procedures in C#

    Basically everything in .NET is a class. Forms are classes, just like everything else. Just create one or more classes and put your methods there. You already use classes like that from the framework, e.g. the System.IO.File class for operations relating to files. If it makes sense to do so, you can declare you class and its members static and then you can use it without having to create an instance, exactly as you do with the System.IO.File and various other classes. For the record, VB.NET has modules that are implemented to work in basically the same way that modules do in VB6 but they compile to the same things as C# static classes.

  3. #3
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,887

    Re: Where to put general procedures in C#

    For example, let's assume in your VB6 application you had a module named Utilities that had a slugify method in it that turned plain text values into slugs. That might look something like this:
    Code:
    Module Utilities
        Function Slugify(ByVal strInput As String) As String
            Dim strSlug As String
            Dim i As Integer
            Dim chrCurrent As String
    
            strSlug = LCase$(strInput)
    
            For i = 1 To Len(strSlug)
                chrCurrent = Mid$(strSlug, i, 1)
    
                If (chrCurrent >= "a" And chrCurrent <= "z") Or (chrCurrent >= "0" And chrCurrent <= "9") Then
                    strSlug = strSlug & chrCurrent
                ElseIf chrCurrent = " " Then
                    strSlug = strSlug & "-"
                End If
            Next i
    
            Slugify = strSlug
        End Function
    End Module
    Now whenever you needed to reference the code, you'd execute the following:
    Code:
    Dim slug As String
    slug = Slugify("Hello World")
    The C# equivalent would be to create a class and make your method static which allows you to reference the member by using the class name itself:
    Code:
    public partial class Utilities
    {
        [GeneratedRegex(@"[^a-z0-9\s-]")]
        private static partial Regex RegexSlugifyMatchNonValidCharacters();
    
        [GeneratedRegex(@"\s+")]
        private static partial Regex RegexSlufigyMatchDuplicateSpaces();
    
        [GeneratedRegex(@"\s")]
        private static partial Regex RegexSlugifyMatchSingleSpaces();
    
        [GeneratedRegex(@"-+")]
        private static partial Regex RegexSlugifyMatchDuplicateHyphens();
    
        public static string Slugify(string text)
        {
            var slug = text.ToLowerInvariant();
            slug = RegexSlugifyMatchNonValidCharacters().Replace(slug, "");
            slug = RegexSlufigyMatchDuplicateSpaces().Replace(slug, " ").Trim();
            slug = RegexSlugifyMatchSingleSpaces().Replace(slug, "-");
            slug = RegexSlugifyMatchDuplicateHyphens().Replace(slug, "-");
            slug = slug.Trim('-');
    
            return slug;
        }
    
    }

    Now whenever you needed to reference the code, it'd look like this:
    Code:
    var slug = Utilities.Slugify("Hello World");
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  4. #4
    Fanatic Member BenJones's Avatar
    Join Date
    Mar 2010
    Location
    Wales UK
    Posts
    694

    Re: Where to put general procedures in C#

    I think jmcilhinney and dday9 have give good usfull answers but I thought I share a link for you that may also help while moving from VB6 to c# hope it may have you

    https://www.vbmigration.com/white-pa...ation-partner/

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2010
    Posts
    791

    Re: Where to put general procedures in C#

    Quote Originally Posted by jmcilhinney View Post
    Basically everything in .NET is a class. Forms are classes, just like everything else. Just create one or more classes and put your methods there. You already use classes like that from the framework, e.g. the System.IO.File class for operations relating to files. If it makes sense to do so, you can declare you class and its members static and then you can use it without having to create an instance, exactly as you do with the System.IO.File and various other classes. For the record, VB.NET has modules that are implemented to work in basically the same way that modules do in VB6 but they compile to the same things as C# static classes.
    Thanks for your help.

    I just tried to add a class to my solution/project.
    It shows me this dialogue:
    https://i.imgur.com/jiMyHaS.jpeg

    It doesn't give me any option to save the new class in any location that I wish.
    So, I have no other choice but to click "Add". After I click "Add", it adds the class and creates the corresponding file under the project (not even the solution)

    I need to create the file under a totally separate folder.
    I need to have a folder named D:\Dev\VCS\Common so that these kinds of common class modules would be stored in there so that all my solution/projects would access them.
    In other words these classes must be common components of all my solution/projects.

    How can I do that?

    Also, if you look at that same dialogue again, it doesn't give me the option to choose an EXISTING class either.
    It only lets me add a NEW class.
    Please note that in VB6 when you add a bas module, the dialogue box in VB6 lts you add either an existing or a new bas module.
    But, in C#, the dialogue box doesn't give you that option.

    Lets say I add a common class and define some common methods in it and use them in a solution/project.
    Then later, I will be developing another solution/project and that new solution/project will also need to access those same common routines.
    So, how can I add that EXISTING class to the new solution/project?

    Please help.
    Thanks.

  6. #6
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,887

    Re: Where to put general procedures in C#

    You could simply create the file outside of Visual Studio, open it inside of Visual Studio to edit, and then when you wanted to add it to your project you would use the Add Existing Item option.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  7. #7
    PowerPoster PlausiblyDamp's Avatar
    Join Date
    Dec 2016
    Location
    Pontypool, Wales
    Posts
    2,624

    Re: Where to put general procedures in C#

    Quote Originally Posted by IliaPreston View Post
    Thanks for your help.

    I just tried to add a class to my solution/project.
    It shows me this dialogue:
    https://i.imgur.com/jiMyHaS.jpeg

    It doesn't give me any option to save the new class in any location that I wish.
    Normally I would right click on the relevant folder in solution explorer, select new, and theat way the item is created in the correct location.

    Quote Originally Posted by IliaPreston View Post
    So, I have no other choice but to click "Add". After I click "Add", it adds the class and creates the corresponding file under the project (not even the solution)
    Classes belong to a project, not a solution - you can't compile a solution.

    Quote Originally Posted by IliaPreston View Post
    Also, if you look at that same dialogue again, it doesn't give me the option to choose an EXISTING class either.
    It only lets me add a NEW class.
    If you right-click on your project (or any folder in your your project) you can select Add -> Existing Item, and then navigate to the file in question. If you click on the drop down next to the "Add" button then you can add the file as a link rather than copying it to the current project.

    Recent versions of Visual Studio also have Shared Projects https://learn.microsoft.com/en-us/pr...s?tabs=windows which might be easier than a folder containing lots of individual source files. Create a shared project containing all of these files, then reference the shared project from your other projects.
    Last edited by PlausiblyDamp; Jul 8th, 2024 at 12:25 PM.

  8. #8
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,603

    Re: Where to put general procedures in C#

    Quote Originally Posted by IliaPreston View Post
    It doesn't give me any option to save the new class in any location that I wish.
    The new item will be added in the location that was selected when you opened the dialogue. If you want to add a new item in a folder, right-click that folder and select the menu option to add a new item. When you click the Add button, the item will be added to that folder. If you have just selected a project then the item will be added to the root folder of that project.
    Quote Originally Posted by IliaPreston View Post
    After I click "Add", it adds the class and creates the corresponding file under the project (not even the solution)
    It would help if you knew how these things work and fit together. Adding a class file to the solution would be possible (I think) but not useful. A class has to be declared in an assembly to be of use and an assembly is generated by building a project. If you want classes that can be used in various projects then create a Class Library project and add the new class to that. That project will then build to a DLL that can be referenced by other EXEs or DLLs. In the same solution, one project can reference another and then they will be built together and can be debugged together. Once your library has been built, other projects can reference it directly or you can create a NuGet package and that can be installed in other projects.

  9. #9

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2010
    Posts
    791

    Re: Where to put general procedures in C#

    Quote Originally Posted by dday9 View Post
    You could simply create the file outside of Visual Studio, open it inside of Visual Studio to edit, and then when you wanted to add it to your project you would use the Add Existing Item option.
    Thanks for your help.

    I am trying to test what you are saying.
    Before even posting my initial post, I had already tried to add a new class (Main menu -> Project -> Add class) which I already explained in post #5.
    And this is the class that I had added at that time:
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Test002SqLite
    {
        public static class CommonUtilities
        {
            public static int AddFiveToInt(int Num)
            {
                Num += 5;
                return Num;
            }
        }
    }
    Please note that the name of my project (as well as the solution) are both Test002SqLite
    And, that same name appears in the above class as the namespace.
    The above class is obviously part of the project named Test002SqLite, so, if the namespace in the above class is Test002SqLite, it should be ok (or that is what I guess)

    Now, if I were to test the thing that you are saying, I should open Windows Explorer and go to the different folder where I want to create my class, create a new text file and put some code in it similar to the above and save it as for example CommonClass.cs
    And then in Visual studio I should add that file to my project.

    But, the problem is that I don't think it is right to declare the namespace as Test002SqLite because I need this new class to be part of all my projects in all my solutions.
    So, what namespace name should I give it?

    Also, if I create the class outside of Visual Studio, and then in Visual Studio I add it to many project (under many solutions) would that be ok?

    Please advise.
    Thanks.

  10. #10
    PowerPoster PlausiblyDamp's Avatar
    Join Date
    Dec 2016
    Location
    Pontypool, Wales
    Posts
    2,624

    Re: Where to put general procedures in C#

    A namespace is only a logical grouping for your code, it doesn't affect anything other than how you refer to things. If you want to share a class between multiple projects then just give it a namespace that reflects this e.g.

    Code:
    namespace Common {
    
    }
    the only difference is that when referring to this class in one of your projects you would need to either fully qualify the class name with the namespace, or put a using statement at the top of each code file for that namespace.

  11. #11
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,603

    Re: Where to put general procedures in C#

    Quote Originally Posted by IliaPreston View Post
    I need this new class to be part of all my projects in all my solutions.
    No, you don't. Any class is part of one project in one solution. What you need is for that class to be AVAILABLE TO all your projects in all your solutions. To that end, you should be creating a new solution with a new Class Library project. That project will generate a DLL when built and you can then reference that DLL in any other project that needs to access the types defined in it. How do you think all your projects can access all the types defined as part of .NET? The entire framework is comprised of DLLs that your projects reference as required.

    Even better, you can create a NuGet package from the compiled DLL and host it on your development machine. You can then install that package in other projects just like you do first-party and third-party NuGet packages to access the types they contain. NuGet packages are a good way to keep track of library versions and to updated projects with new versions of libraries as they become available.

    With regards to namespaces, here's what I recommend. Come up with a "company name" for yourself and prefix everything you do with that. When I was self-employed, my business name was Wunnell Development (my middle name is Philip with one L) and so all my solutions and projects are prefixed with that. Each solution should correspond to a product and then each project should correspond to a component of that product. If I was creating a web site for myself then I might name a solution Wunnell.WebSite and then that might contain projects including Wunnell.WebSite.Model and Wunnell.WebSite.Web. If you're working for a client rather than yourself then you can insert the client name. For instance, I currently work at Spatial Intelligence and we are doing a project for Great Barrier Reef Marine Park Authority called Eye on the Reef. We have a solution named SI.Gbrmpa.Eotr and it contains projects like SI.Gbrmpa.Eotr.Model, SI.Gbrmpa.Eotr.Service, SI.Gbrmpa.Eotr.Service.Interface, SI.Gbrmpa.Eotr.Web and SI.Gbrmpa.Eotr.Web.Test. We also have an internal solution named SI.FileFormats that builds a DLL and creates a NuGet package that we have installed in the Web project of that solution and provides functionality to import and export various data file formats in various of our products.

  12. #12

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2010
    Posts
    791

    Re: Where to put general procedures in C#

    Quote Originally Posted by PlausiblyDamp View Post
    A namespace is only a logical grouping for your code, it doesn't affect anything other than how you refer to things. If you want to share a class between multiple projects then just give it a namespace that reflects this e.g.

    Code:
    namespace Common {
    
    }
    the only difference is that when referring to this class in one of your projects you would need to either fully qualify the class name with the namespace, or put a using statement at the top of each code file for that namespace.
    Thanks for your help.

    I am experimenting with your suggestion.
    I have created a new solution/project which is .Net Core and added a new class as follows:
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Common001Test
    {
        public static class Comm001Test
        {
            public static int AddSixToInt(int Num)
            {
                Num += 6;
                return Num;
            }
    
        }
    }
    I have given different names to the class and the namespace as you can see in the above code. (There is a tiny difference).
    The file name is Comm001Test.
    I don't know why I gave them different names.
    Maybe that was not good.
    Maybe I should have given them the same name.
    But, that is beside the point.

    Also, in the same project I have a form. Actually I didn't add that form. It was added to the project when I created the project.

    I added a button to the form.

    You said:
    you would need to either fully qualify the class name with the namespace, or put a using statement at the top of each code file for that namespace
    If I fully qualify the method name like this (let's call this Code 1):
    Code:
    namespace Common001Test
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void btnTest001_Click(object sender, EventArgs e)
            {
                int N = 10;
                int Res;
    
                Res = Comm001Test.AddSixToInt(N);
                txtDetails.Text = "" + Res;
    
            }
        }
    }
    it works.
    That is classname.methodname

    But, if I qualify the method name like this (let's call this Code 2):
    Code:
            private void btnTest001_Click(object sender, EventArgs e)
            {
                int N = 10;
                int Res;
    
                Res = Common001Test.AddSixToInt(N);
                txtDetails.Text = "" + Res;
            }
    it does not work.
    That is namespace.methodname
    Error CS0234 The type or namespace name 'AddSixToInt' does not exist in the namespace 'Common001Test' (are you missing an assembly reference?) Common001Test D:\Dev\VCS\Tests\Common001Test\Common001Test\Common001Test\Form1.cs 16 Active
    I thought this should work.
    Why doesn't it work?

    Now, instead of qualifying the method name, I try to add a using statement on the top of the code file (let's call this Code 3):
    Code:
    using Common001Test;
    
    namespace Common001Test
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void btnTest001_Click(object sender, EventArgs e)
            {
                int N = 10;
                int Res;
    
                Res = AddSixToInt(N);
                txtDetails.Text = "" + Res;
            }
        }
    }
    it doesn't work:
    Error CS0103 The name 'AddSixToInt' does not exist in the current context Common001Test D:\Dev\VCS\Tests\Common001Test\Common001Test\Common001Test\Form1.cs 17 Active
    Also, this one (let's call this Code 4):
    Code:
    using Comm001Test;
    
    namespace Common001Test
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void btnTest001_Click(object sender, EventArgs e)
            {
                int N = 10;
                int Res;
    
                Res = AddSixToInt(N);
                txtDetails.Text = "" + Res;
            }
        }
    }
    doesn't work:
    Error CS0246 The type or namespace name 'Comm001Test' could not be found (are you missing a using directive or an assembly reference?) Common001Test D:\Dev\VCS\Tests\Common001Test\Common001Test\Common001Test\Form1.cs 1 Active
    Error CS0103 The name 'AddSixToInt' does not exist in the current context Common001Test D:\Dev\VCS\Tests\Common001Test\Common001Test\Common001Test\Form1.cs 17 Active

    Please note that this entire thing is within one same solution/project.
    After I fix this bug, I will use that method "AddSixToInt" in other projects, but at this moment I haven't reached that stage. At this moment I am just trying to get it to work within one same project.

    Why doesn't code 2 (above) work?
    Why doesn't code 3 (above) work?
    Why doesn't code 4 (above) work?

    Please advise.
    Thanks again.

  13. #13
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,603

    Re: Where to put general procedures in C#

    Quote Originally Posted by IliaPreston View Post
    Why doesn't code 2 (above) work?
    Because that's not legal C# syntax. In C#, any class member has to be qualified by a reference to an instance of that class for instance methods or by the class name for static methods. You seem to be under the impression that it should work like VB, where module members can but don't need to be qualified with the module name. That is not the case. You ALWAYS need to type name to qualify a static method (unless the code is within the type itself, in which case there is an implicit this qualifier). You also seem not to understand what the "fully" in "fully-qualified" means. It means including the full namespace, so fully qualifying that method would mean using Common001Test.Comm001Test.AddSixToInt.

  14. #14
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,621

    Re: Where to put general procedures in C#

    To add to that, you can import (Using) namespace... but not classes.... so. "using Comm001Test;" doesn't work because that's a class... not a namespace. "using Common001Test;" does work because it's a namespace... BUT, as jmc noted, you STILL need to use the class name to for the method. If you think about it, it makes sense... what if you had this:

    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Common001Test
    {
        public static class Comm001Test
        {
            public static int AddSixToInt(int Num)
            {
                Num += 6;
                return Num;
            }
    
        }
        public static class Comm002Test
        {
            public static int AddSixToInt(int Num)
            {
                Num += 6;
                return Num;
            }
    
        }
    }
    If you were to simply call "AddSixToInt" ... how would it know which one you wanted? It doesn't. So you need to specify which one you want.


    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  15. #15

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2010
    Posts
    791

    Re: Where to put general procedures in C#

    Quote Originally Posted by jmcilhinney View Post
    Because that's not legal C# syntax. In C#, any class member has to be qualified by a reference to an instance of that class for instance methods or by the class name for static methods. You seem to be under the impression that it should work like VB, where module members can but don't need to be qualified with the module name. That is not the case. You ALWAYS need to type name to qualify a static method (unless the code is within the type itself, in which case there is an implicit this qualifier). You also seem not to understand what the "fully" in "fully-qualified" means. It means including the full namespace, so fully qualifying that method would mean using Common001Test.Comm001Test.AddSixToInt.
    Thanks a lot for your help.
    You said:
    You ALWAYS need to type name to qualify a static method ...
    I am not trying to challenge what you are saying, but PlausiblyDamp told me that I can omit qualifying the method name with the class name if I use the using statement in the beginning of the file:
    PlausiblyDamp: when referring to this class in one of your projects you would need to either fully qualify the class name with the namespace, or put a using statement at the top of each code file for that namespace
    Is what PlausiblyDamp said in the above quote wrong?
    I am not trying to blame PlausiblyDamp (in case his statement was wrong).
    I am just trying to understand this.

    How can you and PlausiblyDamp both be correct?
    I am a bit confused.


    You are also saying:
    You also seem not to understand what the "fully" in "fully-qualified" means. It means including the full namespace, so fully qualifying that method would mean using Common001Test.Comm001Test.AddSixToInt.
    If that is the case then why does my Code #1 in Post #12 (copied below) work?
    Code:
    namespace Common001Test
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void btnTest001_Click(object sender, EventArgs e)
            {
                int N = 10;
                int Res;
    
                Res = Comm001Test.AddSixToInt(N);
                txtDetails.Text = "" + Res;
            }
        }
    }
    The above code works perfectly.
    According to your suggestion it shouldn't work.

    Please help.
    Thanks again
    Ilia

  16. #16
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,603

    Re: Where to put general procedures in C#

    Quote Originally Posted by IliaPreston View Post
    The above code works perfectly.
    According to your suggestion it shouldn't work.
    No, I didn't say that it shouldn't work. There's generally no need to fully-qualify anything because you normally import the namespace, either at the file or project level. It's generally more desirable to do that because it makes code more readable. You would generally only full-qualify a name if there was a class of types from two different imported namespaces. The whole point of the full qualification is to disambiguate the name. If there's no ambiguity, there's no need or reason to fully qualify.

    I should note that, in this case, you're not actually importing the namespace because you're actually inside the namespace. The form you're writing the code in and the class you're accessing are both in the same namespace, so the compiler doesn't require any further qualification. The current namespace is effectively imported by default.

  17. #17
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,603

    Re: Where to put general procedures in C#

    Quote Originally Posted by IliaPreston View Post
    Is what PlausiblyDamp said in the above quote wrong?
    We were both a little bit wrong, actually. You have always been able to import a type name in VB with Imports, which is probably why PD thought it was valid here. C# originally only let you import namespaces and not types. I'm not sure which language version introduced the change but you can now import a type in C# with using static rather than just using. I would generally recommend against doing so though. I'd only do that if you're using one particular type a lot in that particular file and it's clear what all the unqualified member references are. If you start doing it willy nilly, you'll make your code harder to read.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width