试图继承三个基类而不能

时间:2010-02-04 15:56:37

标签: c# inheritance multiple-inheritance

我有一些与我的User课程设计相关的问题但是 他们是不同的,我认为他们应该是独立的 的问题。

所以,第一个与基类的继承有关。我目前 继承两个类ProfileBaseISessionMgrEntry,如下:

public class User : ProfileBase, ISessionMgrEntry

但是,我还希望继承第三个类MembershipUser,如下所示:

public class User : ProfileBase, MembershipUser, ISessionMgrEntry

然而,编译器不会让我这样做。为什么?而且,我该怎么做 在这附近?

感谢。

PS - ASP.NET 3.5 / C#

修改

您好。我认为以下解决方案可能适用于我想要实现的目标。看起来非常简单直接。我这样做,所以我可以创建一个完整/组合User对象。有没有人看到任何可能导致问题的原因?我在叮叮当当时出现的是重叠属性。例如,MembershipUserProfileBase共享“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; }
        } 

        ....

   }

8 个答案:

答案 0 :(得分:38)

在第一个示例中,您实际上并不是从两个类继承,而是从一个类和一个接口继承。

C#不允许从类中继承多个,但允许您实现多个接口。请参阅 this MSDN blog post (链接已死,因此文本粘贴在下方)以获取有关原因的更多信息。

您必须制作一个IMembershipUser界面并在User课程中实施该界面。

接口通常根据前缀为I的具体类名给出名称。因此,类MembershipUser将具有接口IMembershipUser。没有什么可以阻止你使用其他名称,但使用接口的每个人都习惯于这个命名约定。

  

有很多原因我们没有实现Multiple   直接实现继承。 (如您所知,我们支持多个   接口继承)。

     

但是,我应该指出编译器可以创建   MI在CLR中的类型。如果你有一些粗糙的边缘   走这条路:结果是无法验证的,没有互操作   通过CLS使用其他语言,在V1和V1.1中可能会遇到   OS加载程序锁定死锁。 (我们正在解决最后一个问题,   但前两个问题仍然存在)。该技术是生成一些   基于RVA的静态字段中的VTable。为了存放地址   您使用的是托管方法(可能还没有JIT)   VTFixup构造。这个结构是三元组的表。该   三元组由托管方法的令牌,您的地址中的地址组成   应该修复的图像(在这种情况下,VTable的一个插槽你   正在创建基于RVA的静态)和一些标志。可能   corhdr.h中描述了标志,它们允许您指定32-与   64位指针大小,控制虚拟行为,以及是否有一些   reverse-PInvoke行为应该以thunk的形式应用   最终调度到托管方法。如果我们正在表演   unmanaged->托管转换,你也可以控制哪些   应该选择AppDomain来发送呼叫。但是,一个   这些选项(COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN)没有   存在于V1中。我们在V1.1中添加了它。

     

我们有几个原因没有提供可验证的,可验证的,   符合CLS的多实现继承版本:

     
      
  1. 不同的语言实际上对MI的工作方式有不同的期望。例如,如何解决冲突以及是否重复   基地合并或冗余。在我们在CLR中实现MI之前,   我们必须对所有语言进行调查,找出共同点   概念,并决定如何以语言中立的方式表达它们。   我们还必须决定MI是否属于CLS以及什么   这对于不想要这个概念的语言来说意味着(大概是这样)   例如VB.NET)。当然,这就是我们所处的业务   公共语言运行时,但我们还没有为MI做这件事   爱好。

  2.   
  3. MI真正适合的地方实际上非常小。在许多情况下,多个接口继承可以获得   完成工作。在其他情况下,您可以使用封装   和代表团。如果我们要添加一个稍微不同的结构,比如   mixins,实际上会更强大吗?

  4.   
  5. 多个实现继承为实现注入了很多复杂性。这种复杂性影响了铸造,布局,   调度,现场访问,序列化,身份比较,   可验证性,反思,泛型,可能还有很多其他的   地方。

  6.         

    这个功能本身并不清楚。它的   我们经常被问到的事情。这是我们尚未完成的事情   勤奋。但是我的直觉告诉我,在我们做了很深的事情之后   检查时,我们仍然会决定不使用该功能。

答案 1 :(得分:6)

在c#中你可以继承一个类,但可以实现任意数量的接口。 在您的情况下,ProfileBaseMembershipUser是类,ISessionMgrEntry是一个接口。

答案 2 :(得分:4)

C#仅支持单继承。您可以将您的课程链接起来(即MembershipUser继承自ProfileBase)或使用interfaces

答案 3 :(得分:4)

C#不允许multiple inheritance

答案 4 :(得分:2)

C#不支持多重继承。

在第一个示例中,您继承自ProfileBase并声明您的类要实现ISessionMgrEntry接口。

您可以根据需要为类添加任意数量的接口(前提是您全部实现)。

答案 5 :(得分:2)

C#只允许单继承:您只能从一个基类继承。在第一种情况下,ISessionMgrEntry是一个与基类不同的接口。这是一篇关于差异的好文章:http://msdn.microsoft.com/en-us/library/ms973861.aspx

在第二种情况下,您尝试从ProfileBaseMembershipUser继承,编译器将不允许这两种情况。解决这个问题的最佳方法是封装ProfileBaseMembershipUser中的一个(或两个)。

答案 6 :(得分:0)

具有相同成员名称的多个接口不是问题。如果成员可以共享相同的实现,只需创建一个具有相同名称的公共成员;如果他们不能共享相同的实现,您可以只显式实现一个(或所有)成员。

例如,IEnumerable<T>继承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()并非无限递归呼叫;它调用同名的公共成员, not 本身(即IEnumerable.GetEnumerator()方法)。

答案 7 :(得分:0)

可以通过接口实现多重继承。 派生示例必须继承自Base1,Base2和Base3。

class Base1 { public abstract void Method1(); } //base class 1
class Base2 { public abstract void Method2(); } //base class 2
class Base3 { public abstract void Method3(); } //base class 3

//helper interfaces
interface IBase1 { Base1 { get; } } 
interface IBase2 { Base2 { get; } }
interface IBase3 { Base3 { get; } } 

class Derived: IBase1, IBase2, IBase3 { //derived class

  public class D1 : Base1 {  //custom implementation of Base1 class
    public override void Method1() { /* derived Method1 code */ }
  } 
  public class D2 : Base2 {  //custom implementation of Base2 class
    public override void Method2() { /* derived Method2 code */ }
  } 
  public class D3 : Base3 {  //custom implementation of Base3 class
    public override void Method3() { /* derived Method3 code */ }
  } 

  //classes as members
  D1 d1;
  D2 d2;
  D3 d3;
  //....

  //interface implementation
  public Base1 => d1;
  public Base2 => d2;
  public Base3 => d3; 
}