Практическое использование для «внутреннего» ключевого слова в C #

Как насчет этого:

- (void)pageViewController:(UIPageViewController*)pgVC willTransitionToViewControllers:(NSArray*)pendingVCs
{
    pgVC.dataSource = nil; // ... to disallow user to change pages until animation completes
}

- (void)pageViewController:(UIPageViewController*)pgVC
        didFinishAnimating:(BOOL)finished
   previousViewControllers:(NSArray*)prevVCs
       transitionCompleted:(BOOL)completed
{
    if(completed || finished) {
        pgVC.dataSource = _pgViewDataSource; // ... to allow user to change pages again
    }
}
394
задан Philip Stratford 15 April 2019 в 11:00
поделиться

22 ответа

Утилита или классы/методы помощника, к которым требуется получить доступ от многих других классов в рамках того же блока, но что Вы хотите гарантировать код в других блоках, не могут получить доступ.

От MSDN (с помощью archive.org):

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

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

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

353
ответ дан ruffin 15 April 2019 в 11:00
поделиться

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

public class DangerousClass {
    public void SafeMethod() { }
    internal void UpdateGlobalStateInSomeBizarreWay() { }
}
-6
ответ дан yfeldblum 15 April 2019 в 11:00
поделиться
  • 1
    readme говорит, делают-f Make-файл-libbz2_so вместо, делают-f Makefile_libbz2_so – mr2ert 28 June 2013 в 23:10

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

1
ответ дан Steven A. Lowe 15 April 2019 в 11:00
поделиться
  • 1
    Это действительно, что ищет OP? Я понял его по-другому (как поиск значение ). – Pekka 웃 2 June 2010 в 17:50

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

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

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

1
ответ дан Andrew Kennan 15 April 2019 в 11:00
поделиться

У меня есть проект, который использует LINQ к SQL для бэкенда данных. У меня есть два основных пространства имен: Бизнес и Данные. Модель данных LINQ живет в Данных и отмечена "внутренняя"; пространство имен Бизнеса имеет общедоступные классы, которые переносят классы данных LINQ.

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

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

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

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

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

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

2
ответ дан Keith Williams 15 April 2019 в 11:00
поделиться
  • 1
    array_search и array_keys обе работы для меня, однако array_search действительно вынимают дополнительный шаг необходимости захватить первое значение массива, возвращенного array_keys. Таким образом, я буду использовать array_search, но +1 каждому из Вас, поскольку они - оба хорошие ответы. – JD Isaacks 2 June 2010 в 18:07

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

  • общедоступная поверхность : видимый от внешнего блока (общественность, защищенная и внутренняя защищенный): вызывающей стороне не доверяют, таким образом, проверка параметра, документация метода, и т.д. необходима.
  • частная поверхность : не видимый от внешнего блока (частные и внутренние, или внутренние классы): вызывающей стороне обычно доверяют, таким образом, проверка параметра, документация метода, и т.д. может быть опущена.
5
ответ дан Rod 15 April 2019 в 11:00
поделиться

Шумоподавление, чем меньше типов Вы представляете, тем более проста Ваша библиотека. Проверка трамбовки / безопасность - другой (хотя Отражение может выиграть у него).

4
ответ дан Quibblesome 15 April 2019 в 11:00
поделиться

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

Говорят, что Вы хотели, чтобы абстрактный класс был замечен другим блоком, но Вы не хотите, чтобы кто-то был в состоянии наследоваться ему. Изолированный не будет работать, потому что это абстрактно по причине, другие классы в том блоке действительно наследовались ему. Частный не будет работать, потому что Вы могли бы хотеть объявить Родительский класс где-нибудь в другом блоке.

namespace Base.Assembly
{
  public abstract class Parent
  {
    internal abstract void SomeMethod();
  }

  //This works just fine since it's in the same assembly.
  public class ChildWithin : Parent
  {
    internal override void SomeMethod()
    {
    }
  }
}

