C# generic inheritance: invariance getting in the way of calling derived class -


what want do:

abstract class tilebase {     protected tilegroup<tilebase> tilegroup; } class tile : tilebase {     public tile(province province)     {         tilegroup = province;     } } abstract class tilegroup<t> {     protected t[] tiles;     protected tilegroup<tilegroup<t>> tilegroup; } class province : tilegroup<tilebase> {      public province(tile tile, nation nation)     {         tiles = new[] { tile };         tilegroup = nation;     } } class nation : tilegroup<province> {      public nation(province province)     {         tiles = new[] { province };         tilegroup = null;     } } 

this not work because of invariance (if understand invariance correctly): cannot convert nation tilegroup<tilegroup<tilebase>>

so i'll need write this:

class nation : tilegroup<tilegroup<tilebase>> {      public nation(province province)     {         tiles = new[] { province };         tilegroup = null;     } } 

but when layers stacked; gets ugly fast:

map : tilegroup<tilegroup<tilegroup<tilebase>>>  

this makes adding layers between 2 existing layers difficult because 1 change in low layer means changing higher layers.

so how should doing this?


sorry formulation, know want, not how should explain clearer in way.

in order understand going on , why isn’t working, need understand generic types are. in way, kind of template provide exact types every valid t requested language.

when write tilegroup<tilebase> happens new type, let’s call tilegroup_tilebase defined looks this:

class tilegroup_tilebase {     protected tilebase[] tiles;     protected tilegroup<tilegroup<tilebase>> tilegroup; } 

now, let’s continue expansion of generic types bit. know tilegroup<tilebase> type in there, there’s tilegroup<tilegroup_tilebase>, let’s replace that:

class tilegroup_tilebase {     protected tilebase[] tiles;     protected tilegroup_tilegroup_tilebase tilegroup; } class tilegroup_tilegroup_tilebase {     protected tilegroup_tilebase[] tiles;     protected tilegroup<tilegroup<tilegroup_tilebase>> tilegroup; } 

we continue here, enough explain problem. let’s take @ nation instead trying assign in province constructor. nation tilegroup<province>, let’s expand that:

class tilegroup_province {     protected province[] tiles;     protected tilegroup<tilegroup<province>> tilegroup; } 

okay, have types expanded enough. let’s take @ assignment trying do. in province, tilegroup property of type tilegroup<tilegroup<tilebase>>, trying do:

tilegroup<province> nation = null; tilegroup<tilegroup<tilebase>> province_tilegroup = nation; 

can see why fails now? if not, let’s use our expanded generic types here instead:

tilegroup_province nation = null; tilegroup_tilegroup_tilebase province_tilegroup = nation; 

okay, actual types used (remember not doing understand this, generic types actually materialized each t real!). if @ definitions above, tilegroup_province , tilegroup_tilegroup_tilebase not related. sure, similar, there no type relationship allow kind of assignment!

that’s why when deal generic types in bcl, have interfaces. because interfaces allow have type relationship between generic type materializations can use assign 1 another. honest though, abstract classes protected fields make bit difficult clean interfaces, should think whether need kind of type relationships , whether having abstract base type fields necessary.


Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -