Почему это не "непоследовательная доступность" для использования частного вложенного типа внутри родового типа в списке интерфейсов?
Если заголовок не является полностью понятным, вот код, который меня озадачивает:
public interface IFoo<T>
{
}
public class MyClass : IFoo<MyClass.NestedInMyClass>
{
private class NestedInMyClass
{
}
}
Я удивляюсь, что это компиляция без ошибок. Похоже, я разоблачаю тип private
. Разве это не должно быть незаконным?
Возможно, ваши ответы просто будут "Нет никакого правила против этого, так почему бы не так?" Возможно, это также удивительно, что MyClass.NestedInMyClass
находится даже в "сфере действия". Если я удалю квалификацию MyClass.
, она не будет компилироваться.
(Если я изменил IFoo<>
на общий класс, который затем должен стать базовым классом MyClass
, это незаконно, поскольку базовый тип должен быть как минимум доступным, как сам тип.)
Я попробовал это с компилятором С# 4 Visual Studio 2010.
Ответы
Ответ 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
, будет просто одной из таких функций.