Подтвердить что ты не робот

Почему это не "непоследовательная доступность" для использования частного вложенного типа внутри родового типа в списке интерфейсов?

Если заголовок не является полностью понятным, вот код, который меня озадачивает:

public interface IFoo<T>
{
}

public class MyClass : IFoo<MyClass.NestedInMyClass>
{
  private class NestedInMyClass
  {
  }
}

Я удивляюсь, что это компиляция без ошибок. Похоже, я разоблачаю тип private. Разве это не должно быть незаконным?

Возможно, ваши ответы просто будут "Нет никакого правила против этого, так почему бы не так?" Возможно, это также удивительно, что MyClass.NestedInMyClass находится даже в "сфере действия". Если я удалю квалификацию MyClass., она не будет компилироваться.

(Если я изменил IFoo<> на общий класс, который затем должен стать базовым классом MyClass, это незаконно, поскольку базовый тип должен быть как минимум доступным, как сам тип.)

Я попробовал это с компилятором С# 4 Visual Studio 2010.

4b9b3361

Ответ 1

Никакой внешний код не может передать объект этому интерфейсу, поэтому он не является проблемой доступности.

public классам даже разрешено реализовывать интерфейсы private или internal - и аналогичным образом, никакой набросок не может фактически произойти из внешнего кода.

Re: обсуждение реализаций, которые зависят от T - вам будет разрешено это, если вы используете явную реализацию интерфейса - потому что методы для интерфейса в этом случае являются частными. Например:.

public interface IFoo<T>
{
  void DoStuff(T value);
}

public class MyClass : IFoo<MyClass.NestedInMyClass>
{
  void IFoo<MyClass.NestedInMyClass>.DoStuff(MyClass.NestedInMyClass value)
  {
  }
  private class NestedInMyClass
  {
  }
}

работает (поскольку метод реализации интерфейса не отображается самим классом).

Ответ 2

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

Наличие открытого класса Foo реализует интерфейс частного или внутреннего типа IBar включает код, который имеет доступ к IBar, чтобы отбрасывать Foo ссылки на IBar. Тот факт, что Foo доступен для кода, который не имеет доступа к IBar, никоим образом не подразумевает, что он также не будет использоваться кодом, который имеет такой доступ. Действительно, было бы совершенно нормально, что сборка или класс, где Foo определена, захотят использовать функции Foo, которые недоступны для внешнего мира; тот факт, что он реализует IBar, будет просто одной из таких функций.