Могу ли я указать интерфейсы, когда я объявляю участника?

Мне нужен член моего класса для управления, а для него - интерфейс, который мы определяем.

Если я объявлю это так...

public class MyClass
{
    public Control MyMember;
}

... тогда я не получаю методы интерфейса, но если я объявлю это так...

public class MyClass
{
    public IMyInterface MyMember;
}

... тогда я не получаю методы управления. Есть ли способ указать, что MyMember должен быть инициализирован типом, который наследуется от обоих? Я не могу найти его на MSDN. Что-то вроде...

public class MyClass
{
    public Control : IMyInterface MyMember;
}

... или...

public class MyClass
{
    public Control MyMember : IMyInterface;
}

... за исключением того, что никто из них не работает. Могу ли я указать интерфейсы, когда я объявляю член, и если да, то как?

Ответ 1

Вы можете использовать generics с ограничениями:

public interface MyClass {
    public T GetMyControl() where T : Control, IMyInterface { /* ........ */ }
}

Ответ 2

Поскольку очень сложно писать класс оболочки вокруг элемента управления и простой общий класс:

public class MyGenericClass<T> where T : Control, IMyInterface
{
    public T t;
}

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

public class MyClass
{
    private IMyInterface m_field;
    public Control FieldAsControl
    {
        get { return m_field as Control; }
    }
    public IMyInterface Field
    {
        get { return m_field; }
        set
        {
            if (m_field is Control)
            {
                m_field = value;
            }
            else
            {
                throw new ArgumentException();
            }
        }
    }
}

Ответ 3

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

class MyControl : Control, IMyInterface
{
}

а затем используйте этот класс в качестве члена:

public class MyClass
{
    public MyControl MyMember;
}

Ответ 4

Объявить интерфейс ISelf (из T) [*], который включает в себя функцию "Self", которая возвращает T. Поддерживает ли ваш интерфейс не общую и общую версию, где общая версия наследует как не общую версию, так и Сам себе (сам по себе). Затем вы можете наследовать класс как от ISelf (Control), так и от ISelf (от IMyInterface) и объявить свое поле MyMember типом ISelf (IMyInterface (of Control)). Затем MyMember может использоваться как iMyInterface и MyMember.Self как элемент управления. Любое количество интерфейсов может быть объединено таким образом.

[*] Синтаксис VB для дженериков, используемых для того, чтобы избежать угловых скобок, обработанных как HTML-теги.

Ответ 5

Используйте силу наследования на интерфейсе

public interface IMyInterface : Control
{
  ..
}

Теперь вы говорите, что хотите элемент управления с некоторыми специальными методами.


EDIT: TcK, конечно, правы. Вы не можете наследовать интерфейс из конкретного класса.

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

Пример:

public interface IMyInterface 
{
  Control Control { get; }

  [..rest of the definition..]
}

и реализовать его следующим образом:

class MyControl : Control, IMyInterface
{
  public Control Control { get { return this; } }

  [..rest of the implementation..]
}

Ответ 6

Это звучит принципиально неправильно.

Объявляет ли IMyInterface только те же методы/свойства, что и в классе Control? Если нет, чего вы надеетесь достичь? Вы не можете реализовать интерфейс и игнорировать объявленные в нем методы - вы должны явно записать реализации.

Если IMyInterface фактически объявляет те же методы/свойства, что и в классе Control, вам нужно будет создать свой собственный класс MyControl, который наследует от Control и реализует IMyInterface. Это не какая-то глупая причуда языка. Класс Control не был определен как IMyInterface, а С# - это статически типизированный, а не "утиный" язык, поэтому он не может автоматически выдавать управление любому желаемому интерфейсу.