[{"data":1,"prerenderedAt":1094},["ShallowReactive",2],{"blog:2006:substitutabilityofgenerictypesindotnet":3,"blogMore-Development":1053,"comments-substitutabilityofgenerictypesindotnet":1066},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"category":11,"tags":12,"excerpt":15,"body":40,"_type":1045,"_id":1046,"_source":1047,"_file":1048,"_stem":1049,"_extension":1050,"url":1051,"wordCount":1052,"minutes":140,"commentCount":77},"/blog/2006/substitutabilityofgenerictypesindotnet","2006",false,"en","Substitutability of generic types in .NET","","2006-05-03T00:59:00+00:00","Development",[13,14],".NET","C#",{"type":16,"children":17},"root",[18,26],{"type":19,"tag":20,"props":21,"children":22},"element","p",{},[23],{"type":24,"value":25},"text","Anyone using object orientated programming soon finds themselves wanting to perform some action only if an object is of some type or implements some interface.",{"type":19,"tag":20,"props":27,"children":28},{},[29,31,38],{"type":24,"value":30},"The easiest way is to do this is to use the ",{"type":19,"tag":32,"props":33,"children":35},"code",{"className":34},[],[36],{"type":24,"value":37},"is",{"type":24,"value":39}," operator. Typically it will appear something like:",{"type":16,"children":41,"toc":1039},[42,49,53,63,166,193,199,204,344,364,395,400,439,474,480,485,614,619,700,713,719,724,729,896,901,998,1019,1024,1033],{"type":19,"tag":43,"props":44,"children":46},"h2",{"id":45},"the-is-operator",[47],{"type":24,"value":48},"The “is” operator",{"type":19,"tag":20,"props":50,"children":51},{},[52],{"type":24,"value":25},{"type":19,"tag":20,"props":54,"children":55},{},[56,57,62],{"type":24,"value":30},{"type":19,"tag":32,"props":58,"children":60},{"className":59},[],[61],{"type":24,"value":37},{"type":24,"value":39},{"type":19,"tag":64,"props":65,"children":69},"pre",{"className":66,"code":67,"language":68,"meta":9,"style":9},"language-csharp shiki shiki-themes everforest-light dracula","object objA = FunctionToGetAnObject();\nif (obj is SomeClassOrInterface)\n    ((SomeClassOrInterface) obj).SomeMethod();\n","csharp",[70],{"type":19,"tag":32,"props":71,"children":72},{"__ignoreMap":9},[73,108,138],{"type":19,"tag":74,"props":75,"children":78},"span",{"class":76,"line":77},"line",1,[79,85,91,97,103],{"type":19,"tag":74,"props":80,"children":82},{"style":81},"--shiki-default:#3A94C5;--shiki-dark:#FF79C6",[83],{"type":24,"value":84},"object",{"type":19,"tag":74,"props":86,"children":88},{"style":87},"--shiki-default:#5C6A72;--shiki-dark:#F8F8F2",[89],{"type":24,"value":90}," objA ",{"type":19,"tag":74,"props":92,"children":94},{"style":93},"--shiki-default:#F57D26;--shiki-dark:#FF79C6",[95],{"type":24,"value":96},"=",{"type":19,"tag":74,"props":98,"children":100},{"style":99},"--shiki-default:#8DA101;--shiki-dark:#50FA7B",[101],{"type":24,"value":102}," FunctionToGetAnObject",{"type":19,"tag":74,"props":104,"children":105},{"style":87},[106],{"type":24,"value":107},"();\n",{"type":19,"tag":74,"props":109,"children":111},{"class":76,"line":110},2,[112,118,123,127,133],{"type":19,"tag":74,"props":113,"children":115},{"style":114},"--shiki-default:#F85552;--shiki-dark:#FF79C6",[116],{"type":24,"value":117},"if",{"type":19,"tag":74,"props":119,"children":120},{"style":87},[121],{"type":24,"value":122}," (obj ",{"type":19,"tag":74,"props":124,"children":125},{"style":114},[126],{"type":24,"value":37},{"type":19,"tag":74,"props":128,"children":130},{"style":129},"--shiki-default:#3A94C5;--shiki-default-font-style:inherit;--shiki-dark:#8BE9FD;--shiki-dark-font-style:italic",[131],{"type":24,"value":132}," SomeClassOrInterface",{"type":19,"tag":74,"props":134,"children":135},{"style":87},[136],{"type":24,"value":137},")\n",{"type":19,"tag":74,"props":139,"children":141},{"class":76,"line":140},3,[142,147,152,157,162],{"type":19,"tag":74,"props":143,"children":144},{"style":87},[145],{"type":24,"value":146},"    ((",{"type":19,"tag":74,"props":148,"children":149},{"style":129},[150],{"type":24,"value":151},"SomeClassOrInterface",{"type":19,"tag":74,"props":153,"children":154},{"style":87},[155],{"type":24,"value":156},") obj).",{"type":19,"tag":74,"props":158,"children":159},{"style":99},[160],{"type":24,"value":161},"SomeMethod",{"type":19,"tag":74,"props":163,"children":164},{"style":87},[165],{"type":24,"value":107},{"type":19,"tag":20,"props":167,"children":168},{},[169,171,177,179,184,186,191],{"type":24,"value":170},"Here if ",{"type":19,"tag":32,"props":172,"children":174},{"className":173},[],[175],{"type":24,"value":176},"obj_A",{"type":24,"value":178}," is of a type that implements SomeClassOrInterface anywhere in its inheritance tree then ",{"type":19,"tag":32,"props":180,"children":182},{"className":181},[],[183],{"type":24,"value":161},{"type":24,"value":185}," of ",{"type":19,"tag":32,"props":187,"children":189},{"className":188},[],[190],{"type":24,"value":151},{"type":24,"value":192}," will be called.",{"type":19,"tag":43,"props":194,"children":196},{"id":195},"test-substitution-with-generic-types",[197],{"type":24,"value":198},"Test substitution with generic types",{"type":19,"tag":20,"props":200,"children":201},{},[202],{"type":24,"value":203},"Now lets say we have our own generic type. Here’s one to illustrate a point;",{"type":19,"tag":64,"props":205,"children":207},{"className":66,"code":206,"language":68,"meta":9,"style":9},"public class DamoClass\u003CT> {\n    public T GetProperty { get { ... } }\n    public T SetProperty { set { ... } }\n    public bool IsValid { return true; }\n}\n",[208],{"type":19,"tag":32,"props":209,"children":210},{"__ignoreMap":9},[211,246,284,317,335],{"type":19,"tag":74,"props":212,"children":213},{"class":76,"line":77},[214,219,224,230,235,241],{"type":19,"tag":74,"props":215,"children":216},{"style":93},[217],{"type":24,"value":218},"public",{"type":19,"tag":74,"props":220,"children":221},{"style":114},[222],{"type":24,"value":223}," class",{"type":19,"tag":74,"props":225,"children":227},{"style":226},"--shiki-default:#3A94C5;--shiki-dark:#8BE9FD",[228],{"type":24,"value":229}," DamoClass",{"type":19,"tag":74,"props":231,"children":232},{"style":87},[233],{"type":24,"value":234},"\u003C",{"type":19,"tag":74,"props":236,"children":238},{"style":237},"--shiki-default:#3A94C5;--shiki-default-font-style:inherit;--shiki-dark:#FFB86C;--shiki-dark-font-style:italic",[239],{"type":24,"value":240},"T",{"type":19,"tag":74,"props":242,"children":243},{"style":87},[244],{"type":24,"value":245},"> {\n",{"type":19,"tag":74,"props":247,"children":248},{"class":76,"line":110},[249,254,259,264,269,274,279],{"type":19,"tag":74,"props":250,"children":251},{"style":93},[252],{"type":24,"value":253},"    public",{"type":19,"tag":74,"props":255,"children":256},{"style":129},[257],{"type":24,"value":258}," T",{"type":19,"tag":74,"props":260,"children":261},{"style":87},[262],{"type":24,"value":263}," GetProperty { ",{"type":19,"tag":74,"props":265,"children":266},{"style":81},[267],{"type":24,"value":268},"get",{"type":19,"tag":74,"props":270,"children":271},{"style":87},[272],{"type":24,"value":273}," { ",{"type":19,"tag":74,"props":275,"children":276},{"style":93},[277],{"type":24,"value":278},"..",{"type":19,"tag":74,"props":280,"children":281},{"style":87},[282],{"type":24,"value":283},". } }\n",{"type":19,"tag":74,"props":285,"children":286},{"class":76,"line":140},[287,291,295,300,305,309,313],{"type":19,"tag":74,"props":288,"children":289},{"style":93},[290],{"type":24,"value":253},{"type":19,"tag":74,"props":292,"children":293},{"style":129},[294],{"type":24,"value":258},{"type":19,"tag":74,"props":296,"children":297},{"style":87},[298],{"type":24,"value":299}," SetProperty { ",{"type":19,"tag":74,"props":301,"children":302},{"style":81},[303],{"type":24,"value":304},"set",{"type":19,"tag":74,"props":306,"children":307},{"style":87},[308],{"type":24,"value":273},{"type":19,"tag":74,"props":310,"children":311},{"style":93},[312],{"type":24,"value":278},{"type":19,"tag":74,"props":314,"children":315},{"style":87},[316],{"type":24,"value":283},{"type":19,"tag":74,"props":318,"children":320},{"class":76,"line":319},4,[321,325,330],{"type":19,"tag":74,"props":322,"children":323},{"style":93},[324],{"type":24,"value":253},{"type":19,"tag":74,"props":326,"children":327},{"style":81},[328],{"type":24,"value":329}," bool",{"type":19,"tag":74,"props":331,"children":332},{"style":87},[333],{"type":24,"value":334}," IsValid { return true; }\n",{"type":19,"tag":74,"props":336,"children":338},{"class":76,"line":337},5,[339],{"type":19,"tag":74,"props":340,"children":341},{"style":87},[342],{"type":24,"value":343},"}\n",{"type":19,"tag":20,"props":345,"children":346},{},[347,349,354,356,362],{"type":24,"value":348},"If we want to check ",{"type":19,"tag":32,"props":350,"children":352},{"className":351},[],[353],{"type":24,"value":176},{"type":24,"value":355}," supports ",{"type":19,"tag":32,"props":357,"children":359},{"className":358},[],[360],{"type":24,"value":361},"DamoClass\u003CT>",{"type":24,"value":363}," but we don’t care what type T is you might expect to be able to perform;",{"type":19,"tag":64,"props":365,"children":367},{"className":66,"code":366,"language":68,"meta":9,"style":9},"if (objA is DamoClass)\n",[368],{"type":19,"tag":32,"props":369,"children":370},{"__ignoreMap":9},[371],{"type":19,"tag":74,"props":372,"children":373},{"class":76,"line":77},[374,378,383,387,391],{"type":19,"tag":74,"props":375,"children":376},{"style":114},[377],{"type":24,"value":117},{"type":19,"tag":74,"props":379,"children":380},{"style":87},[381],{"type":24,"value":382}," (objA ",{"type":19,"tag":74,"props":384,"children":385},{"style":114},[386],{"type":24,"value":37},{"type":19,"tag":74,"props":388,"children":389},{"style":129},[390],{"type":24,"value":229},{"type":19,"tag":74,"props":392,"children":393},{"style":87},[394],{"type":24,"value":137},{"type":19,"tag":20,"props":396,"children":397},{},[398],{"type":24,"value":399},"But that results in a compilation error because you can’t reference a generic class without specifying the type parameters regardless of whether you care about them or not. You might then try;",{"type":19,"tag":64,"props":401,"children":403},{"className":66,"code":402,"language":68,"meta":9,"style":9},"if (objA is DamoClass\u003Cobject>)\n",[404],{"type":19,"tag":32,"props":405,"children":406},{"__ignoreMap":9},[407],{"type":19,"tag":74,"props":408,"children":409},{"class":76,"line":77},[410,414,418,422,426,430,434],{"type":19,"tag":74,"props":411,"children":412},{"style":114},[413],{"type":24,"value":117},{"type":19,"tag":74,"props":415,"children":416},{"style":87},[417],{"type":24,"value":382},{"type":19,"tag":74,"props":419,"children":420},{"style":114},[421],{"type":24,"value":37},{"type":19,"tag":74,"props":423,"children":424},{"style":129},[425],{"type":24,"value":229},{"type":19,"tag":74,"props":427,"children":428},{"style":87},[429],{"type":24,"value":234},{"type":19,"tag":74,"props":431,"children":432},{"style":81},[433],{"type":24,"value":84},{"type":19,"tag":74,"props":435,"children":436},{"style":87},[437],{"type":24,"value":438},">)\n",{"type":19,"tag":20,"props":440,"children":441},{},[442,444,449,451,457,459,464,466,472],{"type":24,"value":443},"After all every class inherits from ",{"type":19,"tag":32,"props":445,"children":447},{"className":446},[],[448],{"type":24,"value":84},{"type":24,"value":450},". This compiles fine but at runtime if ",{"type":19,"tag":32,"props":452,"children":454},{"className":453},[],[455],{"type":24,"value":456},"objA",{"type":24,"value":458}," is of any type other than ",{"type":19,"tag":32,"props":460,"children":462},{"className":461},[],[463],{"type":24,"value":84},{"type":24,"value":465},", e.g. ",{"type":19,"tag":32,"props":467,"children":469},{"className":468},[],[470],{"type":24,"value":471},"DamoClass\u003Cstring>",{"type":24,"value":473}," it will return false.",{"type":19,"tag":43,"props":475,"children":477},{"id":476},"why",[478],{"type":24,"value":479},"Why?",{"type":19,"tag":20,"props":481,"children":482},{},[483],{"type":24,"value":484},"The following might be what you had in mind;",{"type":19,"tag":64,"props":486,"children":488},{"className":66,"code":487,"language":68,"meta":9,"style":9},"if (objA is DamoClass\u003Cobject>) {\n    ((DamoClass\u003Cobject>) objA).IsValid();\n    object test = ((DamoClass\u003Cobject>) objA).GetProperty;\n}\n",[489],{"type":19,"tag":32,"props":490,"children":491},{"__ignoreMap":9},[492,524,558,607],{"type":19,"tag":74,"props":493,"children":494},{"class":76,"line":77},[495,499,503,507,511,515,519],{"type":19,"tag":74,"props":496,"children":497},{"style":114},[498],{"type":24,"value":117},{"type":19,"tag":74,"props":500,"children":501},{"style":87},[502],{"type":24,"value":382},{"type":19,"tag":74,"props":504,"children":505},{"style":114},[506],{"type":24,"value":37},{"type":19,"tag":74,"props":508,"children":509},{"style":129},[510],{"type":24,"value":229},{"type":19,"tag":74,"props":512,"children":513},{"style":87},[514],{"type":24,"value":234},{"type":19,"tag":74,"props":516,"children":517},{"style":81},[518],{"type":24,"value":84},{"type":19,"tag":74,"props":520,"children":521},{"style":87},[522],{"type":24,"value":523},">) {\n",{"type":19,"tag":74,"props":525,"children":526},{"class":76,"line":110},[527,531,536,540,544,549,554],{"type":19,"tag":74,"props":528,"children":529},{"style":87},[530],{"type":24,"value":146},{"type":19,"tag":74,"props":532,"children":533},{"style":129},[534],{"type":24,"value":535},"DamoClass",{"type":19,"tag":74,"props":537,"children":538},{"style":87},[539],{"type":24,"value":234},{"type":19,"tag":74,"props":541,"children":542},{"style":81},[543],{"type":24,"value":84},{"type":19,"tag":74,"props":545,"children":546},{"style":87},[547],{"type":24,"value":548},">) objA).",{"type":19,"tag":74,"props":550,"children":551},{"style":99},[552],{"type":24,"value":553},"IsValid",{"type":19,"tag":74,"props":555,"children":556},{"style":87},[557],{"type":24,"value":107},{"type":19,"tag":74,"props":559,"children":560},{"class":76,"line":140},[561,566,571,575,580,584,588,592,596,602],{"type":19,"tag":74,"props":562,"children":563},{"style":81},[564],{"type":24,"value":565},"    object",{"type":19,"tag":74,"props":567,"children":568},{"style":87},[569],{"type":24,"value":570}," test ",{"type":19,"tag":74,"props":572,"children":573},{"style":93},[574],{"type":24,"value":96},{"type":19,"tag":74,"props":576,"children":577},{"style":87},[578],{"type":24,"value":579}," ((",{"type":19,"tag":74,"props":581,"children":582},{"style":129},[583],{"type":24,"value":535},{"type":19,"tag":74,"props":585,"children":586},{"style":87},[587],{"type":24,"value":234},{"type":19,"tag":74,"props":589,"children":590},{"style":81},[591],{"type":24,"value":84},{"type":19,"tag":74,"props":593,"children":594},{"style":87},[595],{"type":24,"value":548},{"type":19,"tag":74,"props":597,"children":599},{"style":598},"--shiki-default:#35A77C;--shiki-dark:#F8F8F2",[600],{"type":24,"value":601},"GetProperty",{"type":19,"tag":74,"props":603,"children":604},{"style":87},[605],{"type":24,"value":606},";\n",{"type":19,"tag":74,"props":608,"children":609},{"class":76,"line":319},[610],{"type":19,"tag":74,"props":611,"children":612},{"style":87},[613],{"type":24,"value":343},{"type":19,"tag":20,"props":615,"children":616},{},[617],{"type":24,"value":618},"Which looks fine but if .NET allowed that then how would it prevent;",{"type":19,"tag":64,"props":620,"children":622},{"className":66,"code":621,"language":68,"meta":9,"style":9},"if (objA is DamoClass\u003Cobject>)\n    ((DamoClass\u003Cobject>) objA).SetProperty = 11;\n",[623],{"type":19,"tag":32,"props":624,"children":625},{"__ignoreMap":9},[626,657],{"type":19,"tag":74,"props":627,"children":628},{"class":76,"line":77},[629,633,637,641,645,649,653],{"type":19,"tag":74,"props":630,"children":631},{"style":114},[632],{"type":24,"value":117},{"type":19,"tag":74,"props":634,"children":635},{"style":87},[636],{"type":24,"value":382},{"type":19,"tag":74,"props":638,"children":639},{"style":114},[640],{"type":24,"value":37},{"type":19,"tag":74,"props":642,"children":643},{"style":129},[644],{"type":24,"value":229},{"type":19,"tag":74,"props":646,"children":647},{"style":87},[648],{"type":24,"value":234},{"type":19,"tag":74,"props":650,"children":651},{"style":81},[652],{"type":24,"value":84},{"type":19,"tag":74,"props":654,"children":655},{"style":87},[656],{"type":24,"value":438},{"type":19,"tag":74,"props":658,"children":659},{"class":76,"line":110},[660,664,668,672,676,680,685,690,696],{"type":19,"tag":74,"props":661,"children":662},{"style":87},[663],{"type":24,"value":146},{"type":19,"tag":74,"props":665,"children":666},{"style":129},[667],{"type":24,"value":535},{"type":19,"tag":74,"props":669,"children":670},{"style":87},[671],{"type":24,"value":234},{"type":19,"tag":74,"props":673,"children":674},{"style":81},[675],{"type":24,"value":84},{"type":19,"tag":74,"props":677,"children":678},{"style":87},[679],{"type":24,"value":548},{"type":19,"tag":74,"props":681,"children":682},{"style":598},[683],{"type":24,"value":684},"SetProperty",{"type":19,"tag":74,"props":686,"children":687},{"style":93},[688],{"type":24,"value":689}," =",{"type":19,"tag":74,"props":691,"children":693},{"style":692},"--shiki-default:#DF69BA;--shiki-dark:#BD93F9",[694],{"type":24,"value":695}," 11",{"type":19,"tag":74,"props":697,"children":698},{"style":87},[699],{"type":24,"value":606},{"type":19,"tag":20,"props":701,"children":702},{},[703,705,711],{"type":24,"value":704},"When ",{"type":19,"tag":32,"props":706,"children":708},{"className":707},[],[709],{"type":24,"value":710},"objA.AssociatedObject",{"type":24,"value":712}," might well be something other than an integer? It can’t, so it doesn’t.",{"type":19,"tag":43,"props":714,"children":716},{"id":715},"solution",[717],{"type":24,"value":718},"Solution",{"type":19,"tag":20,"props":720,"children":721},{},[722],{"type":24,"value":723},"The solution is to split your generic class into two classes.",{"type":19,"tag":20,"props":725,"children":726},{},[727],{"type":24,"value":728},"The first contains your non-generic methods and properties and the second inherits from the first adding all the generic specialisation. The good news is that they can even have the same name.",{"type":19,"tag":64,"props":730,"children":732},{"className":66,"code":731,"language":68,"meta":9,"style":9},"public class DamoClass {\n    public object GetProperty { get { ... } }\n    public bool IsValid { return true; }\n}\n\npublic class DamoClass\u003CT> : DamoClass {\n    public T SetProperty { set { ... } }\n}\n",[733],{"type":19,"tag":32,"props":734,"children":735},{"__ignoreMap":9},[736,756,788,803,810,819,856,888],{"type":19,"tag":74,"props":737,"children":738},{"class":76,"line":77},[739,743,747,751],{"type":19,"tag":74,"props":740,"children":741},{"style":93},[742],{"type":24,"value":218},{"type":19,"tag":74,"props":744,"children":745},{"style":114},[746],{"type":24,"value":223},{"type":19,"tag":74,"props":748,"children":749},{"style":226},[750],{"type":24,"value":229},{"type":19,"tag":74,"props":752,"children":753},{"style":87},[754],{"type":24,"value":755}," {\n",{"type":19,"tag":74,"props":757,"children":758},{"class":76,"line":110},[759,763,768,772,776,780,784],{"type":19,"tag":74,"props":760,"children":761},{"style":93},[762],{"type":24,"value":253},{"type":19,"tag":74,"props":764,"children":765},{"style":81},[766],{"type":24,"value":767}," object",{"type":19,"tag":74,"props":769,"children":770},{"style":87},[771],{"type":24,"value":263},{"type":19,"tag":74,"props":773,"children":774},{"style":81},[775],{"type":24,"value":268},{"type":19,"tag":74,"props":777,"children":778},{"style":87},[779],{"type":24,"value":273},{"type":19,"tag":74,"props":781,"children":782},{"style":93},[783],{"type":24,"value":278},{"type":19,"tag":74,"props":785,"children":786},{"style":87},[787],{"type":24,"value":283},{"type":19,"tag":74,"props":789,"children":790},{"class":76,"line":140},[791,795,799],{"type":19,"tag":74,"props":792,"children":793},{"style":93},[794],{"type":24,"value":253},{"type":19,"tag":74,"props":796,"children":797},{"style":81},[798],{"type":24,"value":329},{"type":19,"tag":74,"props":800,"children":801},{"style":87},[802],{"type":24,"value":334},{"type":19,"tag":74,"props":804,"children":805},{"class":76,"line":319},[806],{"type":19,"tag":74,"props":807,"children":808},{"style":87},[809],{"type":24,"value":343},{"type":19,"tag":74,"props":811,"children":812},{"class":76,"line":337},[813],{"type":19,"tag":74,"props":814,"children":816},{"emptyLinePlaceholder":815},true,[817],{"type":24,"value":818},"\n",{"type":19,"tag":74,"props":820,"children":822},{"class":76,"line":821},6,[823,827,831,835,839,843,848,852],{"type":19,"tag":74,"props":824,"children":825},{"style":93},[826],{"type":24,"value":218},{"type":19,"tag":74,"props":828,"children":829},{"style":114},[830],{"type":24,"value":223},{"type":19,"tag":74,"props":832,"children":833},{"style":226},[834],{"type":24,"value":229},{"type":19,"tag":74,"props":836,"children":837},{"style":87},[838],{"type":24,"value":234},{"type":19,"tag":74,"props":840,"children":841},{"style":237},[842],{"type":24,"value":240},{"type":19,"tag":74,"props":844,"children":845},{"style":87},[846],{"type":24,"value":847},"> : ",{"type":19,"tag":74,"props":849,"children":850},{"style":129},[851],{"type":24,"value":535},{"type":19,"tag":74,"props":853,"children":854},{"style":87},[855],{"type":24,"value":755},{"type":19,"tag":74,"props":857,"children":859},{"class":76,"line":858},7,[860,864,868,872,876,880,884],{"type":19,"tag":74,"props":861,"children":862},{"style":93},[863],{"type":24,"value":253},{"type":19,"tag":74,"props":865,"children":866},{"style":129},[867],{"type":24,"value":258},{"type":19,"tag":74,"props":869,"children":870},{"style":87},[871],{"type":24,"value":299},{"type":19,"tag":74,"props":873,"children":874},{"style":81},[875],{"type":24,"value":304},{"type":19,"tag":74,"props":877,"children":878},{"style":87},[879],{"type":24,"value":273},{"type":19,"tag":74,"props":881,"children":882},{"style":93},[883],{"type":24,"value":278},{"type":19,"tag":74,"props":885,"children":886},{"style":87},[887],{"type":24,"value":283},{"type":19,"tag":74,"props":889,"children":891},{"class":76,"line":890},8,[892],{"type":19,"tag":74,"props":893,"children":894},{"style":87},[895],{"type":24,"value":343},{"type":19,"tag":20,"props":897,"children":898},{},[899],{"type":24,"value":900},"Then you are free to do;",{"type":19,"tag":64,"props":902,"children":904},{"className":66,"code":903,"language":68,"meta":9,"style":9},"if (objA is DamoClass) {\n    ((DamoClass) objA).IsValid();\n    object test = ((DamoClass) objA).GetProperty;\n}\n",[905],{"type":19,"tag":32,"props":906,"children":907},{"__ignoreMap":9},[908,932,956,991],{"type":19,"tag":74,"props":909,"children":910},{"class":76,"line":77},[911,915,919,923,927],{"type":19,"tag":74,"props":912,"children":913},{"style":114},[914],{"type":24,"value":117},{"type":19,"tag":74,"props":916,"children":917},{"style":87},[918],{"type":24,"value":382},{"type":19,"tag":74,"props":920,"children":921},{"style":114},[922],{"type":24,"value":37},{"type":19,"tag":74,"props":924,"children":925},{"style":129},[926],{"type":24,"value":229},{"type":19,"tag":74,"props":928,"children":929},{"style":87},[930],{"type":24,"value":931},") {\n",{"type":19,"tag":74,"props":933,"children":934},{"class":76,"line":110},[935,939,943,948,952],{"type":19,"tag":74,"props":936,"children":937},{"style":87},[938],{"type":24,"value":146},{"type":19,"tag":74,"props":940,"children":941},{"style":129},[942],{"type":24,"value":535},{"type":19,"tag":74,"props":944,"children":945},{"style":87},[946],{"type":24,"value":947},") objA).",{"type":19,"tag":74,"props":949,"children":950},{"style":99},[951],{"type":24,"value":553},{"type":19,"tag":74,"props":953,"children":954},{"style":87},[955],{"type":24,"value":107},{"type":19,"tag":74,"props":957,"children":958},{"class":76,"line":140},[959,963,967,971,975,979,983,987],{"type":19,"tag":74,"props":960,"children":961},{"style":81},[962],{"type":24,"value":565},{"type":19,"tag":74,"props":964,"children":965},{"style":87},[966],{"type":24,"value":570},{"type":19,"tag":74,"props":968,"children":969},{"style":93},[970],{"type":24,"value":96},{"type":19,"tag":74,"props":972,"children":973},{"style":87},[974],{"type":24,"value":579},{"type":19,"tag":74,"props":976,"children":977},{"style":129},[978],{"type":24,"value":535},{"type":19,"tag":74,"props":980,"children":981},{"style":87},[982],{"type":24,"value":947},{"type":19,"tag":74,"props":984,"children":985},{"style":598},[986],{"type":24,"value":601},{"type":19,"tag":74,"props":988,"children":989},{"style":87},[990],{"type":24,"value":606},{"type":19,"tag":74,"props":992,"children":993},{"class":76,"line":319},[994],{"type":19,"tag":74,"props":995,"children":996},{"style":87},[997],{"type":24,"value":343},{"type":19,"tag":20,"props":999,"children":1000},{},[1001,1003,1009,1011,1017],{"type":24,"value":1002},"In fact, .NET itself uses this technique for ",{"type":19,"tag":32,"props":1004,"children":1006},{"className":1005},[],[1007],{"type":24,"value":1008},"IEnumerable",{"type":24,"value":1010}," and ",{"type":19,"tag":32,"props":1012,"children":1014},{"className":1013},[],[1015],{"type":24,"value":1016},"IEnumerable\u003CT>",{"type":24,"value":1018},".",{"type":19,"tag":20,"props":1020,"children":1021},{},[1022],{"type":24,"value":1023},"One drawback with this technique is that you can’t redefine the type of a member in the subclass; maybe that’ll make C# 3.0.",{"type":19,"tag":20,"props":1025,"children":1026},{},[1027],{"type":19,"tag":1028,"props":1029,"children":1030},"em",{},[1031],{"type":24,"value":1032},"[)amien",{"type":19,"tag":1034,"props":1035,"children":1036},"style",{},[1037],{"type":24,"value":1038},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":9,"searchDepth":110,"depth":110,"links":1040},[1041,1042,1043,1044],{"id":45,"depth":110,"text":48},{"id":195,"depth":110,"text":198},{"id":476,"depth":110,"text":479},{"id":715,"depth":110,"text":718},"markdown","content:blog:2006:substitutabilityofgenerictypesindotnet.md","content","blog/2006/substitutabilityofgenerictypesindotnet.md","blog/2006/substitutabilityofgenerictypesindotnet","md","/blog/2006/substitutabilityofgenerictypesindotnet/",507,[1054,1058,1062],{"title":1055,"date":1056,"url":1057},"HTML5 Video Cheatsheet: Optimizing videos for the web","2025-12-05T00:00:00Z","/blog/2025/html5-video-cheatsheet/",{"title":1059,"date":1060,"url":1061},"Transactions in the MongoDB EF Core Provider","2025-10-25","/blog/2025/mongodb-explicit-transactions/",{"title":1063,"date":1064,"url":1065},"Queryable Encryption with the MongoDB EF Core Provider","2025-09-22","/blog/2025/mongodb-queryable-encryption/",[1067],{"_path":1068,"_dir":1069,"_draft":6,"_partial":6,"_locale":7,"title":1070,"description":1071,"id":1072,"name":1073,"email":1074,"avatar":1075,"url":1076,"date":1077,"body":1078,"_type":1045,"_id":1091,"_source":1047,"_file":1092,"_stem":1093,"_extension":1050},"/comments/substitutabilityofgenerictypesindotnet/1482","substitutabilityofgenerictypesindotnet","1482","Generally I treat this problem with some caution - often needing to perform conditional behaviour based on typeof() or equivalent is a sign that logic may be in the wrong place. Often this behaviour can be pushed down to the objects themselves through some more generic concept or event behaviour and let polymorphism deal with it. Another way, appropriate if the algorithm is designed to be external to the classes themselves (perhaps because it is pluggable) is with a visitor pattern, where there are multiple overloaded visit(T obj) methods - code flow naturally follows the implementation for the given type.",1482,"Steve","steve@stevestreeting.com","https://www.gravatar.com/avatar/fbe8cc9ac5bc8797382e01e10f5f8e33?r=pg&d=retro","https://www.stevestreeting.com","2006-05-03T21:11:00",{"type":16,"children":1079,"toc":1089},[1080,1084],{"type":19,"tag":20,"props":1081,"children":1082},{},[1083],{"type":24,"value":1071},{"type":19,"tag":20,"props":1085,"children":1086},{},[1087],{"type":24,"value":1088},"Whatever the way, although I do very occasionally use typeof() style logic, I generally feel uncomfortable about it since it normally means I'm not thinking about something the right way. I won't say I've never done it, though ;)",{"title":9,"searchDepth":110,"depth":110,"links":1090},[],"content:comments:substitutabilityofgenerictypesindotnet:1482.md","comments/substitutabilityofgenerictypesindotnet/1482.md","comments/substitutabilityofgenerictypesindotnet/1482",1779264597450]