{"id":13163,"date":"2010-08-12T07:00:00","date_gmt":"2010-08-12T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2010\/08\/12\/how-can-i-find-all-objects-of-a-particular-type\/"},"modified":"2010-08-12T07:00:00","modified_gmt":"2010-08-12T07:00:00","slug":"how-can-i-find-all-objects-of-a-particular-type","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20100812-00\/?p=13163","title":{"rendered":"How can I find all objects of a particular type?"},"content":{"rendered":"<p>\nMore than one customer has asked a question like this:\n<\/p>\n<blockquote CLASS=\"q\"><p>\nI&#8217;m looking for a way to search for all instances of a particular\ntype at runtime.\nMy goal is to invoke a particular method on each of those instances.\nNote that I did not create these object myself or have any other\naccess to them.\nIs this possible?\n<\/p><\/blockquote>\n<p>\nImagine what the world would be like if it were possible.\n<\/p>\n<p>\nFor starters, just imagine the fun you could have if you could\ncall <code>typeof(Secure&shy;String).Get&shy;Instances()<\/code>.\nVegas road trip!\n<\/p>\n<p>\nMore generally, it breaks the semantics of App&shy;Domain\nboundaries,\nsince grabbing all instances of a type lets you get objects from\nanother App&shy;Domain,\nwhich fundamentally violates the point of App&shy;Domains.\n(Okay, you could repair this by saying that the <code>Get&shy;Instances<\/code>\nmethod only returns objects from the current App&shy;Domain.)\n<\/p>\n<p>\nThis imaginary <code>Get&shy;Instances<\/code> method might return\nobjects which are awaiting finalization,\nwhich violates\none of the fundamental assumptions of a finalizer, namely that there\nare no references to the object:\nIf there were, then it wouldn&#8217;t be finalized!\n(Okay, you could repair this by saying that the <code>Get&shy;Instances<\/code>\nmethod does not return objects which are awaiting finalization.)\n<\/p>\n<p>\nOn top of that, you break\n<a HREF=\"http:\/\/www.codeproject.com\/KB\/books\/monitor_csharp_lock.aspx?display=Print#SyncRootPattern\">\nthe syncRoot pattern<\/a>.\n<\/p>\n<pre>\nclass Sample {\n private object syncRoot = new object();\n public void Method() {\n  lock(syncRoot) { ... };\n }\n}\n<\/pre>\n<p>If it were possible to get all objects of a particular class,\nthen anybody could just reach in and grab your private <code>sync&shy;Root<\/code>\nand call <code>Monitor.Enter()<\/code> on it.\nCongratuations, the private synchronization object you created\nis now a public one that anybody can screw with,\ndefeating the whole purpose of having a private syncRoot.\nYou can no longer reason about your syncRoot because you are no longer\nin full control of it.\n(Yes, this can already be done with reflection, but at least when\nreflecting, you know that you&#8217;re grabbing somebody&#8217;s private field\ncalled <code>sync&shy;Root<\/code>, so you already recognize that you&#8217;re\ndoing something dubious.\nWhereas with\n<code>Get&shy;Instances<\/code>,\nyou don&#8217;t know what each of the returned objects is being used for.\nHeck, you don&#8217;t even know if it&#8217;s being used!\nIt might just be garbage lying around waiting to be collected.)<\/p>\n<p>\nMore generally, code is often written on the expectation that\nan object that you never give out a reference to is not accessible\nto others.\nConsider the following code fragment:\n<\/p>\n<pre>\nusing (StreamWriter sr = new StreamWriter(fileName)) {\n sr.WriteLine(\"Hello\");\n}\n<\/pre>\n<p>\nIf it were possible to get all objects of a particular class,\nyou may find that your customers report that they are getting an\n<code>Object&shy;Disposed&shy;Exception<\/code>\non the call to <code>Write&shy;Line<\/code>.\nHow is that possible?\nThe disposal doesn&#8217;t happen until the close-brace, right?\nIs there a bug in the CLR where it&#8217;s disposing an object too soon?\n<\/p>\n<p>\nNope, what happened is that some other thread did exactly what the\ncustomer was asking for a way to do:\nIt grabbed all existing <code>Stream&shy;Writer<\/code> instances and\ninvoked <code>Stream&shy;Writer.Close<\/code> on them.\nIt did this immediately after you constructed the <code>Stream&shy;Writer<\/code>\nand before you did your <code>sr.Write&shy;Line()<\/code>.\nResult: When your <code>sr.Write&shy;Line()<\/code> executes, it finds\nthat the stream was already closed, and therefore the write fails.\n<\/p>\n<p>\nMore generally, consider the graffiti you could inject into all output\nfiles by doing\n<\/p>\n<pre>\nforeach (StreamWriter sr in typeof(StreamWriter).GetInstances()) {\n sr.Write(\"Kilroy was here!\");\n}\n<\/pre>\n<p>\nor even crazier\n<\/p>\n<pre>\nforeach (StringBuilder rb in typeof(StringBuilder).GetInstances()) {\n sb.Insert(0, \"DROP TABLE users; --\");\n}\n<\/pre>\n<p>\nNow no <code>String&shy;Builder<\/code> is safe&mdash;the contents of\nany <code>String&shy;Builder<\/code> can be corrupted at any time!\n<\/p>\n<p>\nIf you could obtain all instances of a type,\nthe fundamental logic behind computer programming breaks down.\nIt effectively becomes impossible to reason about code\nbecause anything could happen to\nyour objects <i>at any time<\/i>.\n<\/p>\n<p>\nIf you need to be able to get all instances of a class,\nyou need to add that functionality to the class itself.\n(<code>GC&shy;Handle<\/code> or <code>Weak&shy;Reference<\/code> will\ncome in handy here.)\nOf course, if you do this, then you clearly opted into\nthe &#8220;anything can happen to your object at any time outside\nyour control&#8221; model and presumably your code operates accordingly.\nYou made your bed; now you get to lie in it.\n<\/p>\n<p>\n(And I haven&#8217;t even touched on thread safety.)\n<\/p>\n<p>\n<b>Bonus reading<\/b>:\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/brada\/archive\/2003\/09\/28\/50391.aspx\">\nQuestionable value of SyncRoot on Collections<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>More than one customer has asked a question like this: I&#8217;m looking for a way to search for all instances of a particular type at runtime. My goal is to invoke a particular method on each of those instances. Note that I did not create these object myself or have any other access to them. [&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-13163","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>More than one customer has asked a question like this: I&#8217;m looking for a way to search for all instances of a particular type at runtime. My goal is to invoke a particular method on each of those instances. Note that I did not create these object myself or have any other access to them. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/13163","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=13163"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/13163\/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=13163"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=13163"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=13163"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}