generics + inheritance

R

Richard Friend

Does anyone know how to get round this problem?

using System;
using System.Collections.Generic;
using System.Text;

namespace ClassLibrary1
{
public class BaseClass
{
public int counter = 0;
}
public class GenericClass<T> : BaseClass where T : BaseClass,new()
{
public T IncrementCounterAndCopy()
{
T t = new T();
t.counter = this.counter+1;
return t;
}
}
public class TestClass1 : GenericClass<TestClass1>
{
}
public class TestClass2 : TestClass1
{
}

public class TestIt
{
public void x()
{
//works ok
TestClass1 t1 = new TestClass1();
TestClass1 t2 = t1.IncrementCounterAndCopy();


TestClass2 tt1 = new TestClass2();
//How can i ensure the return type is of the actual type of my
class
//WITHOUT making all classes in the chain also generic...?
//Possible??
TestClass2 tt2 = t1.IncrementCounterAndCopy(); //compiler error
here...
}
}
}
 
N

Nicholas Paldino [.NET/C# MVP]

Richard,

I'm not sure what you are getting at. The return type of
t1.IncrementCounterAndCopy is TestClass1, which you can't assign to tt2,
which is TestClass2.

Now, I am assuming you are trying to do something like you want
TestClass2 to inherit from TestClass1, and you want the type parameter
passed to GenericClass in that inheritance chain to be TestClass2.

Unfortunately, the only way to do this is, as you said, to place a type
parameter in each level of the inheritance chain, and pass the type all the
way down.
 
R

Richard Friend

Hi

Thanks for the prompt response.

I feared this was the answer, i just mocked up a quick example of a more
complex problem im having.

This is a quick mock of what some existing code i have looks like


public class User : DataBoundComponent<User>
{
}

i then extend that class
public class SpecialUser : User
{
}

How can i ensure that the generic underlying class for SpecialUser gets my
new type 'specializeduser' rather than the base class type?

This is due to my delegates being generic also, in the DataBoundComponent i
have this

public event EventHandler<DataBoundComponentCreatedEventArgs<T>>
ItemCreated;

now when i try to wire a delegate like so

specialuser.ItemCreated =delegate(object
sender,DataBoundComponentCreatedEventArgs<SpecialUser> e)
{
e.Item.Apps =
Applications.SelectApplications(e.Item.FaceBookProfileId);
});

obviously the underlying DataBoundComponents generic type is User not
specialUser so the event args do not match up...

Since im unable to change the User class, im just going to have to create
SpecialUser from the generic class and duplicate all the existing code in
the user class, grrrrrrr

Nicholas Paldino said:
Richard,

I'm not sure what you are getting at. The return type of
t1.IncrementCounterAndCopy is TestClass1, which you can't assign to tt2,
which is TestClass2.

Now, I am assuming you are trying to do something like you want
TestClass2 to inherit from TestClass1, and you want the type parameter
passed to GenericClass in that inheritance chain to be TestClass2.

Unfortunately, the only way to do this is, as you said, to place a type
parameter in each level of the inheritance chain, and pass the type all
the way down.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Richard Friend said:
Does anyone know how to get round this problem?

using System;
using System.Collections.Generic;
using System.Text;

namespace ClassLibrary1
{
public class BaseClass
{
public int counter = 0;
}
public class GenericClass<T> : BaseClass where T : BaseClass,new()
{
public T IncrementCounterAndCopy()
{
T t = new T();
t.counter = this.counter+1;
return t;
}
}
public class TestClass1 : GenericClass<TestClass1>
{
}
public class TestClass2 : TestClass1
{
}

public class TestIt
{
public void x()
{
//works ok
TestClass1 t1 = new TestClass1();
TestClass1 t2 = t1.IncrementCounterAndCopy();


TestClass2 tt1 = new TestClass2();
//How can i ensure the return type is of the actual type of my
class
//WITHOUT making all classes in the chain also generic...?
//Possible??
TestClass2 tt2 = t1.IncrementCounterAndCopy(); //compiler
error here...
}
}
}
 
R

Richard Friend

Well im just going to create my SpecialUser class with its new properties
and create a property to reference the instance of the user class.

But wouldn't it be possible for c# to have some sort of keyword for this,
its not like the compiler doesnt know the type of the concrete class since
its clearly throwing a compiler error already...

something like (pseudo)

class GenericClass<T> where T : new()
{
public T t = new T();
}
class MyClass : GenericClass<mytype>
{

}
class MyClass2 : MyClass
{
}
MyClass x = new MyClass();
MyClass2 y = new MyClass2();

x.t.GetType() would be MyClass
y.t.GetType() would be MyClass2



That would be pretty awsome.
 
N

Nicholas Paldino [.NET/C# MVP]

Richard,

I can't say I've had a use for such a thing, but I can see where it
would be useful. Unfortunately, you can get around it easily now by adding
a type parameter to your derived classes. That's ultimately what would keep
it from being made into a language feature (the ease with which you can
implement this using the current language features).
 
B

Ben Voigt [C++ MVP]

Richard Friend said:
Hi

Thanks for the prompt response.

I feared this was the answer, i just mocked up a quick example of a more
complex problem im having.

This is a quick mock of what some existing code i have looks like


public class User : DataBoundComponent<User>
{
}

i then extend that class
public class SpecialUser : User
{
}

How can i ensure that the generic underlying class for SpecialUser gets my
new type 'specializeduser' rather than the base class type?

You can't, because then User would no longer be a superclass of SpecialUser
in the general case. Only when the type argument is limited to
contravariant usage would such a thing be possible even theoretically.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top