Реализация функциональности друга (доступно в C ++) в C # - PullRequest
2 голосов
/ 05 марта 2009

Хорошо, давайте оставим дискуссию о том, ломает ли дружба инкапсуляцию, и на самом деле попробуем элегантно придумать последовательный дизайн. Это двойная функция:

1) Общий вопрос о том, как реализовать:

  public class A 
   {
      friend class B;
   }


2) Зачем мне эта функциональность? Некоторые из моих классов реализуют интерфейс ISerializable. Однако я хочу сделать методы ISerializable защищенными в классе Derived, чтобы не показывать их клиенту (а также в документации). Однако внутренние классы должны иметь доступ к ним. Каков общий способ решения этой проблемы в C #?

Примечание: я использую дружбу, как определено в текущем стандарте C ++.

Спасибо

Ответы [ 5 ]

4 голосов
/ 05 марта 2009

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

4 голосов
/ 05 марта 2009

C # имеет ключевое слово internal, поэтому другие типы в той же сборке видят типы, помеченные как внутренние. Кроме того, вы можете добавить атрибуты в сборку, чтобы типы вне сборки могли видеть внутренние элементы этой сборки.

1 голос
/ 05 марта 2009

Оставляя InternalsVisibleTo материал в стороне, у вас есть только два варианта реализации интерфейсов:

  • Реализуйте их публичными методами
  • Реализуйте их, используя явную реализацию интерфейса

В обоих случаях любой может вызвать методы, но используя явную реализацию интерфейса, вы можете вызывать методы только через выражение интерфейса (например, вы можете преобразовать переменную фактического типа в ISerializable).

Нет такого понятия, как «внутренняя» реализация интерфейса.

0 голосов
/ 29 ноября 2013

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

Решение 1: класс друга-одиночка

public class A
{
  private underwear myUnderwear;

  public ChangeUnderwear(B friend, underwear newUnderwear) 
  {
    if (friend == null) return;
    myUnderwear = newUnderwear
  }
}

public sealed class B
{
  private B() {};
  private B inst;
  private MessWithA(A a)
  {
    a.ChangeUnderwear(this, new Thong());
  }
}

Кто-нибудь там видит какой-нибудь недостаток? Этот метод будет работать, если у вас есть класс Foo и синглтон FooManager.

Решение 2: Если друг не одиночка, я думаю, вы могли бы использовать ту же идею, скрывая конструкцию и скрывая все экземпляры:

interface IB
{ ... }

public sealed class B : IB
{
  private B() {};
  public IB CreateB()
  {
    return (IB)new B();
  }
  private MessWithA(A a)
  {
    a.ChangeUnderwear(this, new Thong());
  }
}

Но теперь вам нужен какой-то способ, чтобы не дать врагу просто разыграть IB на B, а затем выдать себя за B, чтобы получить доступ только к членам A друзей. Есть идеи?

Решение 3: класс singleton позволяет его экземпляру принадлежать первому вызывающему, который его запрашивает. Класс друга пытается захватить экземпляр при запуске и вызывает истерику, если кто-то другой захватывает его первым

public class A
{
  private underwear myUnderwear;

  public ChangeUnderwear(B.IdCard friend, underwear newUnderwear) 
  {
    if (friend == null) return;
    myUnderwear = newUnderwear
  }
}

public class B
{
  public sealed class IdCard
  {
    private IdCard() {};
    private static bool created = false;
    public IDCard GetId()
    {
      if (created) throw new Exception("Why are two people asking for the same ID?!?");
      created = true;
      return new IDCard();
    }
  }

  private static IdCard id;

  static B()
  {
    id = IDCard.CreateId();
    if (id == false) throw new Tantrum("Panic: Someone stole my ID card before I could grab it");
  }

  private void MessWithA(A a)
  {
    a.ChangeUnderwear(id, new Thong());
  }
}
0 голосов
/ 05 марта 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...