namespace Another.Assembly
{
  //Kaboom, because you can't override an internal method
  public class ChildOutside : Parent
  {
  }

  public class Test 
  { 

    //Just fine
    private Parent _parent;

    public Test()
    {
      //Still fine
      _parent = new ChildWithin();
    }
  }
}

, Как Вы видите, это эффективно позволяет кому-то использовать Родительский класс не имея возможности для наследования.

8
ответ дан Programmin Tool 15 April 2019 в 11:00
поделиться
  • 1
    Время выполнения Языка CLR=Common, интерпретатор, который выполняет весь код.NET. BCL = Библиотека базовых классов, платформа.NET классов, которые установлены наряду с CLR и доступны для использования всем кодом.NET. – Will 10 March 2009 в 13:10

Очень интересное использование внутренних - с внутренним участником, конечно, ограничиваемым только блоком, в котором это объявляется - получает "друга" функциональность до некоторой степени из него. Участник друга - что-то, что видимо только к определенным другим блокам за пределами блока в который его заявленное. C# имеет не созданный в поддержке друга, однако CLR делает.

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

А хорошее использование для InternalsVisibleTo должно представить различных внутренних участников блоку модульного теста, таким образом избавляющему от необходимости сложную отражательную работу arounds протестировать тех участников. Все внутренние участники, являющиеся видимым, не являются большой частью проблемы, однако проявление этого подхода действительно пачкает Ваши интерфейсы класса довольно в большой степени и может потенциально разрушить инкапсуляцию в рамках блока объявления.

6
ответ дан cfeduke 15 April 2019 в 11:00
поделиться
  • 1
    Я соглашаюсь с созданием обратной карты, если необходимо сделать много поисков, но определенно существует простой способ – Michael Mrozek 2 June 2010 в 17:41

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

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

причины это может вызвать проблемы, то, что другой разработчик может быть обвинен в создании другого класса в том же блоке настолько, Ваш. Наличие внутренностей уменьшает ясность абстракции и может вызвать проблемы, будучи неправильно используемым. Это была бы та же проблема, как будто Вы обнародовали его. Другой класс, который создается другим разработчиком, является все еще потребителем, точно так же, как любой внешний класс. Абстракция класса и инкапсуляция не только для защиты для/от внешних классов, но и ни для кого и всех классов.

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

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

10
ответ дан mattlant 15 April 2019 в 11:00
поделиться

Если Вы пишете DLL, который инкапсулирует тонну сложной функциональности в простой общедоступный API, то “internal” используется на участниках класса, которые не должны быть представлены публично.

Скрывающаяся сложность (иначе инкапсуляция) является главным понятием качественной разработки программного обеспечения.

27
ответ дан Jeffrey L Whitledge 15 April 2019 в 11:00
поделиться
  • 1
    Нет никакого приспосабливающего стандарту способа непосредственно зависеть от него. Это ясно также мне. То, что я имел в виду, так скажите в моем выше комментария, было то, что размер устройства хранения данных ссылок заметен и имеет эффект. Когда у Вас есть структура, содержащая ссылочного участника a и другая структура, которая имеет участника указателя вместо этого и никакое дополнение, или выравнивание выходит, размер структуры изменится, если ссылки имели различный размер... – Peter G. 18 October 2010 в 06:41

Быть управляемым "использованием в качестве строгого модификатора, поскольку можно" постановить, что я использую внутренний везде, я должен получить доступ, скажем, к методу от другого класса, пока я явно не должен получать доступ к нему от другого блока.

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

12
ответ дан Ilya Komakhin 15 April 2019 в 11:00
поделиться
  • 1
    @Martin Йорк, можно было зависеть от sizeof (T*) == sizeof (T&) – Peter G. 17 October 2010 в 22:45

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

