views:

344

answers:

3

I have a class Server which talks to a server connection for IRC. It holds a list of known Users, and creates them as necessary.

I have two problems involving the User class:

  1. Anyone can create an instance of a User. I only want the Server class to be able to do this.
  2. If a user (the thing User describes) changes his/her name (or other info, like joined channels), the Server class can change it itself. However, other classes can, too! I want to disallow other classes from touching this information (making it read-only to them).

How can I solve these two problems? In C++, it can be solved by using the friend keyword and making the ctor and setName (and such) private.

Is there a C# keyword which can allow a certain method be accessable by a specified class? This would solve my problem.

+5  A: 

The closest in the .NET world to friend is the internal visibility.

Note that if your two classes are in separate assemblies, you can use the InternalsVisibleTo attribute to allow one assembly visibility of the internals of the other.

Bevan
A: 

Redesigning your class hierarchy is probably a fair solution to this problem. Because it sounds to me like what you really need is a read-only User class when it exists outside the Server class.

I would probably do something like this:

// An abstract base class. This is what I'd use outside the 
// Server class. It's abstract, so it can't be instantiated
// on its own, and it only has getters for the properties. 
public abstract class User
{
   protected User()
   {
   }

   public string Name { get;}
   // Other get-only properties
}

public class ServerUser : User
{
   public ServerUser()
   {
   }

   public string Name { get; set;}
   // Other properties. 
}

Then have the Server class created ServerUser classes, user the Server class to change properties on the ServerUser classes (like changing username) but only expose User classes to the outside world.

Chris Holmes
+5  A: 

Honestly I find the friend access that originated from C++ to be symptomatic of bad design. You're better off fixing your design.

For a start, who really cares if someone creates a User? Does it really matter? I ask this because it seems that sometimes we programmers get caught up worrying about things that simply won't happen or, if they do, it doesn't matter.

If you really do care then do one of the following:

  • Make User an interface. Server can instantiate a private class that implements it; or
  • Make User an inner class of Server with no public constructors so only Server can instantiate it.

Visibility hacks (of which friends in C++ are one and package access in Java are both good examples) are simply asking for trouble and not a good idea.

cletus
I went with both methods you suggested. I created an interface IUser and a ServerUser inner class. (I also split Server into two classes so others can write their custom IRC clients.) Thanks for your answer!
strager