{"id":17133,"date":"2009-08-12T10:00:00","date_gmt":"2009-08-12T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2009\/08\/12\/why-cant-i-pass-a-reference-to-a-derived-class-to-a-function-that-takes-a-reference-to-a-base-class-by-reference\/"},"modified":"2009-08-12T10:00:00","modified_gmt":"2009-08-12T10:00:00","slug":"why-cant-i-pass-a-reference-to-a-derived-class-to-a-function-that-takes-a-reference-to-a-base-class-by-reference","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20090812-00\/?p=17133","title":{"rendered":"Why can&#039;t I pass a reference to a derived class to a function that takes a reference to a base class by reference?"},"content":{"rendered":"<p>\n&#8220;Why can&#8217;t I pass a reference to a derived class\nto a function that takes a reference to a base class by reference?&#8221;\nThat&#8217;s a confusing question, but it&#8217;s phrased that way because\nthe simpler phrasing is wrong!\n<\/p>\n<p>\nThs misleading simplified phrasing of the question is\n&#8220;Why can&#8217;t I pass a reference to a derived class to a function that\ntakes a base class by reference?&#8221;\nAnd in fact the answer is &#8220;You can!&#8221;\n<\/p>\n<pre>\nclass Base { }\nclass Derived : Base { }\nclass Program {\n  static void f(Base b) { }\n  public static void Main()\n  {\n      Derived d = new Derived();\n      f(d);\n  }\n}\n<\/pre>\n<p>\nOur call to <code>f<\/code> passes a reference to the\nderived class\nto a function that takes a reference to the base class.\nThis is perfectly fine.\n<\/p>\n<p>\nWhen people ask this question, they are typically wondering\nabout passing a reference to the base class <i>by reference<\/i>.\nThere is a double indirection here.\nYou are passing a reference to a variable,\nand the variable is a reference to the base class.\nAnd it is this double reference that causes the problem.\n<\/p>\n<pre>\nclass Base { }\nclass Derived : Base { }\nclass Program {\n  static void f(<font COLOR=\"blue\">ref<\/font> Base b) { }\n  public static void Main()\n  {\n      Derived d = new Derived();\n      f(<font COLOR=\"blue\">ref<\/font> d); <font COLOR=\"blue\">\/\/ error<\/font>\n  }\n}\n<\/pre>\n<p>\nAdding the <code>ref<\/code> keyword to the parameter results\nin a compiler error:\n<\/p>\n<pre>\nerror CS1503: Argument '1': cannot convert from 'ref Derived' to 'ref Base'\n<\/pre>\n<p>\nThe reason this is disallowed is that it would allow you to violate\nthe type system.\nConsider:\n<\/p>\n<pre>\n  static void f(ref Base b) { b = new Base(); }\n<\/pre>\n<p>\nNow things get interesting.\nYour call to <code>f(ref d)<\/code> passes a reference to a\n<code>Derived<\/code> by reference.\nWhen the <code>f<\/code> function modifies its formal parameter <code>b<\/code>,\nit&#8217;s actually modifying your variable <code>d<\/code>.\nWhat&#8217;s worse, it&#8217;s putting a <code>Base<\/code> in it!\nWhen <code>f<\/code> returns, your variable <code>d<\/code>,\nwhich is declared as being a reference to a <code>Derived<\/code>\nis actually a reference to the base class <code>Base<\/code>.\n<\/p>\n<p>\nAt this point everything falls apart.\nYour program calls some method like <code>d.OnlyInDerived()<\/code>,\nand the CLR ends up executing a method on an object that doesn&#8217;t\neven support that method.\n<\/p>\n<p>\nYou actually knew this; you just didn&#8217;t know it.\nLet&#8217;s start from the easier cases and work up.\nFirst, passing a reference into a function:\n<\/p>\n<pre>\nvoid f(SomeClass s);\n...\n   T t = new T();\n   f(t);\n<\/pre>\n<p>\nThe function <code>f<\/code> expects to receive a reference to a\n<code>SomeClass<\/code>, but you&#8217;re passing a reference to a <code>T<\/code>.\nWhen is this legal?\n<\/p>\n<p>\n&#8220;Duh.\n<code>T<\/code> must be <code>SomeClass<\/code> or a class derived\nfrom <code>SomeClass<\/code>.&#8221;\n<\/p>\n<p>\nWhat&#8217;s good for the goose is good for the gander.\nWhen you pass a parameter as <code>ref<\/code>,\nit not only goes into the method, but it also comes out.\n(<a HREF=\"http:\/\/foldoc.org\/?call-by-value-result\">Not strictly true<\/a>\nbut close enough.)\nYou can think of it as a bidirectional parameter to the function call.\nTherefore, the rule &#8220;If a function expects a reference to a class,\nyou must provide a reference to that class or a derived class&#8221;\napplies in both directions.\nWhen the parameter goes in, you must provide a reference to that\nclass or a derived class.\nAnd when the parameter comes out,\nit also must be a reference to that class or a derived class\n(because the function is &#8220;passing the parameter&#8221; back to you, the caller).\n<\/p>\n<p>\nBut the only time that <code>S<\/code> can be <code>T<\/code> or a subclass,\nwhile simultaneously having\n<code>T<\/code> be <code>S<\/code> or a subclass\nis when <code>S<\/code> and <code>T<\/code> are the same thing.\nThis is just the law of antisymmetry for partially-ordered sets:\n&#8220;if <i>a<\/i>&nbsp;&le;&nbsp;<i>b<\/i>\nand <i>b<\/i>&nbsp;&le;&nbsp;<i>a<\/i>,\nthen <i>a<\/i>&amp;nbsp=&nbsp;<i>b<\/i>.&#8221;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;Why can&#8217;t I pass a reference to a derived class to a function that takes a reference to a base class by reference?&#8221; That&#8217;s a confusing question, but it&#8217;s phrased that way because the simpler phrasing is wrong! Ths misleading simplified phrasing of the question is &#8220;Why can&#8217;t I pass a reference to a derived [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-17133","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>&#8220;Why can&#8217;t I pass a reference to a derived class to a function that takes a reference to a base class by reference?&#8221; That&#8217;s a confusing question, but it&#8217;s phrased that way because the simpler phrasing is wrong! Ths misleading simplified phrasing of the question is &#8220;Why can&#8217;t I pass a reference to a derived [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17133","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=17133"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17133\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=17133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=17133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=17133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}