[{"data":1,"prerenderedAt":1235},["ShallowReactive",2],{"blog:2007:multiple-inheritance-composition-and-single-responsibility-principle-in-net":3,"blogMore-Development":1221,"comments-multiple-inheritance-composition-and-single-responsibility-principle-in-net":1234},{"id":4,"title":5,"body":6,"category":1204,"commentCount":206,"date":1205,"description":1206,"excerpt":1207,"extension":1208,"filenames":1209,"hidden":1210,"image":1209,"meta":1211,"minutes":206,"navigation":202,"path":1212,"seo":1213,"showCategory":1209,"stem":1214,"tags":1215,"updated":1209,"url":1218,"wordCount":1219,"__hash__":1220},"content\u002Fblog\u002F2007\u002Fmultiple-inheritance-composition-and-single-responsibility-principle-in-net.md","Multiple-inheritance, composition and single responsibility principle in .NET",{"type":7,"value":8,"toc":1194},"minimark",[9,27,30,38,130,135,141,764,767,774,811,814,821,905,915,924,930,937,943,986,997,1085,1101,1105,1108,1177,1184,1190],[10,11,12,13,20,21,26],"p",{},".NET is often chided by C++ developers for failing to support multiple-inheritance. The reply is often ",[14,15,19],"a",{"href":16,"rel":17},"https:\u002F\u002Fwww.artima.com\u002Flejava\u002Farticles\u002Fdesignprinciples4.html",[18],"nofollow","Favor object composition over class inheritance",", a mantra chanted from everywhere including the opening chapters of the ",[14,22,25],{"href":23,"rel":24},"https:\u002F\u002Fwww.amazon.com\u002Fgp\u002Fproduct\u002F0201633612?ie=UTF8&tag=dam-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0201633612",[18],"Gang of Four’s Design Patterns book",".",[10,28,29],{},"If the accepted mantra is that your object should expose interfaces and delegate the implementation of those interfaces elsewhere then it could really do with some better support than .NET currently offers especially where the interface comprises more than a member or two.",[10,31,32,33,37],{},"Consider the following fragment of a class for customer price-lists (properties and methods omitted). We decide to support ",[34,35,36],"code",{},"IList\u003CProductPrice>"," so that consumers of our class can add, remove and iterate over the prices in a familiar manner (principle of least surprise).",[39,40,45],"pre",{"className":41,"code":42,"language":43,"meta":44,"style":44},"language-csharp shiki shiki-themes everforest-light dracula","public class CustomerPriceList : IList\u003CProductPrice> {\n    private List\u003CProductPrice> productPrices = new List\u003CProductPrice>();\n    public Customer Customer;\n}\n","csharp","",[34,46,47,81,112,124],{"__ignoreMap":44},[48,49,52,56,60,64,68,72,75,78],"span",{"class":50,"line":51},"line",1,[48,53,55],{"class":54},"s9HRq","public",[48,57,59],{"class":58},"smiwp"," class",[48,61,63],{"class":62},"sPLAf"," CustomerPriceList",[48,65,67],{"class":66},"s6Vpi"," : ",[48,69,71],{"class":70},"snuxY","IList",[48,73,74],{"class":66},"\u003C",[48,76,77],{"class":70},"ProductPrice",[48,79,80],{"class":66},"> {\n",[48,82,84,87,90,92,94,97,100,103,105,107,109],{"class":50,"line":83},2,[48,85,86],{"class":54},"    private",[48,88,89],{"class":70}," List",[48,91,74],{"class":66},[48,93,77],{"class":70},[48,95,96],{"class":66},"> productPrices ",[48,98,99],{"class":54},"=",[48,101,102],{"class":58}," new",[48,104,89],{"class":70},[48,106,74],{"class":66},[48,108,77],{"class":70},[48,110,111],{"class":66},">();\n",[48,113,115,118,121],{"class":50,"line":114},3,[48,116,117],{"class":54},"    public",[48,119,120],{"class":70}," Customer",[48,122,123],{"class":66}," Customer;\n",[48,125,127],{"class":50,"line":126},4,[48,128,129],{"class":66},"}\n",[131,132,134],"h2",{"id":133},"implement-interface","Implement interface",[10,136,137,138,140],{},"Visual Studio offers some assistance where you can choose Implement interface ",[34,139,36],{}," which gives you all the method definitions with the very unhelpful body of throwing an exception of “This method or operation is not implemented”. It requires some work to fill in all these definitions to something that works:",[39,142,144],{"className":41,"code":143,"language":43,"meta":44,"style":44},"public class CustomerPriceList : IList\u003CProductPrice> {\n    private  List\u003CProductPrice> productPrices = new  List\u003CProductPrice>();\n    public  Customer Customer;\n\n    public int IndexOf(ProductPrice item) {\n        return productPrices.IndexOf(item);\n    }\n\n    public void Insert(int index, ProductPrice item) {\n        productPrices.Insert(index, item);\n    }\n\n    public void RemoveAt(int index) {\n        productPrices.RemoveAt(index);\n    }\n\n    public ProductPrice this[int index] {\n        get { return productPrices[index]; }\n        set { productPrices[index] = value; }\n    }\n\n    public void Add(ProductPrice item) {\n        productPrices.Add(item);\n    }\n\n    public void Clear() {\n        productPrices.Clear();\n    }\n\n    public bool Contains(ProductPrice item) {\n        return productPrices.Contains(item);\n    }\n\n    public void CopyTo(ProductPrice[] array, int arrayIndex) {\n        productPrices.CopyTo(array, arrayIndex);\n    }\n\n    public int Count { get { return productPrices.Count; } }\n\n    public bool IsReadOnly { get { return ((IList)productPrices).IsReadOnly; } }\n\n    public bool Remove(ProductPrice item) {\n        return productPrices.Remove(item);\n    }\n\n    public IEnumerator\u003CProductPrice> GetEnumerator() {\n        return productPrices.GetEnumerator();\n    }\n\n    IEnumerator IEnumerable.GetEnumerator() {\n        return ((IEnumerable) productPrices).GetEnumerator();\n    }\n}\n",[34,145,146,164,189,198,204,229,244,250,255,283,295,300,305,323,334,339,344,366,385,404,409,414,432,442,447,452,465,476,481,486,505,517,522,527,556,567,572,577,602,607,636,641,659,671,676,681,701,712,717,722,737,754,759],{"__ignoreMap":44},[48,147,148,150,152,154,156,158,160,162],{"class":50,"line":51},[48,149,55],{"class":54},[48,151,59],{"class":58},[48,153,63],{"class":62},[48,155,67],{"class":66},[48,157,71],{"class":70},[48,159,74],{"class":66},[48,161,77],{"class":70},[48,163,80],{"class":66},[48,165,166,168,171,173,175,177,179,181,183,185,187],{"class":50,"line":83},[48,167,86],{"class":54},[48,169,170],{"class":70},"  List",[48,172,74],{"class":66},[48,174,77],{"class":70},[48,176,96],{"class":66},[48,178,99],{"class":54},[48,180,102],{"class":58},[48,182,170],{"class":70},[48,184,74],{"class":66},[48,186,77],{"class":70},[48,188,111],{"class":66},[48,190,191,193,196],{"class":50,"line":114},[48,192,117],{"class":54},[48,194,195],{"class":70},"  Customer",[48,197,123],{"class":66},[48,199,200],{"class":50,"line":126},[48,201,203],{"emptyLinePlaceholder":202},true,"\n",[48,205,207,209,213,217,220,222,226],{"class":50,"line":206},5,[48,208,117],{"class":54},[48,210,212],{"class":211},"sXAHl"," int",[48,214,216],{"class":215},"sS4Kt"," IndexOf",[48,218,219],{"class":66},"(",[48,221,77],{"class":70},[48,223,225],{"class":224},"s7cAX"," item",[48,227,228],{"class":66},") {\n",[48,230,232,235,238,241],{"class":50,"line":231},6,[48,233,234],{"class":58},"        return",[48,236,237],{"class":66}," productPrices.",[48,239,240],{"class":215},"IndexOf",[48,242,243],{"class":66},"(item);\n",[48,245,247],{"class":50,"line":246},7,[48,248,249],{"class":66},"    }\n",[48,251,253],{"class":50,"line":252},8,[48,254,203],{"emptyLinePlaceholder":202},[48,256,258,260,263,266,268,271,274,277,279,281],{"class":50,"line":257},9,[48,259,117],{"class":54},[48,261,262],{"class":211}," void",[48,264,265],{"class":215}," Insert",[48,267,219],{"class":66},[48,269,270],{"class":211},"int",[48,272,273],{"class":224}," index",[48,275,276],{"class":66},", ",[48,278,77],{"class":70},[48,280,225],{"class":224},[48,282,228],{"class":66},[48,284,286,289,292],{"class":50,"line":285},10,[48,287,288],{"class":66},"        productPrices.",[48,290,291],{"class":215},"Insert",[48,293,294],{"class":66},"(index, item);\n",[48,296,298],{"class":50,"line":297},11,[48,299,249],{"class":66},[48,301,303],{"class":50,"line":302},12,[48,304,203],{"emptyLinePlaceholder":202},[48,306,308,310,312,315,317,319,321],{"class":50,"line":307},13,[48,309,117],{"class":54},[48,311,262],{"class":211},[48,313,314],{"class":215}," RemoveAt",[48,316,219],{"class":66},[48,318,270],{"class":211},[48,320,273],{"class":224},[48,322,228],{"class":66},[48,324,326,328,331],{"class":50,"line":325},14,[48,327,288],{"class":66},[48,329,330],{"class":215},"RemoveAt",[48,332,333],{"class":66},"(index);\n",[48,335,337],{"class":50,"line":336},15,[48,338,249],{"class":66},[48,340,342],{"class":50,"line":341},16,[48,343,203],{"emptyLinePlaceholder":202},[48,345,347,349,352,356,359,361,363],{"class":50,"line":346},17,[48,348,117],{"class":54},[48,350,351],{"class":70}," ProductPrice",[48,353,355],{"class":354},"sKO3f"," this",[48,357,358],{"class":66},"[",[48,360,270],{"class":211},[48,362,273],{"class":224},[48,364,365],{"class":66},"] {\n",[48,367,369,372,375,378,382],{"class":50,"line":368},18,[48,370,371],{"class":211},"        get",[48,373,374],{"class":66}," { ",[48,376,377],{"class":58},"return",[48,379,381],{"class":380},"sSKRk"," productPrices",[48,383,384],{"class":66},"[index]; }\n",[48,386,388,391,393,396,399,401],{"class":50,"line":387},19,[48,389,390],{"class":211},"        set",[48,392,374],{"class":66},[48,394,395],{"class":380},"productPrices",[48,397,398],{"class":66},"[index] ",[48,400,99],{"class":54},[48,402,403],{"class":66}," value; }\n",[48,405,407],{"class":50,"line":406},20,[48,408,249],{"class":66},[48,410,412],{"class":50,"line":411},21,[48,413,203],{"emptyLinePlaceholder":202},[48,415,417,419,421,424,426,428,430],{"class":50,"line":416},22,[48,418,117],{"class":54},[48,420,262],{"class":211},[48,422,423],{"class":215}," Add",[48,425,219],{"class":66},[48,427,77],{"class":70},[48,429,225],{"class":224},[48,431,228],{"class":66},[48,433,435,437,440],{"class":50,"line":434},23,[48,436,288],{"class":66},[48,438,439],{"class":215},"Add",[48,441,243],{"class":66},[48,443,445],{"class":50,"line":444},24,[48,446,249],{"class":66},[48,448,450],{"class":50,"line":449},25,[48,451,203],{"emptyLinePlaceholder":202},[48,453,455,457,459,462],{"class":50,"line":454},26,[48,456,117],{"class":54},[48,458,262],{"class":211},[48,460,461],{"class":215}," Clear",[48,463,464],{"class":66},"() {\n",[48,466,468,470,473],{"class":50,"line":467},27,[48,469,288],{"class":66},[48,471,472],{"class":215},"Clear",[48,474,475],{"class":66},"();\n",[48,477,479],{"class":50,"line":478},28,[48,480,249],{"class":66},[48,482,484],{"class":50,"line":483},29,[48,485,203],{"emptyLinePlaceholder":202},[48,487,489,491,494,497,499,501,503],{"class":50,"line":488},30,[48,490,117],{"class":54},[48,492,493],{"class":211}," bool",[48,495,496],{"class":215}," Contains",[48,498,219],{"class":66},[48,500,77],{"class":70},[48,502,225],{"class":224},[48,504,228],{"class":66},[48,506,508,510,512,515],{"class":50,"line":507},31,[48,509,234],{"class":58},[48,511,237],{"class":66},[48,513,514],{"class":215},"Contains",[48,516,243],{"class":66},[48,518,520],{"class":50,"line":519},32,[48,521,249],{"class":66},[48,523,525],{"class":50,"line":524},33,[48,526,203],{"emptyLinePlaceholder":202},[48,528,530,532,534,537,539,541,544,547,549,551,554],{"class":50,"line":529},34,[48,531,117],{"class":54},[48,533,262],{"class":211},[48,535,536],{"class":215}," CopyTo",[48,538,219],{"class":66},[48,540,77],{"class":70},[48,542,543],{"class":66},"[] ",[48,545,546],{"class":224},"array",[48,548,276],{"class":66},[48,550,270],{"class":211},[48,552,553],{"class":224}," arrayIndex",[48,555,228],{"class":66},[48,557,559,561,564],{"class":50,"line":558},35,[48,560,288],{"class":66},[48,562,563],{"class":215},"CopyTo",[48,565,566],{"class":66},"(array, arrayIndex);\n",[48,568,570],{"class":50,"line":569},36,[48,571,249],{"class":66},[48,573,575],{"class":50,"line":574},37,[48,576,203],{"emptyLinePlaceholder":202},[48,578,580,582,584,587,590,592,594,596,599],{"class":50,"line":579},38,[48,581,117],{"class":54},[48,583,212],{"class":211},[48,585,586],{"class":66}," Count { ",[48,588,589],{"class":211},"get",[48,591,374],{"class":66},[48,593,377],{"class":58},[48,595,237],{"class":66},[48,597,598],{"class":380},"Count",[48,600,601],{"class":66},"; } }\n",[48,603,605],{"class":50,"line":604},39,[48,606,203],{"emptyLinePlaceholder":202},[48,608,610,612,614,617,619,621,623,626,628,631,634],{"class":50,"line":609},40,[48,611,117],{"class":54},[48,613,493],{"class":211},[48,615,616],{"class":66}," IsReadOnly { ",[48,618,589],{"class":211},[48,620,374],{"class":66},[48,622,377],{"class":58},[48,624,625],{"class":66}," ((",[48,627,71],{"class":70},[48,629,630],{"class":66},")productPrices).",[48,632,633],{"class":380},"IsReadOnly",[48,635,601],{"class":66},[48,637,639],{"class":50,"line":638},41,[48,640,203],{"emptyLinePlaceholder":202},[48,642,644,646,648,651,653,655,657],{"class":50,"line":643},42,[48,645,117],{"class":54},[48,647,493],{"class":211},[48,649,650],{"class":215}," Remove",[48,652,219],{"class":66},[48,654,77],{"class":70},[48,656,225],{"class":224},[48,658,228],{"class":66},[48,660,662,664,666,669],{"class":50,"line":661},43,[48,663,234],{"class":58},[48,665,237],{"class":66},[48,667,668],{"class":215},"Remove",[48,670,243],{"class":66},[48,672,674],{"class":50,"line":673},44,[48,675,249],{"class":66},[48,677,679],{"class":50,"line":678},45,[48,680,203],{"emptyLinePlaceholder":202},[48,682,684,686,689,691,693,696,699],{"class":50,"line":683},46,[48,685,117],{"class":54},[48,687,688],{"class":70}," IEnumerator",[48,690,74],{"class":66},[48,692,77],{"class":70},[48,694,695],{"class":66},"> ",[48,697,698],{"class":215},"GetEnumerator",[48,700,464],{"class":66},[48,702,704,706,708,710],{"class":50,"line":703},47,[48,705,234],{"class":58},[48,707,237],{"class":66},[48,709,698],{"class":215},[48,711,475],{"class":66},[48,713,715],{"class":50,"line":714},48,[48,716,249],{"class":66},[48,718,720],{"class":50,"line":719},49,[48,721,203],{"emptyLinePlaceholder":202},[48,723,725,728,731,733,735],{"class":50,"line":724},50,[48,726,727],{"class":70},"    IEnumerator",[48,729,730],{"class":70}," IEnumerable",[48,732,26],{"class":66},[48,734,698],{"class":215},[48,736,464],{"class":66},[48,738,740,742,744,747,750,752],{"class":50,"line":739},51,[48,741,234],{"class":58},[48,743,625],{"class":66},[48,745,746],{"class":70},"IEnumerable",[48,748,749],{"class":66},") productPrices).",[48,751,698],{"class":215},[48,753,475],{"class":66},[48,755,757],{"class":50,"line":756},52,[48,758,249],{"class":66},[48,760,762],{"class":50,"line":761},53,[48,763,129],{"class":66},[10,765,766],{},"This is a lot of effort for a cluttered solution.",[131,768,770,771],{"id":769},"use-inheritance-to-subclass-listt","Use inheritance to subclass ",[34,772,773],{},"List\u003CT>",[39,775,777],{"className":41,"code":776,"language":43,"meta":44,"style":44},"public class CustomerPriceList : List\u003CProductPrice> {\n  public Customer Customer;\n}\n",[34,778,779,798,807],{"__ignoreMap":44},[48,780,781,783,785,787,789,792,794,796],{"class":50,"line":51},[48,782,55],{"class":54},[48,784,59],{"class":58},[48,786,63],{"class":62},[48,788,67],{"class":66},[48,790,791],{"class":70},"List",[48,793,74],{"class":66},[48,795,77],{"class":70},[48,797,80],{"class":66},[48,799,800,803,805],{"class":50,"line":83},[48,801,802],{"class":54},"  public",[48,804,120],{"class":70},[48,806,123],{"class":66},[48,808,809],{"class":50,"line":114},[48,810,129],{"class":66},[10,812,813],{},"Small amount of code but not an option if you have a class hierarchy in place or need to implement multiple interfaces.",[131,815,817,818,820],{"id":816},"expose-ilistproductprice-property-directly","Expose ",[34,819,36],{}," property directly",[39,822,824],{"className":41,"code":823,"language":43,"meta":44,"style":44},"public class CustomerPriceList : IListable\u003CProductPrice> {\n  private List\u003CProductPrice> productPrices = new List\u003CProductPrice>();\n  public Customer Customer;\n  public IList\u003CProductPrice> ProductPrices { get { return productPrices; } }\n}\n",[34,825,826,845,870,878,901],{"__ignoreMap":44},[48,827,828,830,832,834,836,839,841,843],{"class":50,"line":51},[48,829,55],{"class":54},[48,831,59],{"class":58},[48,833,63],{"class":62},[48,835,67],{"class":66},[48,837,838],{"class":70},"IListable",[48,840,74],{"class":66},[48,842,77],{"class":70},[48,844,80],{"class":66},[48,846,847,850,852,854,856,858,860,862,864,866,868],{"class":50,"line":83},[48,848,849],{"class":54},"  private",[48,851,89],{"class":70},[48,853,74],{"class":66},[48,855,77],{"class":70},[48,857,96],{"class":66},[48,859,99],{"class":54},[48,861,102],{"class":58},[48,863,89],{"class":70},[48,865,74],{"class":66},[48,867,77],{"class":70},[48,869,111],{"class":66},[48,871,872,874,876],{"class":50,"line":114},[48,873,802],{"class":54},[48,875,120],{"class":70},[48,877,123],{"class":66},[48,879,880,882,885,887,889,892,894,896,898],{"class":50,"line":126},[48,881,802],{"class":54},[48,883,884],{"class":70}," IList",[48,886,74],{"class":66},[48,888,77],{"class":70},[48,890,891],{"class":66},"> ProductPrices { ",[48,893,589],{"class":211},[48,895,374],{"class":66},[48,897,377],{"class":58},[48,899,900],{"class":66}," productPrices; } }\n",[48,902,903],{"class":50,"line":206},[48,904,129],{"class":66},[10,906,907,908,911,912,914],{},"This works but means ",[34,909,910],{},"CustomerPriceList"," can not control any of the ",[34,913,71],{}," implementation such as validation.",[10,916,917,918,920,921,923],{},"Methods may also start accepting ",[34,919,36],{}," instead of ",[34,922,910],{}," because developers imagine the parts to be more decoupled than they actually are and are encouraged to code to interfaces not concrete classes.",[10,925,926,927,929],{},"Refactoring away from this at a later date would require a ",[34,928,36],{}," wrapper than delegated calls back to the containing class to prevent an interface-breaking change.",[131,931,933,934,936],{"id":932},"introduce-interface-to-declare-ilistproductprice-available","Introduce interface to declare ",[34,935,36],{}," available",[10,938,939,940,942],{},"Add an interface that signifies a ",[34,941,36],{}," can be obtained by calling the named method, e.g.",[39,944,946],{"className":41,"code":945,"language":43,"meta":44,"style":44},"public interface IListable\u003CT> {\n  IList\u003CT> GetList();\n}\n",[34,947,948,966,982],{"__ignoreMap":44},[48,949,950,952,955,958,960,964],{"class":50,"line":51},[48,951,55],{"class":54},[48,953,954],{"class":58}," interface",[48,956,957],{"class":70}," IListable",[48,959,74],{"class":66},[48,961,963],{"class":962},"sAO9U","T",[48,965,80],{"class":66},[48,967,968,971,973,975,977,980],{"class":50,"line":83},[48,969,970],{"class":70},"  IList",[48,972,74],{"class":66},[48,974,963],{"class":70},[48,976,695],{"class":66},[48,978,979],{"class":215},"GetList",[48,981,475],{"class":66},[48,983,984],{"class":50,"line":114},[48,985,129],{"class":66},[10,987,988,989,992,993,996],{},"This is a similar pattern to that of ",[34,990,991],{},"IEnumerable\u003CT>"," and ",[34,994,995],{},"IEnumerator\u003CT>"," whereby one interface signifies the availability of the other. In this example our class would look like:",[39,998,1000],{"className":41,"code":999,"language":43,"meta":44,"style":44},"public class CustomerPriceList : IListable\u003CProductPrice> {\n  private List\u003CProductPrice> productPrices = new List\u003CProductPrice>();\n  public Customer Customer;\n  public IList\u003CProductPrice> GetList() {\n    return productPrices;\n  }\n}\n",[34,1001,1002,1020,1044,1052,1068,1076,1081],{"__ignoreMap":44},[48,1003,1004,1006,1008,1010,1012,1014,1016,1018],{"class":50,"line":51},[48,1005,55],{"class":54},[48,1007,59],{"class":58},[48,1009,63],{"class":62},[48,1011,67],{"class":66},[48,1013,838],{"class":70},[48,1015,74],{"class":66},[48,1017,77],{"class":70},[48,1019,80],{"class":66},[48,1021,1022,1024,1026,1028,1030,1032,1034,1036,1038,1040,1042],{"class":50,"line":83},[48,1023,849],{"class":54},[48,1025,89],{"class":70},[48,1027,74],{"class":66},[48,1029,77],{"class":70},[48,1031,96],{"class":66},[48,1033,99],{"class":54},[48,1035,102],{"class":58},[48,1037,89],{"class":70},[48,1039,74],{"class":66},[48,1041,77],{"class":70},[48,1043,111],{"class":66},[48,1045,1046,1048,1050],{"class":50,"line":114},[48,1047,802],{"class":54},[48,1049,120],{"class":70},[48,1051,123],{"class":66},[48,1053,1054,1056,1058,1060,1062,1064,1066],{"class":50,"line":126},[48,1055,802],{"class":54},[48,1057,884],{"class":70},[48,1059,74],{"class":66},[48,1061,77],{"class":70},[48,1063,695],{"class":66},[48,1065,979],{"class":215},[48,1067,464],{"class":66},[48,1069,1070,1073],{"class":50,"line":206},[48,1071,1072],{"class":58},"    return",[48,1074,1075],{"class":66}," productPrices;\n",[48,1077,1078],{"class":50,"line":231},[48,1079,1080],{"class":66},"  }\n",[48,1082,1083],{"class":50,"line":246},[48,1084,129],{"class":66},[10,1086,1087,1088,1090,1091,1093,1094,1096,1097,1100],{},"Which is less code, a closer adherence to single responsibility principle (SRP) and the ability to change without breaking the interface although it still does nothing to prevent passing ",[34,1089,71],{}," or ",[34,1092,838],{}," interfaces where ",[34,1095,910],{}," would be more suitable. An ",[34,1098,1099],{},"IPriceList"," class could be introduced although it starts to feel like abstract infinity.",[131,1102,1104],{"id":1103},"improved-support-from-net","Improved support from .NET",[10,1106,1107],{},"I’d really like to see .NET improve on the support for interfaces and composition, like perhaps the following:",[39,1109,1111],{"className":41,"code":1110,"language":43,"meta":44,"style":44},"public class CustomerPriceList : IList\u003CProductPrice> goto productPrice {\n  private IList\u003CProductPrice> productPrice = new IList\u003CProductPrice>();\n  public Customer Customer;\n}\n",[34,1112,1113,1140,1165,1173],{"__ignoreMap":44},[48,1114,1115,1117,1119,1121,1123,1125,1127,1129,1131,1134,1137],{"class":50,"line":51},[48,1116,55],{"class":54},[48,1118,59],{"class":58},[48,1120,63],{"class":62},[48,1122,67],{"class":66},[48,1124,71],{"class":70},[48,1126,74],{"class":66},[48,1128,77],{"class":70},[48,1130,695],{"class":66},[48,1132,1133],{"class":70},"goto",[48,1135,1136],{"class":70}," productPrice",[48,1138,1139],{"class":66}," {\n",[48,1141,1142,1144,1146,1148,1150,1153,1155,1157,1159,1161,1163],{"class":50,"line":83},[48,1143,849],{"class":54},[48,1145,884],{"class":70},[48,1147,74],{"class":66},[48,1149,77],{"class":70},[48,1151,1152],{"class":66},"> productPrice ",[48,1154,99],{"class":54},[48,1156,102],{"class":58},[48,1158,884],{"class":70},[48,1160,74],{"class":66},[48,1162,77],{"class":70},[48,1164,111],{"class":66},[48,1166,1167,1169,1171],{"class":50,"line":114},[48,1168,802],{"class":54},[48,1170,120],{"class":70},[48,1172,123],{"class":66},[48,1174,1175],{"class":50,"line":126},[48,1176,129],{"class":66},[10,1178,1179,1180,1183],{},"This would signify to the compiler that all ",[34,1181,1182],{},"IList\u003CT>"," interfaces should be wired up to the productPrice variable unless explicitly defined and gives goto a whole new lease of life.",[10,1185,1186],{},[1187,1188,1189],"em",{},"[)amien",[1191,1192,1193],"style",{},"html pre.shiki code .s9HRq, html code.shiki .s9HRq{--shiki-default:#F57D26;--shiki-dark:#FF79C6}html pre.shiki code .smiwp, html code.shiki .smiwp{--shiki-default:#F85552;--shiki-dark:#FF79C6}html pre.shiki code .sPLAf, html code.shiki .sPLAf{--shiki-default:#3A94C5;--shiki-dark:#8BE9FD}html pre.shiki code .s6Vpi, html code.shiki .s6Vpi{--shiki-default:#5C6A72;--shiki-dark:#F8F8F2}html pre.shiki code .snuxY, html code.shiki .snuxY{--shiki-default:#3A94C5;--shiki-default-font-style:inherit;--shiki-dark:#8BE9FD;--shiki-dark-font-style:italic}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);}html pre.shiki code .sXAHl, html code.shiki .sXAHl{--shiki-default:#3A94C5;--shiki-dark:#FF79C6}html pre.shiki code .sS4Kt, html code.shiki .sS4Kt{--shiki-default:#8DA101;--shiki-dark:#50FA7B}html pre.shiki code .s7cAX, html code.shiki .s7cAX{--shiki-default:#5C6A72;--shiki-default-font-style:inherit;--shiki-dark:#FFB86C;--shiki-dark-font-style:italic}html pre.shiki code .sKO3f, html code.shiki .sKO3f{--shiki-default:#DF69BA;--shiki-default-font-style:inherit;--shiki-dark:#BD93F9;--shiki-dark-font-style:italic}html pre.shiki code .sSKRk, html code.shiki .sSKRk{--shiki-default:#35A77C;--shiki-dark:#F8F8F2}html pre.shiki code .sAO9U, html code.shiki .sAO9U{--shiki-default:#3A94C5;--shiki-default-font-style:inherit;--shiki-dark:#FFB86C;--shiki-dark-font-style:italic}",{"title":44,"searchDepth":83,"depth":83,"links":1195},[1196,1197,1199,1201,1203],{"id":133,"depth":83,"text":134},{"id":769,"depth":83,"text":1198},"Use inheritance to subclass List\u003CT>",{"id":816,"depth":83,"text":1200},"Expose IList\u003CProductPrice> property directly",{"id":932,"depth":83,"text":1202},"Introduce interface to declare IList\u003CProductPrice> available",{"id":1103,"depth":83,"text":1104},"Development","2007-08-06T12:58:00+00:00",".NET is often chided by C++ developers for failing to support multiple-inheritance. The reply is often Favor object composition over class inheritance, a mantra chanted from everywhere including the opening chapters of the Gang of Four’s Design Patterns book.","[object Object]","md",null,false,{},"\u002Fblog\u002F2007\u002Fmultiple-inheritance-composition-and-single-responsibility-principle-in-net",{"title":5,"description":1206},"blog\u002F2007\u002Fmultiple-inheritance-composition-and-single-responsibility-principle-in-net",[1216,1217],".NET","C#","\u002Fblog\u002F2007\u002Fmultiple-inheritance-composition-and-single-responsibility-principle-in-net\u002F",907,"TGvDoBlnqwxwHhB9Bs7p8BrWHV_mXcFJrogBxJQdieo",[1222,1226,1230],{"title":1223,"date":1224,"url":1225},"Transactions in the MongoDB EF Core Provider","2025-10-25","\u002Fblog\u002F2025\u002Fmongodb-explicit-transactions\u002F",{"title":1227,"date":1228,"url":1229},"Queryable Encryption with the MongoDB EF Core Provider","2025-09-22","\u002Fblog\u002F2025\u002Fmongodb-queryable-encryption\u002F",{"title":1231,"date":1232,"url":1233},"Lazy Loading with EF Core Proxies","2025-04-02","\u002Fblog\u002F2025\u002Fef-proxies\u002F",[],1780900531232]