Click here to Skip to main content
15,888,610 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

As a long-time C++ programmer, I am always on the lookout for the dangers of the inheritance diamond (possible in C++ because it allows multiple inheritance).

In my current C# program, I have just discovered I am doing the same thing but using interfaces, and I am wondering if it is functionally okay? Is it a bad practise, and if it is, how should I be looking to re-factor it?

This complete program shows an example of what I mean:

C#
using System;

namespace ConsoleApplication1
{
	public interface IBaseService
	{
		int X { get; }
	}

	public interface ISpecificService : IBaseService
	{
		int Y { get; }
	}

	public abstract class ServiceBase : IBaseService
	{
		public int X { get { return 42; } }
	}

	public class ConcreteClass : ServiceBase, ISpecificService
	{
		public int Y { get { return 43; } }
	}

	class Program
	{
		static void Main( string[] args )
		{
			ConcreteClass c = new ConcreteClass();
			Console.WriteLine( $"X={c.X.ToString()}, Y={c.Y.ToString()}" );
			Console.ReadKey();
		}
	}
}


Output is: 'X=42, Y=43'.

Any advice or pointers to useful articles would be very much appreciated.

To give a bit more detail about the real-world situation, I have the following:

I have an IBaseService, which is the core contract that all my services must implement. No 'base-class' implementation is possible for these functions and hence it needs to be an interface.

I have specific services, which must implement the core contract but also add their own requirements to the contract. Once again, no 'base-class' implementation of these is possible, so these specific services also need to be interfaces.

I also would like to have a home for some other functionality that does have a 'base-class' concrete implementation, and so I have an abstract ServiceBase for this code.

Any concrete service thus gets the benefit of the concrete common code from the ServiceBase but then has to implement the contract dictated by the chain of interfaces it also inherits.

It all seems quite logical, and I struggle to see which bits I could do differently without reducing the chance that a new programmer (or me in a week's time) might come along and write a new service that doesn't fulfil all of its obligations and can take advantage of common code.

It's easier to code than explain. Hope this makes sense.

Kind wishes ~ Patrick

What I have tried:

I've tried the code above, obviously, which works fine. Guess I am more bothered about something being seriously wrong with the design.
Posted
Updated 14-Mar-16 5:51am
v2
Comments
glen205 14-Mar-16 9:03am    
I'm not sure you have a true "inheritance diamond" problem here, because your ConcreteClass isn't "inheriting" from two abstract bases, it's inheriting from one abstract and implementing one interface.

The "inheritance diamond" problem comes when two competing implementations are inherited and it's impossible to tell which one the derived class should inherit - you don't have that here because only one "side" of the diamond has an implementation....

... I think!
Patrick Skelton 14-Mar-16 9:17am    
That's pretty much what I thought. Maybe it just looks strange to me BECAUSE I come from a C++ background.
johannesnestler 14-Mar-16 11:07am    
you are technically IMPLEMENTING interfaces in C# and not INHERITING them, so just forget about your "inner C++ Alarm bells", this problem doesn't apply to C#, cause no real multiple inheritance is possible. - sure, in an example like Kornfeld Eliyahu Peter showed you may get the impression you are "inheriting" because of the syntax used to express that a specific class fullfills an interface. If the interfaces would have conflicting methods/member names you can use explicit Interface implementation to avoid that conflicts...
Patrick Skelton 14-Mar-16 11:33am    
Thank you for the explanation.

1 solution

It is impossible to get some 'pure' diamond inheritance in C# (no multiple inheritence), but you can get smething like this:
C#
interface IA
{
  void MethodA();
}

interface IB : IA
{
  void MethodB();
}

interface IC : IA
{
  void MethodC();
}

class D : IB, IC
{
  public void MethodA()
  {
    //
  }

  public void MethodB()
  {
    //
  }

  public void MethodC()
  {
    //
  }
}


As for the good-or-bad part...It is hard to tell as we do not know why you got there...It does not look too good in your sample, but in real life it can be justified easily...For sure, you can relax, C# will not let you do something that bad as multiply inheritence :-)...
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900