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

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

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

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

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

其他回答

Multiple inheritance is one of those things that generally causes more problems than it solves. In C++ it fits the pattern of giving you enough rope to hang yourself, but Java and C# have chosen to go the safer route of not giving you the option. The biggest problem is what to do if you inherit multiple classes that have a method with the same signature that the inheritee doesn't implement. Which class's method should it choose? Or should that not compile? There is generally another way to implement most things that doesn't rely on multiple inheritance.

如果你可以接受IFirst和ISecond的方法只能与IFirst和ISecond的契约交互的限制(就像你的例子一样)……你可以用扩展方法做你想做的事情。在实践中,这种情况很少发生。

public interface IFirst {}
public interface ISecond {}

public class FirstAndSecond : IFirst, ISecond
{
}

public static MultipleInheritenceExtensions
{
  public static void First(this IFirst theFirst)
  {
    Console.WriteLine("First");
  }

  public static void Second(this ISecond theSecond)
  {
    Console.WriteLine("Second");
  }
}

///

public void Test()
{
  FirstAndSecond fas = new FirstAndSecond();
  fas.First();
  fas.Second();
}

因此,基本思想是在接口中定义所需的实现……这个需要的东西应该支持扩展方法中的灵活实现。当你需要“向接口添加方法”时,你可以添加一个扩展方法。

是的,使用接口是一个麻烦,因为每当我们在类中添加方法时,我们都必须在接口中添加签名。此外,如果我们已经有一个类有一堆方法,但没有接口怎么办?我们必须手动为所有想要继承的类创建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可以访问父类和母类的所有方法和属性,模拟多重继承,继承父类的实例。不完全一样,但很实用。

在c# 8中,你实际上可以通过接口成员的默认实现来实现多重继承:

interface ILogger
{
    void Log(LogLevel level, string message);
    void Log(Exception ex) => Log(LogLevel.Error, ex.ToString()); // New overload
}

class ConsoleLogger : ILogger
{
    public void Log(LogLevel level, string message) { ... }
    // Log(Exception) gets default implementation
}

考虑只使用组合而不是尝试模拟多重继承。你可以使用接口来定义组成组合的类,例如:isteable暗示了方向盘类型的属性,IBrakable暗示了BrakePedal类型的属性,等等。

一旦你完成了这些,你可以使用c# 3.0中添加的扩展方法功能来进一步简化对这些隐含属性的方法调用,例如:

public interface ISteerable { SteeringWheel wheel { get; set; } }

public interface IBrakable { BrakePedal brake { get; set; } }

public class Vehicle : ISteerable, IBrakable
{
    public SteeringWheel wheel { get; set; }

    public BrakePedal brake { get; set; }

    public Vehicle() { wheel = new SteeringWheel(); brake = new BrakePedal(); }
}

public static class SteeringExtensions
{
    public static void SteerLeft(this ISteerable vehicle)
    {
        vehicle.wheel.SteerLeft();
    }
}

public static class BrakeExtensions
{
    public static void Stop(this IBrakable vehicle)
    {
        vehicle.brake.ApplyUntilStop();
    }
}


public class Main
{
    Vehicle myCar = new Vehicle();

    public void main()
    {
        myCar.SteerLeft();
        myCar.Stop();
    }
}