我有一些与我的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; }
}
....
}
答案 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的多实现继承版本:
不同的语言实际上对MI的工作方式有不同的期望。例如,如何解决冲突以及是否重复 基地合并或冗余。在我们在CLR中实现MI之前, 我们必须对所有语言进行调查,找出共同点 概念,并决定如何以语言中立的方式表达它们。 我们还必须决定MI是否属于CLS以及什么 这对于不想要这个概念的语言来说意味着(大概是这样) 例如VB.NET)。当然,这就是我们所处的业务 公共语言运行时,但我们还没有为MI做这件事 爱好。
MI真正适合的地方实际上非常小。在许多情况下,多个接口继承可以获得 完成工作。在其他情况下,您可以使用封装 和代表团。如果我们要添加一个稍微不同的结构,比如 mixins,实际上会更强大吗?
- 醇>
多个实现继承为实现注入了很多复杂性。这种复杂性影响了铸造,布局, 调度,现场访问,序列化,身份比较, 可验证性,反思,泛型,可能还有很多其他的 地方。
这个功能本身并不清楚。它的 我们经常被问到的事情。这是我们尚未完成的事情 勤奋。但是我的直觉告诉我,在我们做了很深的事情之后 检查时,我们仍然会决定不使用该功能。
答案 1 :(得分:6)
在c#中你可以继承一个类,但可以实现任意数量的接口。
在您的情况下,ProfileBase
和MembershipUser
是类,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
在第二种情况下,您尝试从ProfileBase
和MembershipUser
继承,编译器将不允许这两种情况。解决这个问题的最佳方法是封装ProfileBase
和MembershipUser
中的一个(或两个)。
答案 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;
}