c# - 试图继承三个基类而不能

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

    ....
}

最佳答案

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

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

您必须创建一个IMembershipUser 接口(interface)并在您的User 类中实现它。

接口(interface)的命名通常基于具体的类名,前缀为I。所以 MembershipUser 类将有一个接口(interface) IMembershipUser。没有什么可以阻止您使用其他名称,但每个使用接口(interface)的人都习惯了这种命名约定。

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.

关于c# - 试图继承三个基类而不能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2201058/

相关文章:

c# - 在 finally 中进行 try/catch 可以吗?

c# - 如何添加对 C# 脚本的引用

java - 如何在java中使用父亲的方法和儿子的变量?

c++ - 虚基类是如何存储的?

java - 如何在 java 中使用扩展相同但具有不同通用参数的接口(interface)扩展 2?

c++ - 多重继承类引用

c# - WCF : This message cannot support the operation because it has been copied

c# - 更改部分类中的 LINQ2SQL 属性?

php - 使用 PhpDoc 记录 PHP 多重继承

c# - 我应该共享使用公共(public)字段的对象的 UI 吗?