Практическое использование для «внутреннего» ключевого слова в C # - PullRequest
383 голосов
/ 03 октября 2008

Не могли бы вы объяснить, как на практике использовать ключевое слово internal в C #?

Я знаю, что модификатор internal ограничивает доступ к текущей сборке, но когда и при каких обстоятельствах его следует использовать?

Ответы [ 22 ]

5 голосов
/ 03 октября 2008

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

Например, DAL может иметь ORM, но объекты не должны подвергаться бизнес-уровню, все взаимодействие должно осуществляться статическими методами и передачей необходимых параметров.

5 голосов
/ 03 октября 2008

Как правило, существует два вида членов:

  • общедоступная поверхность : видна с внешней сборки (общедоступная, защищенная и внутренняя защита): вызывающий объект не является доверенным, поэтому требуется проверка параметров, документирование методов и т. д.
  • закрытая поверхность : не видна из внешней сборки (частные и внутренние или внутренние классы): вызывающей стороне обычно доверяют, поэтому проверка параметров, документация по методам и т. д. могут быть опущены.
4 голосов
/ 10 июня 2010

Внутренние классы позволяют вам ограничивать API вашей сборки. Это имеет свои преимущества, например упрощает понимание вашего API.

Кроме того, если в вашей сборке существует ошибка, вероятность исправления, вносящего критическое изменение, меньше. Без внутренних классов вы должны были бы предположить, что изменение открытых членов любого класса было бы серьезным изменением. С внутренними классами можно предположить, что изменение их открытых элементов нарушает только внутренний API сборки (и любые сборки, на которые есть ссылка в атрибуте InternalsVisibleTo).

Мне нравится иметь инкапсуляцию на уровне класса и на уровне сборки. Есть некоторые, кто не согласен с этим, но приятно знать, что функциональность доступна.

4 голосов
/ 03 октября 2008

Снижение шума, чем меньше типов вы выставляете, тем проще ваша библиотека. Защита от несанкционированного доступа / защита - это другое (хотя Reflection может победить ее).

2 голосов
/ 10 июня 2010

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

Однако я не вижу смысла в создании классов или участников internal без особых причин, настолько же мало, как имеет смысл делать их public или private без особых причин.

2 голосов
/ 03 октября 2008

У меня есть проект, который использует LINQ-to-SQL для обработки данных. У меня есть два основных пространства имен: Biz и Data. Модель данных LINQ находится в Data и помечена как «внутренняя»; пространство имен Biz содержит открытые классы, которые обертывают классы данных LINQ.

Итак, есть Data.Client и Biz.Client; последний предоставляет все соответствующие свойства объекта данных, например:

private Data.Client _client;
public int Id { get { return _client.Id; } set { _client.Id = value; } }

Объекты Biz имеют закрытый конструктор (для принудительного использования фабричных методов) и внутренний конструктор, который выглядит следующим образом:

internal Client(Data.Client client) {
    this._client = client;
}

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

Впервые я действительно много использовал internal, и это оказалось весьма полезным.

1 голос
/ 10 июня 2010

Имейте в виду, что любой класс, определенный как public, будет автоматически отображаться в intellisense, когда кто-то смотрит на пространство имен вашего проекта. С точки зрения API важно показывать пользователям вашего проекта только те классы, которые они могут использовать. Используйте ключевое слово internal, чтобы скрыть вещи, которые они не должны видеть.

Если ваш Big_Important_Class для проекта А предназначен для использования вне вашего проекта, то вам не следует отмечать его internal.

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

1 голос
/ 30 декабря 2009

Как насчет этого: обычно рекомендуется не предоставлять объект List внешним пользователям сборки, а предоставлять IEnumerable. Но намного проще использовать объект List внутри сборки, потому что вы получаете синтаксис массива и все другие методы List. Итак, у меня обычно есть внутреннее свойство, открывающее список для использования внутри сборки.

Комментарии приветствуются об этом подходе.

1 голос
/ 03 октября 2008

единственное, что я когда-либо использовал в качестве внутреннего ключевого слова, это код проверки лицензии в моем продукте; -)

1 голос
/ 03 октября 2008

Одним из применений внутреннего ключевого слова является ограничение доступа к конкретным реализациям со стороны пользователя вашей сборки.

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

Кроме того, внутренние конструкторы позволяют вам контролировать, где и когда создается экземпляр общедоступного класса.

...