c# - Generics Inheritance and conversion -
this question has answer here:
i have following classes:
class item { } class meetingitem : item { } class itemgroup<t> { }
now, works without issue:
item something; = new meetingitem();
this fails:
itemgroup<item> itemgroup; itemgroup = new itemgroup<meetingitem>(); // fails here
i'm getting "cannot implicitly convert type 'itemgroup<meetingitem>
' 'itemgroup<item>
'" error. isn't i'm doing above (assigning type item , instantiating meetingitem)?
what have collection of items in itemgroup class along few other members. , i'm going have collection of itemgroups contain different types of derived items. ideally i'd have item abstract class (maybe interface, might need keep class depending on need implement).
i'm open refactoring ideas.
thanks.
edit add solution without having generic itemgroup: decided ditch generics... kinda... cobbled this:
public class itemgroup { public type itemtype => this.items.gettype().getgenericarguments()[0]; public ilist items { get; set; } public itemgroup(type itemtype) { var genericlisttype = typeof(list<>).makegenerictype(itemtype); items = (ilist)activator.createinstance(genericlisttype); } }
so, can this:
list<itemgroup> groups = new list<itemgroup>(); groups.add(new itemgroup(typeof(meetingitem));
and can test specific item type following:
groups[0].itemtype == typeof(meetingitem)
it seems little hacky, works. i'm little concerned performance on itemtype property, , i'm open refactoring ideas.
this issue variance.
consider simple interface this:
interface myinterface<t> { t getstuff(); void setstuff(t value); }
now, have myinterface<a>
, , myinterface<b>
, b
inherits a
.
it's safe return b
instead of a
. however, isn't safe return a
instead of b
. therefore, looking @ getstuff
, should possible cast myinterface<b>
myinterface<a>
, not vice versa.
it's safe pass b
instead of a
. however, isn't safe pass a
instead of b
. therefore, looking @ setstuff
, should possible cast myinterface<a>
myinterface<b>
, not vice versa.
the problem should obvious - can't fulfill both @ once. there no safe cast both of methods.
if can avoid having both ways in single interface, can use out
/in
keywords specify kind of variance supported interface, that's it. looking @ classes .net framework:
ienumerable<object> enumerable = enumerable.empty<string>(); // safe, // enumerable covariant icollection<object> collection = new collection<string>(); // error, // collection isn't covariant func<object> func = () => "hi!"; // safe, func<t> covariant action<object> func = (string val) => { ... }; // error, action<t> isn't covariant
on other hand, contravariance:
func<string> func = () => new object(); // error, func<t> isn't contravariant action<string> func = (object val) => { ... }; // safe, action<t> contravariant
Comments
Post a Comment