Могу ли я указать интерфейсы при объявлении участника?
Мне нужен член моего класса, чтобы он был элементом управления, и чтобы он реализовывал интерфейс, который мы определяем.
Если я объявлю это так...
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;
}
... за исключением того, что ни одна из этих работ. Могу ли я указать интерфейсы при объявлении участника, и если да, то как?
6 ответов
Вы можете использовать дженерики с ограничениями:
public interface MyClass {
public T GetMyControl() where T : Control, IMyInterface { /* ........ */ }
}
Так как написать класс-оболочку для Control и простой универсальный класс очень сложно:
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();
}
}
}
}
Объявите интерфейс ISelf(из T) [*], который включает функцию "Self", которая возвращает T. Пусть ваш интерфейс поддерживает неуниверсальную и универсальную версию, где универсальная версия наследует и неуниверсальную версию, и ISelf(из сам). Затем вы можете иметь класс, унаследованный от ISelf(из Control) и ISelf(из IMyInterface), и объявить поле MyMember типа ISelf(из IMyInterface(из Control)). Затем MyMember может использоваться как iMyInterface, а MyMember.Self - как элемент управления. Любое количество интерфейсов может быть объединено таким образом.
[*] Синтаксис VB для обобщений используется, чтобы избежать обработки угловых скобок как тегов HTML.
Вы можете иметь свой собственный класс, полученный из элемента управления с интерфейсом, определенным как:
class MyControl : Control, IMyInterface
{
}
а затем использовать этот класс в качестве члена:
public class MyClass
{
public MyControl MyMember;
}
Используйте силу наследования на интерфейсе
public interface IMyInterface : Control
{
..
}
Теперь вы говорите, что хотите контроль с некоторыми специальными методами.
РЕДАКТИРОВАТЬ: TcKs, конечно, правильно.. вы не можете наследовать интерфейс от конкретного класса.
Одним из способов решения этой проблемы может быть расширение интерфейса с помощью свойства или метода, который возвращает элемент управления.
Образец:
public interface IMyInterface
{
Control Control { get; }
[..rest of the definition..]
}
и реализовать это так:
class MyControl : Control, IMyInterface
{
public Control Control { get { return this; } }
[..rest of the implementation..]
}
Это звучит в корне неправильно.
Объявляет ли IMyInterface только те же методы / свойства, что и в классе Control? Если нет, что вы надеетесь достичь? Вы не можете реализовать интерфейс и игнорировать методы, объявленные внутри него - вы должны явно выписать реализации.
Если IMyInterface действительно объявляет только те же методы / свойства, что и в классе Control, вам придется создать свой собственный класс MyControl, который наследуется от Control и реализует IMyInterface. Это не какая-то глупая причуда языка. Класс Control не был определен как IMyInterface, а C# является статически типизированным, а не "утиным" языком, поэтому он не может автоматически предоставить Control любой интерфейс, какой вы пожелаете.