Сделать методы / свойства видимыми для одного класса, скрытыми для других

у меня есть класс Server который разговаривает с подключением сервера для IRC. Он содержит список известных UserS, и создает их по мере необходимости.

у меня есть две проблемы с участием User класс:

  1. любой может создать экземпляр User. Я хочу только Server класс, чтобы иметь возможность сделать это.
  2. если пользователь (дело User описывает) изменяет свое имя (или другую информацию, например, присоединенные каналы),Server класс может изменить его себя. Однако другие классы тоже могут! Я хочу запретить другим классам касаться этой информации (делая ее доступной только для чтения).

как я могу решить эти две проблемы? В C++ это можно решить с помощью friend ключевое слово и создание ctor и setName (и подобные) частная.

есть ли ключевое слово C#, которое может разрешить доступ к определенному методу указанным классом? Это решило бы мою проблему.

3 ответов


честно говоря, я найти friend доступ, который возник из C++, чтобы быть симптомом плохого дизайна. Тебе лучше починить свой дизайн.

для начала, кого действительно волнует, если кто-то создает пользователя? Разве это имеет значение? Я спрашиваю об этом, потому что иногда мы, программисты, начинаем беспокоиться о том, чего просто не произойдет, а если и произойдет, то это не имеет значения.

Если вы действительно заботитесь затем выполните одно из следующих действий:

  • сделать Пользовательский интерфейс. Сервер может создать экземпляр частного класса, который его реализует; или
  • сделайте пользователя внутренним классом сервера без открытых конструкторов, чтобы только сервер мог создать его экземпляр.

видимость хаки (из которых друзья в C++ являются одним, а доступ к пакетам в Java-оба хороших примера) просто просят неприятностей, а не хорошей идеи.


самый близкий в мире .NET к friend - Это internal видимости.

обратите внимание, что если ваши два класса находятся в отдельных сборках, вы можете использовать InternalsVisibleTo атрибут для обеспечения видимости одной сборки внутренних элементов другой.


перепроектирование иерархии классов, вероятно, является справедливым решением этой проблемы. Потому что мне кажется, что вам действительно нужен пользовательский класс только для чтения, когда он существует вне серверного класса.

Я, вероятно, сделал бы что-то вроде этого:

// 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. 
}

затем класс сервера создал классы ServerUser, пользователь-класс сервера для изменения свойств классов ServerUser (например, изменение имени пользователя), но только предоставляет классы пользователей внешнему миру.