-1

I have need for nesting Generics, as in A< B< Base > > .

When I do this, only the outer properties (A) are exposed. I can not figure out how to access (B)'s methods, etc. I then tried to access the interfaces internally with the same results.

(edit) To clarify the use case, the solution I need should work with public class C : A < B < Base > > or public class C : B < A < Base > > I don't need those to result in identical classes, but both definitions have the corresponding methods. As you might suspect, I am trying to use this to implement common functionality in a modular mode across several objects. Extension methods get me close, but they won't allow overridden behavior as this solution would (if it is achievable).

I have attached test code, which shows the problems perhaps more clearly than I ca.

using System;
using System.Reflection;

namespace ArchitecturalTestGround
{
    public interface IBase
    {
        void BaseMethod1();
    }
    public interface IA : IBase
    {
        void AMethod();
    }
    public interface IB : IBase
    {
        void BMethod();
    }
    public class Base : IBase
    {
        public void BaseMethod1() { }
    }
    public class A<T> : IA where T : IBase
    {
        public void BaseMethod1() { }
        public void AMethod() { }
    }
    public class B<T> : IB where T : IBase
    {
        public void BaseMethod1() { }
        public void BMethod() { }
    }
    public class Test1 : A<B<Base>>
    {
    }

    public class Test2 : B<A<Base>>
    {
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            Test1 e1 = new Test1();
            Test2 e2 = new Test2();


            Console.WriteLine("Test1 - A<B<Base>>");
            foreach (MemberInfo mi in typeof(Test1).GetMembers())
            {
                Console.WriteLine($"  {mi.Name}.{mi.MemberType}");
            }
            if (e1 is IB) { Console.WriteLine("   Supports IB"); }
            if (e1 is IA) { Console.WriteLine("   Supports IA"); }

            Console.WriteLine();
            Console.WriteLine("Test2 - B<A<Base>>");
            foreach (MemberInfo mi in typeof(Test2).GetMembers())
            {
                Console.WriteLine($"  {mi.Name}.{mi.MemberType}");
            }
            if (e2 is IB) { Console.WriteLine("   Supports IB"); }
            if (e2 is IA) { Console.WriteLine("   Supports IA"); }

            Console.ReadKey();
        }
    }
}
cyriously
  • 1
  • 1

2 Answers2

0

Test1 is inheriting from A<T> (regardless of what T is) and A<T> inherits from from IA, which in turn inherits from IBase, so you will only see the methods from that inheritance chain:

From A<T>:

public void BaseMethod1() { }
public void AMethod() { }

From IA:

void AMethod();

From IBase:

void BaseMethod1();

(By the way, notice from your code sample that you would probably get a compiler warning because of BaseMethod1).

I think I see where you are going with this. You have probably encountered a situation where you need to inherit from two classes. Multiple class inheritance is not possible in C#. There are some ways around it though.

Generally speaking, if you encounter a situation like this, more times than not it means you need to rethink your design. If you are still interested on the subject, check this guy out:

Multiple Inheritance in C#

Community
  • 1
  • 1
JuanR
  • 7,405
  • 1
  • 19
  • 30
  • You are correct in where I am going! I added some comments to my question to help explain that more. However, I am not convinced that multiple inheritance is always bad. It is powerful and can be misused, but that doesn't necessarily make it inappropriate in all situations. (obvious cliche avoided.) – cyriously Apr 28 '17 at 16:33
  • I didn't say it was bad. I just said most of the time. :-) – JuanR May 01 '17 at 13:39
  • By the way @cyriously, you are misunderstanding generics. Having a generic type with the other class type will only help you create a template where you can use that type but it won't merge the definition into your base class. That is, unless you decide to use an internal instance to forward calls to. – JuanR May 01 '17 at 13:41
  • Juan - criticism accepted. It is partly that I am misunderstanding, and partly that I don't to accept it as the truth without a workaround. :-) – cyriously May 02 '17 at 00:08
0

Is it possible to change your definitions like this?

public class A<T> : IA where T : IBase
{
    T NestedGeneric;

    public A(T nested)
    {
        NestedGeneric = nested;
    }

    public void BaseMethod1() { }

    public void AMethod() { }
}


public class Test1 : A<B<Base>>
{
    public B<Base> NestedGeneric;
    public Test1(B<Base> nested) : base(nested)
    {
        NestedGeneric = nested;
    }
}

This allows you do do e1.NestedGeneric.BMethod();.

HaveSpacesuit
  • 3,572
  • 6
  • 40
  • 59
  • Good idea, and one I also tested. However, this won't get me there. I added some comments above to clarify my intent. – cyriously Apr 28 '17 at 16:37