1

Possible Duplicate:
Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?
Generic class that inherits its generic type

I would like to be able to do something like this, only in C#:

template<class MyClass>
class MockComposite : MyClass
{

};

The class above inherits from the specified type. MyClass is a base type, and this is the reason I want this behaviour. I want to be able to instantiate this object with classes derived from MyClass.

I understand you cannot use templates in C#, but is there any way to get the behaviour I want without having to write a new class for each different type of object?

EDIT - I want to be able to instantiate an object that will test the behaviour of any class, as long as that class is derived from a specified type - 'MyClass'.

Community
  • 1
  • 1
Dollarslice
  • 9,917
  • 22
  • 59
  • 87

2 Answers2

1

In C# you have the concept of generics. The following code is equivalent to your C++ code:

class MockComposite<T> : T
    where T : MyClass
{
}

Unfortunatelly, it is invalid. You will get the following compile error:

Cannot derive from 'T' because it is a type parameter

In C# you would usually solve this problem with composition instead of inheritance.

Composition in this case means one of two things:

  1. Your class still has the generic argument but doesn't try to derive from it. Furthermore, it has the new constraint, meaning that the generic argument needs to have a default constructor:

    class MockComposite<T>
        where T : MyClass, new()
    {
        T _toTest;
    
        public MockComposite()
        {
            _toTest = new T();
        }
    }
    

    This means you can instantiate the mock class like this: var mock = new MockComposite<ClassA>(); without the need for creating an instance of ClassA outside of the mock class.

    class MockComposite
    {
        MyClass _toTest;
    
        public MockComposite(MyClass toTest)
        {
            _toTest = toTest;
        }
    }
    

    This means you have to instantiate the mock class like this: var mock = new MockComposite(new ClassA());

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • @exacerbatedexpert: Maybe you want to read the whole answer. The C++ code translated to C# generic syntax is the code I posted. BTW: 2 downvotes? Do you have multiple accounts? – Daniel Hilgarth Aug 28 '12 at 15:15
0

This is simply not possible in C#. But this is a case of trying to use one language as another, different, language. In C++ this pattern has its uses. You can accomplish the same things in C#, but using different techniques.

Maybe this will help you:

class Myclass
{
}

class ChildClass : MyClass
{
}

class MockComposite<T> where T : MyClass
{
    public MockComposite(T objectToTest) { ... }
}

Here, you can pass a any class that derives from MyClass into CompositeTester<>. The biggest difference between this and your code is that here you need to pass in real existing non-generic classes that inherit MyClass. You are trying to inherit generically which is not possible.

In C++ this is basically like doing:

class Myclass
{
};

class ChildClass : MyClass
{
};

template<typename T>
class MockComposite
{
public:
    MockComposite(const T& objectToTest) { ... }
};

C# generics might look a bit like C++ templates but it's an entirely different idea. While C++ templates let you do be very flexible almost to the point of being like macros, generics remain rather tight, type-wise. You cannot do anything with a generic type that you have not said it can do explicitly, hence generic constraints like where T : MyClass. By specifying that, MockComposite.MockComposite can use T as a MyType.

tenfour
  • 36,141
  • 15
  • 83
  • 142
  • I want to be able to write an object with generic testing behaviour that I can use to test any object that is derived from one specific base-class object. – Dollarslice Aug 28 '12 at 14:58
  • @SirYakalot: And why does this testing class need to derive from the class that needs to be tested? – Daniel Hilgarth Aug 28 '12 at 15:01
  • I suppose it could be written in an entirely different way. I'm converting some code and was wondering if there was an equivalent. – Dollarslice Aug 28 '12 at 15:02
  • @SirYakalot: See [my answer](http://stackoverflow.com/a/12162023/572644). Most likely, you will want to use composition. – Daniel Hilgarth Aug 28 '12 at 15:04