3

is something like this possible in C#?

Suppose that I have this:

public class T : U
{
 ...
}

and I want this:

public class A<T> : B<U>
{
...
}

so that I can have this in my code:

B<U> x = new A<T>();
jambodev
  • 351
  • 2
  • 3
  • 9

3 Answers3

2

You can't have it exactly like you write it, but you can do this:

public class A<T, U> : B<U> where T : U
{
   ...
}

and then do

B<U> x = new A<T, U>();
Roy Dictus
  • 32,551
  • 8
  • 60
  • 76
  • He can have it exactly as he wrote it, it just might not mean what he wanted it to. But he can have exactly what he typed for as valid C# if he wants. :) – Chris Feb 21 '12 at 16:22
  • OK, what I wrote was not exactly what I meant :) – jambodev Feb 22 '12 at 08:17
1

That initial code does work fine... Though there is possibly some confusion due to the terms you have used...

I believe the code you have written could be rewritten more clearly as follows:

void Main()
{
    B<Foobar> x = new A<Wibble>();

}

// Define other methods and classes here
public class Foobar
{
}

public class Wibble : Foobar
{
}

public class B<U>
{
}

public class A<T> : B<Foobar>
{
}

The key thing to note is that sometimes you were using U in the context of a generic parameter and sometimes you were using it as a concrete class.

The above code is equivalent (in terms of the IL that LINQPad compiles it to) to:

void Main()
{
    B<U> x = new A<T>();

}

// Define other methods and classes here
public class U
{
}

public class T : U
{
}

public class B<U>
{
}

public class A<T> : B<U>
{
}

Only the last two classes use generic parameters and the last class doesn't have U defined as a generic parameter so it treats it as the concrete class. It is hard to say whether this is what you want or not since you haven't told us what you want, just shown us some code. I think probably you want the two generic parameter solution as answered by @Roy Dictus but you may want this. Its hard to say. ;-)

I should note that I credit this answer in part to a previous answer that was deleted. That answer pointed out that the code compiles fine which inspired me to test the actual code. Sadly with the answer deleted I can't credit the person in question for the inspiration.

Thank you all. Chris this solves my problem provided that I be able to call constructor of T in constructor of A<T> below: public class A<T> : B<Foobar> { } How can I do that? – jambodev 1 min ago

In this case T is a generic parameter so you have to tell the compiler that T is definitely constructable. To do this you need to constrain T to ensure that it has a constructor. Then you should be able to create new instances of it whenever you want (eg T foo = new T();

You cannot of course call the constuctor in the same way you would chain the constructor of a base class since A does not derive from T in any way, it just uses objects of type T in its generic patterns.

public class A<T> : B<Foobar> where T :new()
{
    public T MyInstance {get; set;}
    public A()
    {
        MyInstance = new T();
    }
}

void Main()
{
    B<Foobar> x = new A<Wibble>();
    Wibble y = ((A<Wibble>)x).MyInstance;
}

(this code replaces the equivalent methods from my first code block)

Note that y is an object of type Wibble that was created in the conscructor of x. Note also that I needed to cast x before accessing it because B<Foobar> knows nothing about the use of the generic type Wibble.

Chris
  • 27,210
  • 6
  • 71
  • 92
  • Thank you all. Chris this solves my problem provided that I be able to call constructor of T in constructor of A below: public class A : B { } How can I do that? – jambodev Feb 21 '12 at 17:32
0

It isn't entirely clear what you to do (the class names don't help, my brain was struggling with class T). Is Roy Dictus' answer what you want, or perhaps Chris' answer was what you are looking for? I interpreted the question in a different way from either of the former, like this

    public class MyBaseClass  {}

    public class MyClass : MyBaseClass {}

    interface IB<out T>{}

    public class B<T> : IB<T> { }

    public class A<T> : B<T>   {}

    static void Main(string[] args)
    {
        IB<MyBaseClass> myVar = new A<MyClass>();
    }

The key being that interfaces support covariance, classes do not.

Community
  • 1
  • 1
Myles McDonnell
  • 12,943
  • 17
  • 66
  • 116