Попытка наследовать три базовых класса и не может

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

Так, первое связано с наследованием базовых классов. Я в настоящее время наследовал два класса, ProfileBase и ISessionMgrEntry как таковой:

public class User : ProfileBase, ISessionMgrEntry

Но, я также хочу наследовать третий класс, MembershipUser, как это:

public class User : ProfileBase, MembershipUser, ISessionMgrEntry

Однако компилятор не позволит мне сделать это. Почему? И, как я обхожу это?

Спасибо.

PS - ASP.NET 3.5 / C#

Править

Привет. Я думаю ниже решения, может работать на то, чего я пытаюсь достигнуть. Это кажется довольно простым и прямым. Я делаю это так, я могу создать полное/объединенное User объект. Кто-либо видит какие-либо основания, почему это могло бы вызвать проблемы? Тот, который подошел, в то время как я был звоном, это перекрывает свойства. Например, оба MembershipUser и ProfileBase доля"UserName". Должен я просто выбрал один или другой, или это будет недостатком дизайна? Предложения? Еще раз спасибо.

 public class User
    {

        #region Constructors
            private readonly MembershipUser _MembershipUser;
            private readonly ProfileBase _ProfileBase;
        #endregion

        public User()
        {
            _MembershipUser = new MembershipUser();
            _ProfileBase = new ProfileBase();

        }

        public string Comment
        {
            get { return _MembershipUser.Comment as string; }
            set { _MembershipUser.Comment = value; }
        }

        public bool IsAnonymous
        {
            get { return _ProfileBase.IsAnonymous as bool; }
        } 

        ....

   }
28
задан Irshad 15 June 2015 в 07:32
поделиться

7 ответов

В первом примере вы фактически наследуете не два класса, а один класс и интерфейс.

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

Вам нужно будет создать интерфейс IMembershipUser и реализовать его в своем классе User .

Интерфейсы обычно получают имена на основе имени конкретного класса с префиксом I . Таким образом, класс MembershipUser будет иметь интерфейс IMembershipUser . Ничто не мешает вам использовать какое-то другое имя, но все, кто использует интерфейсы, привыкли к этому соглашению об именах.

Есть ряд причин, по которым мы не реализуем множественное наследование реализации напрямую. (Как вы знаете, мы поддерживаем множественное наследование интерфейсов ).

Однако я должен отметить, что компиляторы могут создавать MI для своих типов внутри CLR.Если вы пойдете по этому пути, есть несколько острых углов: результат не поддается проверке, нет взаимодействия с другими языками через CLS, а в V1 и V1.1 вы можете столкнуться с тупиковых ситуаций с блокировкой загрузчика ОС. (Мы решаем эту последнюю проблему, , но первые две проблемы остаются). Метод состоит в том, чтобы сгенерировать несколько таблиц VT в статических полях на основе RVA. Чтобы разместить адреса управляемых методов (которые, вероятно, еще не были JITted), вы используете конструкцию VTFixup. Эта конструкция представляет собой таблицу троек. Тройки состоят из токена управляемого метода, адреса в вашем изображении , который необходимо исправить (в данном случае, слот таблицы VTable, которую вы создаете в статика на основе RVA) и некоторые флаги. Возможные флаги описаны в corhdr.h, и они позволяют вам указать 32-битные или 64-битные размеры указателя, контроль над виртуальным поведением, а также то, будут ли некоторые обратные Поведение PInvoke следует применять в форме преобразователя, который в конечном итоге отправляет управляемому методу. Если мы выполняем переход неуправляемый-> управляемый, у вас также есть некоторый контроль над тем, какой домен приложения должен быть выбран для отправки вызова. Однако один из этих параметров (COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN) не существует в V1. Мы добавили его в V1.1.

Есть несколько причин, по которым мы не предоставили встроенную, поддающуюся проверке, CLS-совместимую версию множественного наследования реализации:

  1. На самом деле разные языки имеют разные ожидания относительно того, как работает MI. Например, как разрешаются конфликты и объединяются или дублируются повторяющиеся базы.Прежде чем мы сможем реализовать MI в CLR, мы должны провести обзор всех языков, выяснить общие концепции и решить, как выразить их в нейтральной для языка манере. { {1}} Нам также нужно будет решить, принадлежит ли MI к CLS и что это будет означать для языков, которым не нужна эта концепция (например, VB.NET). Конечно, мы занимаемся этим как общеязыковая среда выполнения, но у нас еще не было времени сделать это для MI .

  2. Количество мест, где действительно подходит ИМ, на самом деле довольно мало. Во многих случаях вместо этого можно выполнить задание с помощью множественного наследования интерфейсов. В других случаях вы можете использовать инкапсуляцию и делегирование. Если бы мы добавили немного другую конструкцию, например миксины , было бы это на самом деле более мощным?

  3. Множественное наследование реализаций привносит много сложности в реализацию. Эта сложность влияет на приведение типов, разметку, отправку, доступ к полям, сериализацию, сравнение идентичности, проверяемость, отражение, обобщения и, возможно, многие другие места.

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

40
ответ дан 28 November 2019 в 02:58
поделиться

в C # вы просто можете наследовать от одного класса , но реализует столько интерфейсов , сколько хотите. { {1}} в вашем случае ProfileBase и MembershipUser - это классы, а ISessionMgrEntry - интерфейс.

7
ответ дан 28 November 2019 в 02:58
поделиться
4
ответ дан 28 November 2019 в 02:58
поделиться

C# позволяет наследовать только одно: можно наследовать только от одного базового класса. В первом случае ISessionMgrEntry представляет собой интерфейс, отличный от базового класса. Вот хорошая статья об этой разнице: http://msdn.microsoft.com/en-us/library/ms973861.aspx

Во втором случае вы пытаетесь наследовать от обоих ProfileBase и MembershipUser, что компилятор не позволит. Лучший способ обойти это - инкапсулировать один (или оба) из ProfileBase и MembershipUser.

2
ответ дан 28 November 2019 в 02:58
поделиться

C # поддерживает только одиночное наследование. Вы можете объединить свои классы в цепочку (т.е. MembershipUser наследуется от ProfileBase ) или использовать интерфейсы .

4
ответ дан 28 November 2019 в 02:58
поделиться

C # не поддерживает множественное наследование.

В первом примере вы наследуете от ProfileBase и объявляете, что ваш класс реализует интерфейс ISessionMgrEntry .

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

3
ответ дан 28 November 2019 в 02:58
поделиться

Несколько интерфейсов с одинаковыми именами элементов не являются проблемой. Если члены могут использовать одну и ту же реализацию, просто создайте публичный член с тем же именем; если они не могут использовать одну и ту же реализацию, вы можете просто явно реализовать один (или все) члены.

Например, IEnumerable наследует IEnumerable , и оба предоставляют метод GetEnumerator () с разными типами возвращаемых значений. Следовательно, IEnumerable.GetEnumerator () обычно реализуется явно:

class Foo : IEnumerable<object>{
    // explicitly implement IEnumerable.GetEnumerator()
    IEnumerator IEnumerable.GetEnumerator ()
    {
        return GetEnumerator();
    }

    public IEnumerator<object> GetEnumerator ()
    {
        yield break;
    }
}

Вызов GetEnumerator () в IEnumerable.GetEnumerator () не является бесконечно рекурсивным вызовом ; он вызывает публичный член с тем же именем, не сам (т.е. метод IEnumerable.GetEnumerator () ).

0
ответ дан 28 November 2019 в 02:58
поделиться
Другие вопросы по тегам:

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