由于多重继承是不好的(它使源代码更加复杂),c#没有直接提供这样的模式。但有时候拥有这种能力是有帮助的。

例如,我能够使用接口和三个类实现缺少的多重继承模式:

public interface IFirst { void FirstMethod(); }
public interface ISecond { void SecondMethod(); }

public class First:IFirst 
{ 
    public void FirstMethod() { Console.WriteLine("First"); } 
}

public class Second:ISecond 
{ 
    public void SecondMethod() { Console.WriteLine("Second"); } 
}

public class FirstAndSecond: IFirst, ISecond
{
    First first = new First();
    Second second = new Second();
    public void FirstMethod() { first.FirstMethod(); }
    public void SecondMethod() { second.SecondMethod(); }
}

每当我向其中一个接口添加方法时,我也需要更改类FirstAndSecond。

是否有一种方法可以像在c++中那样将多个现有类注入到一个新类中?

也许有一种使用某种代码生成的解决方案?

或者它看起来像这样(虚构的c#语法):

public class FirstAndSecond: IFirst from First, ISecond from Second
{ }

这样,当我修改其中一个接口时,就不需要更新类FirstAndSecond。


EDIT

也许考虑一个实际的例子会更好:

您有一个现有的类(例如,基于ITextTcpClient的基于文本的TCP客户端),您已经在项目中的不同位置使用它。现在,您觉得有必要创建一个类的组件,以便windows窗体开发人员可以轻松访问。

据我所知,你目前有两种方法来做到这一点:

编写一个从组件继承的新类,并使用类本身的实例实现TextTcpClient类的接口,如FirstAndSecond所示。 编写一个继承TextTcpClient的新类,并以某种方式实现IComponent(实际上还没有尝试过这个)。

在这两种情况下,您都需要为每个方法而不是每个类做工作。因为你知道我们将需要TextTcpClient和Component的所有方法,所以将这两个方法合并到一个类中是最简单的解决方案。

为了避免冲突,这可以通过代码生成来完成,结果可以在之后修改,但手动输入这是一个纯粹的痛苦。


当前回答

我创建了一个c#后编译器来实现这类事情:

using NRoles;

public interface IFirst { void FirstMethod(); }
public interface ISecond { void SecondMethod(); }

public class RFirst : IFirst, Role {
  public void FirstMethod() { Console.WriteLine("First"); }
}

public class RSecond : ISecond, Role {
  public void SecondMethod() { Console.WriteLine("Second"); }
}

public class FirstAndSecond : Does<RFirst>, Does<RSecond> { }

你可以将后编译器作为Visual Studio post-build-event运行:

C: \ some_path \ nroles-v0.1.0-bin \ nutate.exe " $(定位路径)"

在同一个程序集中,你可以这样使用它:

var fas = new FirstAndSecond();
fas.As<RFirst>().FirstMethod();
fas.As<RSecond>().SecondMethod();

在另一个程序集中,你像这样使用它:

var fas = new FirstAndSecond();
fas.FirstMethod();
fas.SecondMethod();

其他回答

我创建了一个c#后编译器来实现这类事情:

using NRoles;

public interface IFirst { void FirstMethod(); }
public interface ISecond { void SecondMethod(); }

public class RFirst : IFirst, Role {
  public void FirstMethod() { Console.WriteLine("First"); }
}

public class RSecond : ISecond, Role {
  public void SecondMethod() { Console.WriteLine("Second"); }
}

public class FirstAndSecond : Does<RFirst>, Does<RSecond> { }

你可以将后编译器作为Visual Studio post-build-event运行:

C: \ some_path \ nroles-v0.1.0-bin \ nutate.exe " $(定位路径)"

在同一个程序集中,你可以这样使用它:

var fas = new FirstAndSecond();
fas.As<RFirst>().FirstMethod();
fas.As<RSecond>().SecondMethod();

在另一个程序集中,你像这样使用它:

var fas = new FirstAndSecond();
fas.FirstMethod();
fas.SecondMethod();

是的,使用接口是一个麻烦,因为每当我们在类中添加方法时,我们都必须在接口中添加签名。此外,如果我们已经有一个类有一堆方法,但没有接口怎么办?我们必须手动为所有想要继承的类创建Interface。最糟糕的是,如果子类要从多个接口继承,我们必须在子类中实现接口中的所有方法。

通过遵循Facade设计模式,我们可以使用访问器模拟从多个类继承。在类内部使用{get;set;}将类声明为需要继承的属性,所有公共属性和方法都来自该类,并在子类的构造函数中实例化父类。

例如:

 namespace OOP
 {
     class Program
     {
         static void Main(string[] args)
         {
             Child somechild = new Child();
             somechild.DoHomeWork();
             somechild.CheckingAround();
             Console.ReadLine();
         }
     }

     public class Father 
     {
         public Father() { }
         public void Work()
         {
             Console.WriteLine("working...");
         }
         public void Moonlight()
         {
             Console.WriteLine("moonlighting...");
         }
     }


     public class Mother 
     {
         public Mother() { }
         public void Cook()
         {
             Console.WriteLine("cooking...");
         }
         public void Clean()
         {
             Console.WriteLine("cleaning...");
         }
     }


     public class Child 
     {
         public Father MyFather { get; set; }
         public Mother MyMother { get; set; }

         public Child()
         {
             MyFather = new Father();
             MyMother = new Mother();
         }

         public void GoToSchool()
         {
             Console.WriteLine("go to school...");
         }
         public void DoHomeWork()
         {
             Console.WriteLine("doing homework...");
         }
         public void CheckingAround()
         {
             MyFather.Work();
             MyMother.Cook();
         }
     }


 }

有了这个结构,类Child可以访问父类和母类的所有方法和属性,模拟多重继承,继承父类的实例。不完全一样,但很实用。

您可以有一个实现IFirst和ISecond的抽象基类,然后从该基类继承。

如果X继承了Y,这有两个正交的效果:

Y将为X提供默认功能,因此X的代码只需要包含与Y不同的东西。 几乎在任何需要用Y的地方,都可以用X代替。

Although inheritance provides for both features, it is not hard to imagine circumstances where either could be of use without the other. No .net language I know of has a direct way of implementing the first without the second, though one could obtain such functionality by defining a base class which is never used directly, and having one or more classes that inherit directly from it without adding anything new (such classes could share all their code, but would not be substitutable for each other). Any CLR-compliant language, however, will allow the use of interfaces which provide the second feature of interfaces (substitutability) without the first (member reuse).

由于多重继承是不好的(它使源代码更加复杂),c#没有直接提供这样的模式。但有时候拥有这种能力是有帮助的。

c#和。net CLR还没有实现MI,因为他们还没有总结出它将如何在c#、VB.net和其他语言之间互操作,而不是因为“这会使源代码更复杂”。

MI是一个有用的概念,未回答的问题是:“当你在不同的超类中有多个公共基类时,你该怎么办?”

Perl是我使用过的唯一一种MI可以很好地工作的语言。. net可能有一天会引入它,但现在还没有,CLR已经支持MI,但正如我所说的,目前还没有针对它的语言结构。

在此之前,你会被代理对象和多个接口所困扰:(