3

I have an implementation of the Shunting-Yard algorithm that I am trying to integrate clearly into our framework. Currently I have it all packed into a class with a simple public interface.

namespace MathematicalParser {
  public class ExpressionParser {
    public ExpressionParser(string expression, List<string> variables);
    public double GetNumericValue(Dictionary<string,double> variableValues);
  }
}

Inside this class there are a lot of helper classes, helper enums, static variables etc to map different names to functions. All these are private so that is no concern to the user of the library.

In an effort to improve maintainability of the code I'm trying to separate code that is logically unrelated into their own classes, these classes do however not have any meaning outside of the ExpressionParser so I'd like to limit their visibility to the namespace MathematicalParser (which only contains the ExpressionParser).

How do you best accomplish this in c#, the internal keyword only works on assemblies and private can't be used in namespaces.

lyml
  • 95
  • 1
  • 4
  • 3
    What's wrong with `internal`? Is your assembly so huge that you can't trust other developers not to try and use them? The whole point of namespacing is that you group types together, so there should be no confusion about the purpose of your helper classes. – Joe Jul 18 '12 at 11:40
  • @Joe Trust and trust, I'd rather not expose them to unneeded classes when they try to use the ExpressionParser. As I have written it right now the public interface is great and all the infrastructure is hidden inside the class. I simply wish to split the code into logically coherent maintainable chunks without changing the interface. – lyml Jul 18 '12 at 13:07
  • In which case I've posted an answer that might be of use, the only thing I can think of. – Joe Jul 18 '12 at 13:21
  • possible duplicate of [Namespace only class visibility in C#/.NET?](http://stackoverflow.com/questions/1223873/namespace-only-class-visibility-in-c-net) – nawfal Feb 25 '13 at 10:34

3 Answers3

1

Have you tried using private nested classes?
Take a look in here: Private inner classes in C# - why aren't they used more often?

Community
  • 1
  • 1
ioreskovic
  • 5,531
  • 5
  • 39
  • 70
  • I might be misunderstanding you but I believe that's the way it is written now. I wish to maintain the functionality of private inner classes (i.e. non public infrastructure code) while splitting up the code into maintainable chunks. Some of these classes are quite big and might themselves need updates if there is bug in the implementation. – lyml Jul 18 '12 at 13:09
  • Ah, I see. You want to declare and use a private class that is a separate compilation unit? – ioreskovic Jul 18 '12 at 13:30
1

If you're really desperate to do this (in the light of my comment on the original question), you could put all the helper classes into a single assembly and make them internal, so they are effectively closed off from use. Then make a second assembly, the one you let people use, and put the 'public' classes and methods in a second assembly. Then use InternalsVisibleTo to allow your 'public' assembly use the other 'private' assembly's helper classes and methods.

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

This does mean that you have to force people using your library to work in a different assembly to the one containing your 'public' library code. I think from your question you're saying that they are working in the same assembly, in which case you'd have to separate the 'public' library out into a different assembly. And if you did do this, then simply making the methods internal and putting them in the same assembly would do the job after all.

If you go the two-assembly route and if your colleagues are working on the same assembly, at least there's the extra 'step' in referencing another assembly that might prevent them from using it.

And if that isn't enough ... I don't know, write a WCF webservice and work through that*.

*that was satire

Joe
  • 46,419
  • 33
  • 155
  • 245
1

I wouldn't do this (same opinion as Joe), but here's another solution derived from Lopina's answer: nested classes + partial classes.

PublicClass.cs:

namespace MyNamespace
{
    public partial class PublicClass
    {
        public int ReturnSomeStuff()
        {
            MyHelperClass1 tmp = new MyHelperClass1();
            MyHelperClass2 tmp2 = new MyHelperClass2();

            return tmp.GetValue1() + tmp2.GetValue2();
        }
    }
}

PrivateClass1.cs:

namespace MyNamespace
{
    public partial class PublicClass
    {
        private class MyHelperClass1
        {
            public int GetValue1()
            {
                return 5;
            }
        }
    }
}

PrivateClass2.cs:

namespace MyNamespace
{
    public partial class PublicClass
    {
        private class MyHelperClass2
        {
            public int GetValue2()
            {
                return 10;
            }
        }
    }
}

Program.cs:

public class Program
{
    private static void Main(string[] args)
    {
        PublicClass tmp = new PublicClass();

        MyHelperClass2 zz;  // Can't access MyHelperClass2 here cause it's private

        Console.WriteLine(tmp.ReturnSomeStuff());
        Console.ReadLine();
    }
}

As you can see, your different helper classes are physically separated in different files (maybe it'll help you maintain your code). And you can't access them directly, they are private to the PublicClass.

ken2k
  • 48,145
  • 10
  • 116
  • 176
  • This was a very useful answer. It allows me to split up the code and access the static variables defined by my parser from each logical unit without polluting the namespace. – lyml Jul 18 '12 at 15:44