Наследуется только внутри сборки в C # - PullRequest
12 голосов
/ 10 марта 2009

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

Ответы [ 8 ]

16 голосов
/ 10 марта 2009
14 голосов
/ 10 марта 2009

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

public class Foo
{
    internal Foo()
    {
    }

    public Foo Create()
    {
        return new Foo();
    }
}

Вот альтернатива, которая позволяет вам обновлять класс во внешних сборках

public sealed class Foo : FooBase
{

}

public class FooBase
{
    internal FooBase() { }
}

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

5 голосов
/ 10 марта 2009

Если ваш класс абстрактный, есть очень простой способ сделать это:

public abstract class Foo {
    internal abstract void DoNothing();
    // ... other members
}

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

1 голос
/ 13 марта 2019

Чтобы ответить на вопрос 10 лет спустя (я искал то же самое решение, поэтому думаю, что было бы полезно записать его на тот случай, если у кого-нибудь еще возникнет такая же проблема в будущем), с тех пор эта проблема была решена изначально (хотя и косвенно), с модификатором доступа « частная защита », представленным в C # 7.2.

Этот модификатор разрешает доступ только в том случае, если он находится в той же сборке и является производным от базового класса. Примените его к конструктору, и он не может быть выведен за пределы текущей сборки. Кроме того, если вы можете избежать «внутренних» и / или метаданных, сделайте это, поскольку это требует C # 7.2, что может нарушить совместимость со старыми устройствами или приложениями. Также обратите внимание, что ошибка, создаваемая этим (не может получить доступ к конструктору из-за уровня защиты), не та же, что и при попытке получить запечатанный класс (не может получить запечатанный класс), но конечный результат тот же.

1 голос
/ 10 октября 2017

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

  1. Создать базовый класс с внутренним конструктором.
  2. Сделайте ваши производные классы наследуемыми от базового класса и запечатаны.

`` ``

public abstract class LockResult {
    internal LockResult() {

    }
}

public sealed class LockSucceededResult : LockResult {
    //Info for when a lock succeeded
}

public sealed class LockFailedResult : LockResult {
    //Info for when a lock failed
}

`` ``

1 голос
/ 10 марта 2009

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

public interface IFoo
{
}

internal class Foo : IFoo
{
}

public sealed class PublicFoo : IFoo
{
    private Foo m_Foo = new Foo();
}
1 голос
/ 10 марта 2009

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

public class MyClass{
  public MyClass(){
    if(this.GetType().Assembly != typeof(MyClass).Assembly){
        throw new Exception("Can't derive from this type!");
  }
}

Проверил это. Кажется, работает. Единственная проблема заключается в том, что если кто-то не читает документацию, проблема известна во время выполнения.

0 голосов
/ 10 марта 2009

Нет. В самом языке C # такого положения нет. Тем не менее, обходные пути - как предложено другими здесь - может быть достаточным.

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