, Когда у Вас есть основанная на C/C++ библиотека, которую Вы хотите к DllImport, можно импортировать эти функции как статические функции класса и сделать их внутренними, таким образом, пользователь только имеют доступ к обертке а не исходному API, таким образом, это не может смешать ни с чем. Функции, являющиеся статичным, можно использовать их везде в блоке для нескольких классов обертки, в которых Вы нуждаетесь.

можно смотреть на Моно. Каир, это - обертка вокруг каирской библиотеки, которая использует этот подход.

20
ответ дан Edwin Jarvis 15 April 2019 в 11:00
поделиться
  • 1
    @Peter G: Это не будет работать, как Вы ожидаете. Поскольку ссылки являются псевдонимами, RHS на самом деле получает размер T (как T& псевдоним к T). Таким образом это только содержит, когда sizeof (T) == sizeof (освобождают*). Попытайтесь печатать sizeof(char&), это возвратится 1. Псевдонимы не представляют новую переменную, они представляют новое название переменной (таким образом, им даже, возможно, не понадобятся указатели, которые будут реализованы (если переменная и ссылка находятся в том же объеме). – Martin York 18 October 2010 в 00:04

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

57
ответ дан Joel Mueller 15 April 2019 в 11:00
поделиться

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

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

5
ответ дан Aaron Powell 15 April 2019 в 11:00
поделиться

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

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

.
1
ответ дан 22 November 2019 в 23:38
поделиться

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

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

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

1
ответ дан 22 November 2019 в 23:38
поделиться

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

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

2
ответ дан 22 November 2019 в 23:38
поделиться

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

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

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

4
ответ дан 22 November 2019 в 23:38
поделиться

Этот пример содержит два файла: Assembly1.cs и Assembly2.cs. Первый файл содержит внутренний базовый класс BaseClass. Во втором файле попытка создать экземпляр BaseClass приведет к ошибке.

// Assembly1.cs
// compile with: /target:library
internal class BaseClass 
{
   public static int intM = 0;
}

// Assembly1_a.cs
// compile with: /reference:Assembly1.dll
class TestAccess 
{
   static void Main()
   {  
      BaseClass myBase = new BaseClass();   // CS0122
   }
}

В этом примере используйте те же файлы, что и в примере 1, и измените уровень доступности BaseClass на public . Также измените уровень доступности члена IntM на внутренний . В этом случае вы можете создать экземпляр класса, но не можете получить доступ к внутреннему члену.

// Assembly2.cs
// compile with: /target:library
public class BaseClass 
{
   internal static int intM = 0;
}

// Assembly2_a.cs
// compile with: /reference:Assembly1.dll
public class TestAccess 
{
   static void Main() 
   {      
      BaseClass myBase = new BaseClass();   // Ok.
      BaseClass.intM = 444;    // CS0117
   }
}

источник : http://msdn.microsoft.com/en-us/library/7c5ka91b (VS.80) .aspx

7
ответ дан 22 November 2019 в 23:38
поделиться

Если Бобу нужен BigImportantClass, то Бобу нужно заставить людей, владеющих проектом A, подписаться под гарантией, что BigImportantClass будет написан для удовлетворения его потребностей, протестирован, чтобы убедиться, что он удовлетворяет его потребностям, задокументирован как удовлетворяющий его потребностям, и что будет установлен процесс, гарантирующий, что он никогда не будет изменен так, чтобы больше не удовлетворять его потребностям.

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

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

83
ответ дан 22 November 2019 в 23:38
поделиться

Идея состоит в том, что при проектировании библиотеки только классы, предназначенные для использования извне (клиентами вашей библиотеки), должны быть общедоступными. Таким образом, вы можете скрыть классы, которые

  1. Могут измениться в будущих выпусках (если бы они были общедоступными, вы бы взломали клиентский код)
  2. Бесполезны для клиента и могут вызвать путаницу
  3. Небезопасны (поэтому неправильное использование может довольно сильно нарушить работу вашей библиотеки)

и т. д.

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

0
ответ дан 22 November 2019 в 23:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: