Внутренний абстрактный класс: как скрыть использование вне блока?

Пессимистическая блокировка является хорошей идеей, если серьезные конфликты будут вероятными. Для большей части программирования Вы не будете видеть серьезных конфликтов, таким образом, пессимистическая блокировка будет довольно бессмысленна. Исключения к этому были бы то, если Вы:

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

Иначе...

48
задан Hannele 19 February 2014 в 16:45
поделиться

6 ответов

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

Способ к Сделайте это, чтобы сделать абстрактный базовый класс общедоступным, но предоставьте ему внутренний конструктор по умолчанию:

public abstract class MyClass
{
    internal MyClass() { }
}

Это позволит MyClass (и, следовательно, его членам) быть видимыми и использоваться для классов вне вашей сборки, но классы вне вашей сборки не могут наследовать от него (появится ошибка компиляции).

Изменить: если классы, которые могут быть видимыми внешними сборками, наследуются от MyClass, вы не можете предотвратить MyClass также видимым - например, , отображается в Intellisense. Однако вы можете предотвратить их использование , выполнив указанные выше действия.

89
ответ дан 26 November 2019 в 18:38
поделиться

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

9
ответ дан 26 November 2019 в 18:38
поделиться

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

Поместите свой абстрактный базовый класс в 1 сборка со всем внутренним. В AssemblyInfo для этой сборки вам нужно добавить

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

Затем в другой сборке у вас будут все классы, которые вы хотите публично доступны. Обратите внимание, что вы по-прежнему сможете получить доступ к базовому классу из intellisense для любого кода внутри cs_friend_assemblies_2 или того, как вы называете свою сборку, но не где-либо еще.

6
ответ дан 26 November 2019 в 18:38
поделиться

Вы не можете одновременно сделать класс доступным для других сборок для наследования, но также и частным, чтобы он не был виден другим потребителям. Вы можете сделать класс внутренним и предоставить его конкретной сборке (если это дружественная сборка) с помощью атрибута [InternalsVisibleTo] , но я не думаю, что это то, что вам нужно.

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

abstract class MyBaseClass
{
    protected MyBaseClass() { ... } // only inheritors can access this...
}

Вы можете скрыть члены класса от Intellisense, используя атрибут EditorBrowsable :

abstract class MyBaseClass
{ 
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    public void SomeMethodToBeHidden() { }
}

Следует отметить, что некоторые люди сообщали о проблемах с IDE, которые не всегда соблюдали этот атрибут.

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

Будут ли другие сборки когда-либо унаследованы от вашего абстрактного базового класса или любого из публичные классы, которые наследуются от вашего абстрактного базового класса?

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

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

Это поможет?

0
ответ дан 26 November 2019 в 18:38
поделиться

Насколько я понимаю, это не проблема. Заметьте:

public abstract class Foo {
    public void virtual Bar() {
        // default implementation
    }
}

public class NormalFoo : Foo { }

public class SpecialFoo : Foo {
    public override void Bar() {
        // special implementation
    }
}

var foolist = new List<Foo>();

foolist.Add( new NormalFoo() );
foolist.Add( new SpecialFoo() );

foreach (var f in foolist) {
    f.Bar();
}

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

1
ответ дан 26 November 2019 в 18:38
поделиться
Другие вопросы по тегам:

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