Generics Casting [modified]
-
Am I missing something, or the example below is really impossible. The class called
FirstImplementation
derives fromGenericClass
, and the generic parameter used,FirstClass
derives fromBase
. So from the outside I should be able to castFirstImplementation
toGenericClass
public class Base { public int X { get; set; } } public class FirstClass : Base { public int Y { get; set; } } public abstract class GenericClass<T> where T: Base { public T Item { get; set;} } public class FirstImplementation : GenericClass<FirstClass> { public GenericClass<Base> Cast() { return (GenericClass<Base> )this; // --> doesn't work } }
modified on Thursday, January 15, 2009 6:18 AM
-
Am I missing something, or the example below is really impossible. The class called
FirstImplementation
derives fromGenericClass
, and the generic parameter used,FirstClass
derives fromBase
. So from the outside I should be able to castFirstImplementation
toGenericClass
public class Base { public int X { get; set; } } public class FirstClass : Base { public int Y { get; set; } } public abstract class GenericClass<T> where T: Base { public T Item { get; set;} } public class FirstImplementation : GenericClass<FirstClass> { public GenericClass<Base> Cast() { return (GenericClass<Base> )this; // --> doesn't work } }
modified on Thursday, January 15, 2009 6:18 AM
That's not how generics work unfortunately. You can't do this
GenericClass<firstclass> var1; GenericClass<base> var2; var2 = (GenericClass<base> )var1;
Your var1 & var2 variables are different types. One is a generic class using base as it's type member, and one is using FirstClass as it's type member, you can't cast one to the other, just because FirstClass is a subclass of Base. var1 isn't a subclass of var2. What generics effectively do is define a new class using the type you specified. So it effectively equates to this:
public class GenericClassUsingBase { public Base Item { get; set; } } public class GenericClassUsingFirstClass { public FirstClass Item { get; set; } }
You'll see if you try and cast these you can't do that either:
GenericClassUsingFirstClass var1; GenericClassUsingBase var2; var2 = (GenericClassUsingBase)var1;
They are basically different types, just because they are using type parameters that subclass each other doesn't make them subclasses of themselves.
Simon
-
That's not how generics work unfortunately. You can't do this
GenericClass<firstclass> var1; GenericClass<base> var2; var2 = (GenericClass<base> )var1;
Your var1 & var2 variables are different types. One is a generic class using base as it's type member, and one is using FirstClass as it's type member, you can't cast one to the other, just because FirstClass is a subclass of Base. var1 isn't a subclass of var2. What generics effectively do is define a new class using the type you specified. So it effectively equates to this:
public class GenericClassUsingBase { public Base Item { get; set; } } public class GenericClassUsingFirstClass { public FirstClass Item { get; set; } }
You'll see if you try and cast these you can't do that either:
GenericClassUsingFirstClass var1; GenericClassUsingBase var2; var2 = (GenericClassUsingBase)var1;
They are basically different types, just because they are using type parameters that subclass each other doesn't make them subclasses of themselves.
Simon
-
Thanks. Great explanation. I guess I'm not the only one who bumps into this. Any known workarounds? Or rethink the whole implementation from scratch?
gnjunge wrote:
Any known workarounds?
That kind of depends what you are trying to do. If you are trying to treat generics of a class tree as a tree themselves, I suspect you are slightly misusing the idea of generic classes. You might be better defining explicit classes instead of generic ones, and then having them all inherit from the same interface or abstract class instead if you need that. What is it you are trying to archive?
Simon
-
Am I missing something, or the example below is really impossible. The class called
FirstImplementation
derives fromGenericClass
, and the generic parameter used,FirstClass
derives fromBase
. So from the outside I should be able to castFirstImplementation
toGenericClass
public class Base { public int X { get; set; } } public class FirstClass : Base { public int Y { get; set; } } public abstract class GenericClass<T> where T: Base { public T Item { get; set;} } public class FirstImplementation : GenericClass<FirstClass> { public GenericClass<Base> Cast() { return (GenericClass<Base> )this; // --> doesn't work } }
modified on Thursday, January 15, 2009 6:18 AM
C# 4.0 brings generic covariance[^]. While the current code will still not compile, inserting an interface will get you going.
public interface IGenericClass where T : Base { public T Item {get; } } // note, having a set will not work
public abstract class GenericClass : IGenericClass {...}
var derived = new FirstImplementation();
IGenericClass<Base> baseInterface = derived;C# 4.0 is still in CTP stage though.
Regards Senthil [MVP - Visual C#] _____________________________ My Home Page |My Blog | My Articles | My Flickr | WinMacro
-
gnjunge wrote:
Any known workarounds?
That kind of depends what you are trying to do. If you are trying to treat generics of a class tree as a tree themselves, I suspect you are slightly misusing the idea of generic classes. You might be better defining explicit classes instead of generic ones, and then having them all inherit from the same interface or abstract class instead if you need that. What is it you are trying to archive?
Simon
-
C# 4.0 brings generic covariance[^]. While the current code will still not compile, inserting an interface will get you going.
public interface IGenericClass where T : Base { public T Item {get; } } // note, having a set will not work
public abstract class GenericClass : IGenericClass {...}
var derived = new FirstImplementation();
IGenericClass<Base> baseInterface = derived;C# 4.0 is still in CTP stage though.
Regards Senthil [MVP - Visual C#] _____________________________ My Home Page |My Blog | My Articles | My Flickr | WinMacro