Разрешить реализацию интерфейса только для определенных классов

Можно ли разрешить только некоторым определенным классам реализовать итерал? Скажем, что я создал интерфейс IMyInterface, и я хочу, чтобы только классы, полученные из UserControl, имели возможность реализовать мой интерфейс. Возможно ли это?

Ответ 1

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

interface IMyInterface
{
    void Foo();
    UserControl Control { get; }
}


class MyControl : UserControl, IMyInterface
{
    public void Foo()
    {
        // TODO: Write code here
    }

    UserControl IMyInterface.Control
    {
        get { return this; }
    }
}

UPDATE

Существует и другое решение - создание общего метода. Сам интерфейс не будет ограничен, но будет работать метод. Например, следующий метод требует, чтобы его параметр наследовал UserControl и реализовал IMyInterface:

void Bar<T>(T item)
  where T : UserControl, IMyInterface
{
    item.Width = 120;    // user control property
    item.Foo();          // IMyInterface method
}

Ответ 2

Похоже, вы хотите что-то вроде этого:

abstract class IMyInterface : UserControl { }

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

Ответ 3

Я понимаю, что это старый пост, но мне пришлось решить именно эту проблему.

Вот как вы можете это сделать:

class BaseClass { }

interface OnlyBaseClass<TSelf> where TSelf : BaseClass, OnlyBaseClass<TSelf>
{

}

class ChildClass : BaseClass, OnlyBaseClass<ChildClass> { }

class ImpostorClass : OnlyBaseClass<ImposterClass> { }

interface ImposterInterface : OnlyBaseClass<ImposterInterface > { }

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

Ограничение на TSelf можно понимать как:

TSelf должен: Наследовать от BaseClass и реализовать OnlyBaseClass <TSelf>

... который может использовать только тип, наследующий BaseClass и реализующий OnlyBaseClass.

Вы можете быть умными и делать следующее:

class AdvancedImpostorClass : OnlyBaseClass<ChildClass> {}

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

public SomeMethod<TBaseAndInterface>(TBaseAndInterface value)
    where TBaseAndInterface: BaseClass, OnlyBaseClass<TBaseAndInterface>
{ }

Все это стало возможным благодаря силе F-Bound Polymorphism.

Ответ 4

Это невозможно. Если вы видите интерфейс, его можно реализовать.

Ответ 5

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

Ответ 6

Случай, который вы описываете, по-видимому, соответствует "абстрактному методу в родительском классе" (здесь userControl), если интерфейс уже не существует для других целей.

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