开发者

Trying to inherit three base classes and can't

开发者 https://www.devze.com 2022-12-19 08:49 出处:网络
I have a few questions related to the design of my User class b开发者_如何学Gout they are different enough that I think they should be independent

I have a few questions related to the design of my User class b开发者_如何学Gout they are different enough that I think they should be independent questions.

So, the first is related to inheritance of base classes. I am currently inheriting two classes, ProfileBase and ISessionMgrEntry as such:

public class User : ProfileBase, ISessionMgrEntry

But, I also want to inherit a third class, MembershipUser, like this:

public class User : ProfileBase, MembershipUser, ISessionMgrEntry

However, the compiler won't let me do that. Why? And, how do I get around this?

Thanks.

PS - ASP.NET 3.5 / C#

EDIT

Hi. I think the below solution may work for what I am trying to acheive. It seems pretty simple and straight forward. I am doing this so I can create a complete/combined User object. Does anybody see any reason why this might cause problems? One that came up while I was ding this is overlapping properties. For example, both MembershipUser and ProfileBase share "UserName". Should I just chose one or the other or will this be a design flaw? Suggestions? Thanks again.

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; }
    } 

    ....
}


In the first example you're not actually inheriting from two classes, but from one class and an interface.

C# doesn't allow multiple inheritance from classes, but does allow you to implement multiple interfaces. See this MSDN blog post (link is dead so text is pasted below) for more information on why.

You will have to make an IMembershipUser interface and implement that in your User class.

Interfaces are usually given names based on the concrete class name prefixed by an I. So the class MembershipUser would have an interface IMembershipUser. There's nothing stopping you using some other name, but everyone who uses interfaces is used to this naming convention.

There are a number of reasons we don’t implement Multiple Implementation Inheritance directly. (As you know, we support Multiple Interface Inheritance).

However, I should point out that it’s possible for compilers to create MI for their types inside the CLR. There are a few rough edges if you go down this path: the result is unverifiable, there is no interop with other languages via the CLS, and in V1 and V1.1 you may run into deadlocks with the OS loader lock. (We’re fixing that last problem, but the first two problems remain). The technique is to generate some VTables in RVA-based static fields. In order to deposit the addresses of managed methods (which probably haven’t been JITted yet), you use the VTFixup construct. This construct is a table of triplets. The triplets consist of a token to a managed method, an address in your image that should be fixed up (in this case, a slot of the VTable you are creating in the RVA-based static), and some flags. The possible flags are described in corhdr.h and they allow you to specify 32- vs. 64-bit pointer sizes, control over virtual behavior, and whether some reverse-PInvoke behavior should be applied in the form of a thunk that eventually dispatches to the managed method. If we are performing an unmanaged->managed transition, you also have some control over which AppDomain should be selected for us to dispatch the call. However, one of these options (COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN) doesn’t exist in V1. We added it in V1.1.

There are several reasons we haven’t provided a baked-in, verifiable, CLS-compliant version of multiple implementation inheritance:

  1. Different languages actually have different expectations for how MI works. For example, how conflicts are resolved and whether duplicate bases are merged or redundant. Before we can implement MI in the CLR, we have to do a survey of all the languages, figure out the common concepts, and decide how to express them in a language-neutral manner. We would also have to decide whether MI belongs in the CLS and what this would mean for languages that don’t want this concept (presumably VB.NET, for example). Of course, that’s the business we are in as a common language runtime, but we haven’t got around to doing it for MI yet.

  2. The number of places where MI is truly appropriate is actually quite small. In many cases, multiple interface inheritance can get the job done instead. In other cases, you may be able to use encapsulation and delegation. If we were to add a slightly different construct, like mixins, would that actually be more powerful?

  3. Multiple implementation inheritance injects a lot of complexity into the implementation. This complexity impacts casting, layout, dispatch, field access, serialization, identity comparisons, verifiability, reflection, generics, and probably lots of other places.

It’s not at all clear that this feature would pay for itself. It’s something we are often asked about. It’s something we haven’t done due diligence on. But my gut tells me that, after we’ve done a deep examination, we’ll still decide to leave the feature unimplemented.


in c# you just can inherit from one class, but implement as many interfaces as you want. in your case ProfileBase and MembershipUser are classes and ISessionMgrEntry is an interface.


C# only supports single inheritance. You can either chain together your classes (i.e. MembershipUser inherits from ProfileBase) or use interfaces.


C# does not allow multiple inheritance.


C# doesn't support multiple inheritance.

In the first example you are inheriting from ProfileBase and declaring your class to be implementing the ISessionMgrEntry interface.

You can add as many interfaces to a class as you want (provided you implement them all).


C# only allows single inheritance: you can only inherit from one base class. In the first case ISessionMgrEntry is an interface which is different from a base class. Here's a good article on the difference: http://msdn.microsoft.com/en-us/library/ms973861.aspx

In the second case you are trying to inherit from both ProfileBase and MembershipUser, which the compiler won't allow. The best way to get around this would be to encapsulate one (or both) of ProfileBase and MembershipUser.


Multiple interfaces with identical member names are not a problem. If the members can share the same implementation, just create a public member with the same name; if they can't share the same implementation, you can just explicitly implement one (or all) of the members.

For example, IEnumerable<T> inherits IEnumerable, and both provide a GetEnumerator() method with differing return types. Consequently, IEnumerable.GetEnumerator() is generally explicitly implemented:

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

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

Calling GetEnumerator() in IEnumerable.GetEnumerator() isn't an infinitely recursive call; it calls the public member of the same name, not itself (i.e. the IEnumerable.GetEnumerator() method).


Multiple inheritance can be achieved with interfaces. Example Derived has to inherit from Base1, Base2 and 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; 
}
0

精彩评论

暂无评论...
验证码 换一张
取 消