<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kelly Brown</title>
    <description>The latest articles on DEV Community by Kelly Brown (@thebuzzsaw).</description>
    <link>https://dev.to/thebuzzsaw</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F192750%2Fe61e2721-e7b0-4f95-b59e-4843aa136ccc.png</url>
      <title>DEV Community: Kelly Brown</title>
      <link>https://dev.to/thebuzzsaw</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thebuzzsaw"/>
    <language>en</language>
    <item>
      <title>Introducing Jawbone Sockets</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Sun, 01 Jun 2025 18:27:40 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/introducing-jawbone-sockets-ah0</link>
      <guid>https://dev.to/thebuzzsaw/introducing-jawbone-sockets-ah0</guid>
      <description>&lt;p&gt;Hi! Sorry I'm so wildly inconsistent about blogging. I've just been hard at work on a lot of things. :)&lt;/p&gt;

&lt;p&gt;I ranted previously about &lt;a href="https://dev.to/thebuzzsaw/jawbone-networking-motivation-5ek4"&gt;the awful state of .NET socket libraries&lt;/a&gt; for game devs. I originally developed my new socket library inside the confines of my Jawbone lib, but the project evolved enough and sparked enough interest from third parties that I decided it was worth spinning off into its own focused project.&lt;/p&gt;

&lt;p&gt;Introducing... &lt;a href="https://github.com/ObviousPiranha/Jawbone.Sockets" rel="noopener noreferrer"&gt;Jawbone.Sockets&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Be sure to &lt;a href="https://github.com/ObviousPiranha/Jawbone.Sockets/blob/main/README.md#design" rel="noopener noreferrer"&gt;take a tour&lt;/a&gt; to become familiar with the API design. The sockets perform zero allocation (beyond the socket creation itself), and they indeed perform better than &lt;code&gt;System.Net&lt;/code&gt; sockets, but the more time I spend with this library, the more I just enjoy the drastically simplified design. &lt;code&gt;Span&amp;lt;T&amp;gt;&lt;/code&gt; is the heart and soul of everything in this library.&lt;/p&gt;

&lt;h2&gt;
  
  
  IpAddress Internals
&lt;/h2&gt;

&lt;p&gt;I do want to draw attention to a few things that are not in the tour. It took me a while to settle on how I wanted to structure &lt;code&gt;IpAddressV4&lt;/code&gt; and &lt;code&gt;IpAddressV6&lt;/code&gt;. I had a recurring issue where I wanted to reinterpret the data in the address depending on the context. IPv4 addresses are sometimes bytes but sometimes just a whole &lt;code&gt;UInt32&lt;/code&gt;. IPv6 addresses are sometimes bytes, sometimes an array of &lt;code&gt;UInt16&lt;/code&gt;, and sometimes an array of &lt;code&gt;UInt32&lt;/code&gt;. Initially, I tackled this by simply exposing a bunch of methods that converted the address to a respective span, but I later noticed the recent addition of &lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-12.0/inline-arrays" rel="noopener noreferrer"&gt;inline arrays&lt;/a&gt;. I was not a fan at first. They seemed clunky and hard to use, but once I discovered that they implicitly convert to spans, I knew it was the way forward.&lt;/p&gt;

&lt;p&gt;So, &lt;code&gt;IpAddressV4&lt;/code&gt; and &lt;code&gt;IpAddressV6&lt;/code&gt; are both just union structs. They have multiple ways to access the underlying data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IpAddressV4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataU8&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Changed to 10.0.0.15.&lt;/span&gt;

&lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataU32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Capture entire address.&lt;/span&gt;

&lt;span class="c1"&gt;// Fancy way of initializing 2001:db8:4006:812::200e&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;v6&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IpAddressV6&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromHostU16&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="m"&gt;0x2001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0xdb8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0x4006&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0x812&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0x200e&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Captures the 0x4006 in network order!&lt;/span&gt;
&lt;span class="kt"&gt;ushort&lt;/span&gt; &lt;span class="n"&gt;segment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v6&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataU16&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Set every byte to 0xab via span!&lt;/span&gt;
&lt;span class="n"&gt;v6&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataU8&lt;/span&gt;&lt;span class="p"&gt;[..].&lt;/span&gt;&lt;span class="nf"&gt;Fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0xab&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Walk each 32-bit chunk.&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;v6&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataU32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This union approach made implementing other aspects of the structs trivial. Constructing, parsing, formatting, hashing, and equating all hugely benfited from this flexibility. (And none of it required inheritance, allocations, or dynamic dispatch.)&lt;/p&gt;

&lt;p&gt;These IP address types are exactly as big as they need to be, so they pack tightly. This makes them good for use cases such as keys in a dictionary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generic Addressing
&lt;/h2&gt;

&lt;p&gt;Splitting IP addresses into two concrete types obviously presents a few problems. What if an application wants to support both IPv4 and IPv6? Does that mean there has to be two complete implementations of everything?&lt;/p&gt;

&lt;p&gt;Well yes... but no. At least, no one should be &lt;em&gt;typing&lt;/em&gt; out two complete implementations. Both &lt;code&gt;IpAddressV4&lt;/code&gt; and &lt;code&gt;IpAddressV6&lt;/code&gt; implement &lt;code&gt;IIpAddress&amp;lt;T&amp;gt;&lt;/code&gt;, so as long as the communications subsystem is generic, it can handle both no problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MultiplayerSystem&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;unmanaged&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IIpAddress&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PlayerSessionInfo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_sessions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IUdpSocket&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_serverSocket&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MultiplayerSystem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IUdpSocket&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;serverSocket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_serverSocket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serverSocket&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Much of the functionality provided by &lt;code&gt;IIpAddress&amp;lt;T&amp;gt;&lt;/code&gt; is possible thanks to &lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/static-virtual-interface-members" rel="noopener noreferrer"&gt;static virtual members interfaces&lt;/a&gt;. Any generic code is still free to parse text via &lt;code&gt;T.Parse(...)&lt;/code&gt; or target localhost by way of &lt;code&gt;T.Local&lt;/code&gt;. Naturally, there are non-static methods available as well such as &lt;code&gt;address.IsLoopback&lt;/code&gt; (where &lt;code&gt;address&lt;/code&gt; is &lt;code&gt;T&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Despite everything I've said, there &lt;em&gt;is&lt;/em&gt; also a storage type called &lt;code&gt;IpAddress&lt;/code&gt;. It's another struct that simply uses an enum to track whether it's holding an IPv4 address or IPv6 address. This is handy for code that &lt;em&gt;really&lt;/em&gt; doesn't care, but it's worth noting that this container doesn't interact with sockets at all. The sockets expect specific address types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;For now, the lib only targets .NET 9. I may add support for .NET 8 if support doesn't end by the time I polish everything up for a 1.0 release. I'm using this lib in a couple projects of my own. Once I have a substantial application to demonstrate this package's viability, I'll feel better about going GA.&lt;/p&gt;

&lt;p&gt;If you're interested, &lt;a href="https://github.com/ObviousPiranha/Jawbone.Sockets/blob/main/README.md#design" rel="noopener noreferrer"&gt;take the tour&lt;/a&gt;, grab the latest package on &lt;a href="https://www.nuget.org/packages/Jawbone.Sockets/" rel="noopener noreferrer"&gt;NuGet&lt;/a&gt;, and tell me what you think!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Jawbone Networking Motivation</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Sat, 10 Jun 2023 17:34:32 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/jawbone-networking-motivation-5ek4</link>
      <guid>https://dev.to/thebuzzsaw/jawbone-networking-motivation-5ek4</guid>
      <description>&lt;p&gt;Some quick context: &lt;a href="https://dev.to/thebuzzsaw/jawbone-a-new-game-dev-library-for-net-5-537j"&gt;Jawbone is my game library&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Motivation
&lt;/h1&gt;

&lt;p&gt;The big secret game project I'm working on right now is multiplayer and uses UDP for its networking. Naturally, at the start of all this, I looked inside .NET itself since there are classes for working with UDP, but I found myself unable to stomach the offerings there. I have a couple requirements of the code I work with in game dev.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First, allocations must be kept to a minimum.&lt;/strong&gt; In C#, this usually means I wanna see two things: structs and spans. Where possible, I want to keep things off the heap: structs sit nicely on the stack in local contexts. From there, if I must use the heap, I want data packed tightly, and structs sit nicely side-by-side in an array or in the body of another class/struct. And lastly, I want to slice my arrays freely. If I need to work with some portion of an array, spans let me do that without copying the whole array. Also, circling back the first point in this paragraph, if I must allocate memory, I don't want my library code doing that invisibly. Let me allocate my own byte arrays &lt;em&gt;once&lt;/em&gt; and simply reuse them by way of &lt;code&gt;Span&amp;lt;byte&amp;gt;&lt;/code&gt; and &lt;code&gt;ReadOnlySpan&amp;lt;byte&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second, dynamic dispatch must be kept to a minimum.&lt;/strong&gt; This impacts both performance and readability. Where possible, I don't want my code branching like crazy when performing a straightforward operation. I don't need polymorphism most of the time. I don't need last-minute runtime decisions most of the time. I frequently know the truth up front and would like to compile that truth into my engine.&lt;/p&gt;

&lt;p&gt;So, how do the UDP classes in .NET measure up to these standards? Well, they're not great. Please note that I understand that classes in the core libraries aspire to be all things to all people &lt;em&gt;and&lt;/em&gt; are dealing with decades of legacy code/usage by this point. I'm not attacking the people who made this. Regardless, I feel there is value in explaining exactly what could be improved for contexts like mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  System.Net.Sockets.UdpClient
&lt;/h2&gt;

&lt;p&gt;Let's look at the main contender: &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.udpclient?view=net-7.0"&gt;UdpClient&lt;/a&gt;. Right out of the gate, I'm not thrilled with the design. &lt;/p&gt;

&lt;p&gt;First off, I'm not going to touch &lt;code&gt;ReceiveAsync&lt;/code&gt; or &lt;code&gt;BeginReceive&lt;/code&gt;/&lt;code&gt;EndReceive&lt;/code&gt;. I love async C# but not in game dev. So, that just leaves me with &lt;code&gt;Receive&lt;/code&gt; (&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.udpclient.receive?view=net-7.0#system-net-sockets-udpclient-receive(system-net-ipendpoint@)"&gt;docs&lt;/a&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="nf"&gt;Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;IPEndPoint&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;remoteEP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the problem? Well, there are two problems, but we'll get to the other problem later. The method allocates and returns a byte array. I find it strange there is no overload that accepts a &lt;code&gt;Span&amp;lt;byte&amp;gt;&lt;/code&gt; yet to let me fill my own buffer. The &lt;code&gt;Send&lt;/code&gt; method has already received some love.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ReadOnlySpan&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;datagram&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;IPEndPoint&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;endPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You know what's funny? Take a look at the &lt;a href="https://github.com/dotnet/runtime/blob/da1da02bbd2cb54490b7fc22f43ec32f5f302615/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UDPClient.cs#L832"&gt;source code&lt;/a&gt; for &lt;code&gt;Receive&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;received&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReceiveFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MaxUDPSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;tempRemoteEP&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;remoteEP&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IPEndPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;tempRemoteEP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// because we don't return the actual length, we need to ensure the returned buffer&lt;/span&gt;
&lt;span class="c1"&gt;// has the appropriate length.&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;received&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;MaxUDPSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;newBuffer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;received&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BlockCopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;received&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;newBuffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It writes to an interim buffer &lt;em&gt;anyway&lt;/em&gt;. C'mon! Just let me pass in a &lt;code&gt;Span&amp;lt;byte&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  System.Net.Sockets.Socket
&lt;/h2&gt;

&lt;p&gt;Oh well. That's not gonna work. So, let's move onto the next contender: &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket?view=net-7.0"&gt;Socket&lt;/a&gt;. This looks much better. It's lower level. It provides nearly direct access to the socket itself. And right out of the gate, it solves the primary allocation problem (&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.receivefrom?view=net-7.0#system-net-sockets-socket-receivefrom(system-span((system-byte))-system-net-endpoint@)"&gt;docs&lt;/a&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;ReceiveFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Span&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;EndPoint&lt;/span&gt; &lt;span class="n"&gt;remoteEP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sending is fine too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;SendTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ReadOnlySpan&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;EndPoint&lt;/span&gt; &lt;span class="n"&gt;remoteEP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, now what? We solved &lt;em&gt;most&lt;/em&gt; of the allocation problem... but now we are contending with the lovely address/endpoint classes, which also introduces dynamic dispatch.&lt;/p&gt;

&lt;h2&gt;
  
  
  System.Net.IPAddress
&lt;/h2&gt;

&lt;p&gt;As cool as it is that .NET supports a royal cacophony of &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.addressfamily?view=net-7.0"&gt;address families&lt;/a&gt;, all we really care about is IPv4 and IPv6. Of the two, IPv4 is arguably the most important even today, but supporting both is straightforward. (Seriously, think about just how many games would break if IPv4 ceased being an option.)&lt;/p&gt;

&lt;p&gt;So, that brings us to &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.net.ipaddress?view=net-7.0"&gt;IPAddress&lt;/a&gt;, which is the catchall datatype for socket addresses either IPv4 or IPv6.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strike 1: Heap objects
&lt;/h3&gt;

&lt;p&gt;So, this class has decided that all instances must live in the heap. Thanks for that. Oh, but it &lt;a href="https://github.com/dotnet/runtime/blob/da1da02bbd2cb54490b7fc22f43ec32f5f302615/src/libraries/System.Net.Primitives/src/System/Net/IPAddress.cs#L44"&gt;gets better&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;/// This field is only used for IPv6 addresses. A null value indicates that this instance is an IPv4 address.&lt;/span&gt;
&lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;ushort&lt;/span&gt;&lt;span class="p"&gt;[]?&lt;/span&gt; &lt;span class="n"&gt;_numbers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, an IPv6 address is &lt;strong&gt;two heap objects&lt;/strong&gt;. Wonderful. It just gets worse as you go down the method list. Requesting the address in bytes allocates a byte array for you. Again, I know this is a casualty of the C# mantra of 2005 ("Allocations are free! The garbage collector will save us all!"), but this was honestly never necessary. There should have been allocation-free ways of doing this.&lt;/p&gt;

&lt;p&gt;From there, more heap layers join the party thanks to &lt;code&gt;EndPoint&lt;/code&gt; &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.net.endpoint?view=net-7.0"&gt;itself being an abstract class&lt;/a&gt;. All an "endpoint" needs to do is combine an address and a port.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strike 2: Invisible caching
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;/// A lazily initialized cache of the result of calling &amp;lt;see cref="ToString"/&amp;gt;.&lt;/span&gt;
&lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;_toString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;/// A lazily initialized cache of the &amp;lt;see cref="GetHashCode"/&amp;gt; value.&lt;/span&gt;
&lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;_hashCode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I mean, this doesn't bother me &lt;em&gt;too much&lt;/em&gt;. I appreciate that the devs are keeping an eye on performance for the typical coder who just wants to Get Things Done™. Caching the hash code feels odd to me given that hash codes should always be relatively fast.&lt;/p&gt;

&lt;p&gt;Regardless, I don't want to see this behavior native to a type. I'd rather have a &lt;code&gt;Cached&amp;lt;T&amp;gt;&lt;/code&gt; wrapper for special cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strike 3: Object-Oriented Nonsense
&lt;/h3&gt;

&lt;p&gt;So, an &lt;code&gt;IPAddress&lt;/code&gt; can be either an IPv4 address &lt;em&gt;or&lt;/em&gt; an IPv6 address. I &lt;em&gt;think&lt;/em&gt; I understand the desired convenience here: you don't &lt;em&gt;really&lt;/em&gt; care what kind of address it is; you just want to store it one place. My problem is that there really isn't a situation where I need or want that.&lt;/p&gt;

&lt;p&gt;If I open a socket and bind it to an IPv4 address, all addresses are 32 bits. If I bind it to an IPv6 address, all addresses are 128 bits. If I want to operate my socket in dual mode, the addresses are still always represented using 128 bits; an IPv4 address is simply &lt;a href="https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses"&gt;represented in a special format&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If I know the exact sizes of my addresses &lt;em&gt;before&lt;/em&gt; even opening the socket, why should I pay the price of all this garbage collector activity?&lt;/p&gt;

&lt;h1&gt;
  
  
  We can do better
&lt;/h1&gt;

&lt;p&gt;Even setting aside all my gripes about allocations or performance, I just want a simpler API for working with UDP. In my next post, I'll cover the basics of networking in &lt;a href="https://github.com/ObviousPiranha/Jawbone"&gt;Jawbone&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>C# Namespace Fever</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Sun, 28 May 2023 16:39:32 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/c-namespace-fever-3a8b</link>
      <guid>https://dev.to/thebuzzsaw/c-namespace-fever-3a8b</guid>
      <description>&lt;p&gt;Alright... I'm done chopping my code into microscopic namespaces. There's just no point. All it does is force a bunch of &lt;code&gt;using&lt;/code&gt; statements all over the code (both in the project itself and in any project consuming it as a library).&lt;/p&gt;

&lt;p&gt;The most common place I see this unhealthy obsession is in your typical ASP.NET app. Devs feel this compulsion to make a namespace for every &lt;em&gt;kind&lt;/em&gt; of component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyApp.Web.Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyApp.Web.Models&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyApp.Web.Services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyApp.Web.Utils&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is a &lt;em&gt;kind&lt;/em&gt; representation. I've even seen projects isolate &lt;code&gt;Models.Request&lt;/code&gt; from &lt;code&gt;Models.Response&lt;/code&gt;. Personally, I do not think this is necessary or helpful. In my more recent endeavors, I've settled on just using &lt;code&gt;MyApp.Web&lt;/code&gt; and stopping there. It gets rid of a ton of useless &lt;code&gt;using&lt;/code&gt; statements, and all the identifiers I need are now properly visible. I still find it acceptable to put the other whole layers into separate namespaces (&lt;code&gt;MyApp.Domain&lt;/code&gt;, &lt;code&gt;MyApp.Repository&lt;/code&gt;, etc.).&lt;/p&gt;

&lt;p&gt;I fell prey to this in &lt;a href="https://github.com/ObviousPiranha/Jawbone"&gt;Jawbone&lt;/a&gt;. I think there is just something alluring about "being as cool as the .NET base classes". Hey, .NET has a namespace for its collections, so I should have a namespace for my collections! There's just one problem, though: .NET is huge, and my library is not. When you reach a certain size, it makes sense to gently categorize various components. Also, if code exists in distinct projects, having a different namespace makes sense.&lt;/p&gt;

&lt;p&gt;So, I've taken the first steps to wrangling this mess. I am eliminating the &lt;code&gt;Piranha.Jawbone.Tools&lt;/code&gt; and &lt;code&gt;Piranha.Jawbone.Collections&lt;/code&gt; namespaces. In my mind, there are only two scenarios that justify a new namespace:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Strongly distinct domains: I am keeping namespaces such as &lt;code&gt;Piranha.Jawbone.Sqlite&lt;/code&gt; and &lt;code&gt;Piranha.Jawbone.Sdl&lt;/code&gt;. Those are &lt;em&gt;highly cohesive domains&lt;/em&gt; that could arguably even be spun off into their own libraries if the need arose. They revolve around major native components and have clear delineation.&lt;/li&gt;
&lt;li&gt;Isolation of extensions on common datatypes: if I want to introduce extensions for common types like &lt;code&gt;string&lt;/code&gt; or &lt;code&gt;DateTime&lt;/code&gt; or whatever, I don't want those extensions flooding devs' autocomplete. It's polite to let them opt in by &lt;code&gt;using Piranha.Jawbone.Extensions&lt;/code&gt;. They should not pay that price just for &lt;code&gt;using Piranah.Jawbone&lt;/code&gt;. Meanwhile, for new datatypes introduced by Jawbone itself, the extensions just sit in the &lt;code&gt;Piranha.Jawbone&lt;/code&gt; namespace.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Already, I am enjoying the drastic reduction in &lt;code&gt;using&lt;/code&gt; statements.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Jawbone: a new game dev library for .NET 5</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Wed, 30 Dec 2020 04:07:15 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/jawbone-a-new-game-dev-library-for-net-5-537j</link>
      <guid>https://dev.to/thebuzzsaw/jawbone-a-new-game-dev-library-for-net-5-537j</guid>
      <description>&lt;p&gt;(Obviously, time has passed, and I'm targeting .NET 7 now.)&lt;/p&gt;

&lt;p&gt;I want to develop cross-platform games in modern C#. I have effectively retired from C++; I want to build my little game dev empire in the latest version of .NET. Frankly, I want nothing to do with .NET Framework or Mono anymore.&lt;/p&gt;

&lt;p&gt;After a bunch of research and lots of disappointment (a whole blog post for another day), I have begun development of a new cross-platform game library. It is called &lt;a href="https://github.com/ObviousPiranha/Jawbone"&gt;Jawbone&lt;/a&gt; because it is a super important part of the piranha! (My company is "Obvious Piranha". That's the reference.) This middleware will simplify deploying to Windows, Mac, and Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;This library provides access to &lt;a href="https://www.libsdl.org/"&gt;SDL 2&lt;/a&gt;, OpenGL, &lt;a href="https://openal-soft.org/"&gt;OpenAL&lt;/a&gt;, &lt;a href="https://github.com/nothings/stb"&gt;STB&lt;/a&gt; (images, fonts, and Vorbis), and &lt;a href="https://www.sqlite.org/index.html"&gt;SQLite 3&lt;/a&gt;. In addition to raw access, there are abstractions that make working with these tools less painful.&lt;/p&gt;

&lt;p&gt;The entire library makes use of &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references"&gt;nullable references&lt;/a&gt;. This will make it absolutely clear to consumers when &lt;code&gt;null&lt;/code&gt; is an acceptable value. Jawbone will also make use of &lt;a href="https://docs.microsoft.com/en-us/archive/msdn-magazine/2018/january/csharp-all-about-span-exploring-a-new-net-mainstay"&gt;spans&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Continuing the tradition of projects such as SQLite and STB, all source code for Jawbone is public domain.&lt;/p&gt;

&lt;p&gt;The native libraries are also all dynamically loaded, which makes it easier to pick and choose the components important to you. The native libraries are &lt;em&gt;not&lt;/em&gt; automatically included. (Also, see &lt;a href="https://github.com/ObviousPiranha/PiranhaNative"&gt;this repo&lt;/a&gt; for building the public domain libraries for use with Jawbone.) This helps avoid inadvertently including a bunch of native binaries in a project that only wanted the C# code.&lt;/p&gt;

&lt;p&gt;Jawbone makes heavy use of &lt;a href="https://dev.to/thebuzzsaw/dependency-injection-in-game-dev-1hdh"&gt;dependency injection&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are many more individual features I hope to detail in future posts!&lt;/p&gt;

&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;p&gt;Before anyone becomes too excited, it is important to understand that the library is in a wildly immature state. The API contract is unstable and undocumented. I will most certainly post updates later on as the API matures. I have plans for three major phases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version 0
&lt;/h3&gt;

&lt;p&gt;I am working on two games using this library. As a result, the design will shift every day. Building real games will help me harden the library's design and add needed features, but the library will be completely filled with sharp edges. It will be unfit for public consumption in this state as it will continue to be undocumented and incomplete as there will most certainly be features that &lt;em&gt;other&lt;/em&gt; games need that my games happen to omit.&lt;/p&gt;

&lt;p&gt;If you are a daring developer and choose to dive into the code at this stage, just know that you will run into things that don't make sense as there is still code leftover from when I began pursuing one design and shifted over to another. :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Version 1
&lt;/h3&gt;

&lt;p&gt;After completion of those two games, I will revisit the library and begin removing those sharp edges. I will refine the API into a user-friendly contract that makes sense and form &lt;a href="https://blog.codinghorror.com/falling-into-the-pit-of-success/"&gt;pits of success&lt;/a&gt;. There will be documentation explaining proper use of the library as well more sample code. Completion of this phase is when I'll feel more comfortable spreading the news to places like Reddit and submitting binary builds to Nuget. :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Version 2
&lt;/h3&gt;

&lt;p&gt;Eventually, I want to reduce reliance on raw access to the various native libraries. Raw access will always be an option for power users, but I want to build an abstraction that is nice to use without sacrificing performance. I anticipate adding more robust access to OpenGL ES and Vulkan in this version as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sneak Peek
&lt;/h2&gt;

&lt;p&gt;To see the framework in action, I released a &lt;a href="https://github.com/ObviousPiranha/Jawbone/releases/tag/v0.0.0.1"&gt;binary build&lt;/a&gt; of the sample application (currently Windows 64-bit only). Enjoy!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Less Magic, Please</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Sat, 12 Dec 2020 19:29:41 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/less-magic-please-3kil</link>
      <guid>https://dev.to/thebuzzsaw/less-magic-please-3kil</guid>
      <description>&lt;p&gt;I haven't posted in a while. I need to fix that. I have a lot of topics I wish to discuss in the near future. For now, here's a quick thought.&lt;/p&gt;

&lt;p&gt;C# delegates are great, aren't they?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;DoTheThing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how I invoked that delegate? I simply treated it like a method: &lt;code&gt;handler(_data)&lt;/code&gt;. The issue is that delegates are objects, not methods. I've noticed in my own code that I've taken to writing this instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I never &lt;em&gt;consciously&lt;/em&gt; decided to invoke my delegates this way. It sort of just happened. Reflecting on this, I realized that being able to call delegates directly as if they are methods kinda hurts readability. I want my code to be just a bit more explicit. Let's look at another example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Huh? What's going on here? Why bother with the &lt;code&gt;== true&lt;/code&gt; part? Let's simplify that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's better. Except... C# is angry now.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cannot implicitly convert type 'bool?' to 'bool'. An explicit conversion exists (are you missing a cast?)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ooooooh. I get it. The &lt;code&gt;== true&lt;/code&gt; part is a sneaky workaround to the fact that &lt;code&gt;flag&lt;/code&gt; is a &lt;code&gt;bool?&lt;/code&gt; or &lt;code&gt;Nullable&amp;lt;bool&amp;gt;&lt;/code&gt;. In that case, I have a preferred way to handle this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValueOrDefault&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See, I don't like obscuring the fact that &lt;code&gt;flag&lt;/code&gt; is a &lt;code&gt;Nullable&amp;lt;bool&amp;gt;&lt;/code&gt;. I don't want to pretend that it's a flavored &lt;code&gt;bool&lt;/code&gt;. The fact is &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; is its own type with its own rules. The code above makes it &lt;em&gt;abundantly&lt;/em&gt; clear to any reader that we are dealing with a &lt;code&gt;bool?&lt;/code&gt; and not a &lt;code&gt;bool&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agree or disagree. I like comments and discussion.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Dependency Injection in Game Dev</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Mon, 17 Aug 2020 04:44:07 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/dependency-injection-in-game-dev-1hdh</link>
      <guid>https://dev.to/thebuzzsaw/dependency-injection-in-game-dev-1hdh</guid>
      <description>&lt;p&gt;I am a huge fan of dependency injection. It is a central theme in &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1"&gt;ASP.NET Core&lt;/a&gt;, which I use extensively. In recent weeks, I became specifically interested in the dependency injection components themselves and learned how to use them outside of ASP.NET Core. It's remarkably simple to create your own &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.servicecollection?view=dotnet-plat-ext-3.1"&gt;ServiceCollection&lt;/a&gt;, populate it with services, and then build a &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.serviceprovider?view=dotnet-plat-ext-3.1"&gt;ServiceProvider&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While that's all well and good, web development was the only domain I could think of where dependency injection would help. After all, server applications are long-running programs that need to juggle lots of components and connect everything together. I did not anticipate my interest in dependency injection and my interest in game dev colliding.&lt;/p&gt;

&lt;p&gt;Here is an idea of the code powering top level systems in my engine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LibraryMapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ISqlite3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;nativeDll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SqliteExtensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResolveName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LibraryMapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IStb&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;nativeDll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StbExtensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResolveName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;al&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OpenAlLoader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoadOpenAl&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;audio&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AudioRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;al&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sdl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SdlLoader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoadSdl&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;windowManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WindowManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sdl&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So, not only do these systems need to initialize at the beginning, they need to be cleaned up at the end. From there, the systems begin progressively feeding in subsequent systems: &lt;code&gt;AudioRenderer&lt;/code&gt; requires &lt;code&gt;IOpenAl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Originally, I was happy with this approach. I like how explicit and straightforward the code is. The order of events is clear. The object lifetimes are clear. What's not to like?&lt;/p&gt;

&lt;p&gt;I started adding new subsystems. The first thing I did was begin replacing all calls to &lt;code&gt;Console.WriteLine&lt;/code&gt; with calls to an instance of &lt;code&gt;ILogger&lt;/code&gt;. This meant configuring the logging system up front and then injecting the logger into every system that is interested.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;loggerProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ConsoleLoggerProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;LocalConsoleLoggerOptions&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;loggerProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;audio&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AudioRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;windowManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WindowManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sdl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This one example wasn't that bad, but I began extracting internal subsystems and injecting them into the necessary main system because I needed access to those subsystems from other main systems. This outer method became somewhat of a nightmare to read and maintain. There were &lt;em&gt;many&lt;/em&gt; local variables feeding into &lt;em&gt;many&lt;/em&gt; constructors for various systems. I often had to return to the outer method, add stuff, reorder stuff, and come up with a dozen more variable names.&lt;/p&gt;

&lt;p&gt;The nice thing about dependency injection frameworks is that they remove the burden of initializing and disposing services in the correct order. So, I decided to look into replacing all this with dependency injection. I was just going to run a little experiment. If I hated it, I could just revert it.&lt;/p&gt;

&lt;p&gt;So, I made a service collection...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ServiceCollection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;...and filled it with stuff...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;services&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddLogging&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetMinimumLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trace&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddConsole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IncludeScopes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DisableColors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSqlite3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nativeDll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddStb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nativeDll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOpenAl&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSdl2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AudioRenderer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;WindowManager&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Renderer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddMetricRepository&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;...and built a service provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Make sure I didn't mess up.&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ServiceProviderOptions&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ValidateScopes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ValidateOnBuild&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;serviceProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceCollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BuildServiceProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, I can pull services out, perform additional initialization, and start the game.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;windowManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;WindowManager&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;windowManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I gotta say: I'm &lt;em&gt;very&lt;/em&gt; happy with the result. I was worried about losing the clarity of performing all these operations manually, but I much prefer the agility I'm afforded with this deferred initialization. Now, if I want to pull a subsystem into another system, it's as simple as adding it to the constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ImportantSystem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ImportantSystem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ItemSystem&lt;/span&gt; &lt;span class="n"&gt;itemSystem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CraftingSystem&lt;/span&gt; &lt;span class="n"&gt;craftingSystem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I do not have to go back to the outer method, call the new constructor, pass the dependencies in, and possibly change the order of initialization. I also gain a new superpower: I can &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.activatorutilities.createinstance?view=dotnet-plat-ext-3.1#Microsoft_Extensions_DependencyInjection_ActivatorUtilities_CreateInstance__1_System_IServiceProvider_System_Object___"&gt;spawn objects and automatically inject all of its dependencies&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ActivatorUtilities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateInstance&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;serviceProvider&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I highly doubt I am the first one to have this idea of using DI in a game engine, but it was satisfying to leverage a new bit of tech and simplify the code. Have you leveraged dependency injection outside of web development before? How did it go?&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>What else would I change in a C# rewrite?</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Sat, 06 Jun 2020 22:38:57 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/what-else-would-i-change-in-a-c-rewrite-3h64</link>
      <guid>https://dev.to/thebuzzsaw/what-else-would-i-change-in-a-c-rewrite-3h64</guid>
      <description>&lt;p&gt;Just reiterating: I love C#. I will use it forever. These are just thoughts about how I would approach a spinoff language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Immutable Arrays
&lt;/h2&gt;

&lt;p&gt;Increasingly, I wish &lt;code&gt;T[]&lt;/code&gt; was immutable. It makes perfect sense that strings are immutable. As a result, there is cognitive dissonance in arrays being mutable. I wish I could concatenate two arrays the way I concatenate two strings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.string.create"&gt;.NET Core 2.1 introduced&lt;/a&gt; &lt;code&gt;string.Create&lt;/code&gt;, which gives you temporary mutable access to the string's storage (&lt;code&gt;Span&amp;lt;char&amp;gt;&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TState&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;SpanAction&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A similar solution would work for arrays to avoid unnecessary copies. There could also be an overload that handles one element at a time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TState&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;valueGenerator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Eliminate Multicast Delegate
&lt;/h2&gt;

&lt;p&gt;I can't remember the original reason for this decision. I believe it was done to support events in GUI frameworks.&lt;/p&gt;

&lt;p&gt;It is easy to compose a custom multicast delegates from monocast delegates, but the reverse is simply not possible. We all pay for the cost of multicast delegates even though up to 100% of delegates in a project are monocast. That's an unfortunate fee for using delegates at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix &lt;code&gt;switch&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;switch&lt;/code&gt; statement was lifted straight from C/C++.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;DoTheThing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;DoTheOtherThing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;DoAnotherThing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;DoDefaultThing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's just adopt the if-statement scope rules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;DoTheThing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;DoTheOtherThing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;DoAnotherThing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt;
        &lt;span class="nf"&gt;DoDefaultThing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Sealed by Default
&lt;/h2&gt;

&lt;p&gt;I don't think classes should be open to extension by default. Inheritance is a very particular superpower in the OOP landscape. I feel that a given class should have to &lt;em&gt;invite&lt;/em&gt; inheritance rather than &lt;em&gt;restrict&lt;/em&gt; inheritance. In other words, switch to opt-in rather than opt-out.&lt;/p&gt;

&lt;p&gt;A class could invite inheritance by marking itself with either &lt;code&gt;abstract&lt;/code&gt; (which requires inheritance anyway) or some other keyword like &lt;code&gt;base&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Widget&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Drop Multidimensional Arrays
&lt;/h2&gt;

&lt;p&gt;Treating an array as multidimensional data belongs to abstractions. Force developers to explicitly decide whether the grid is row-major, column-major, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drop &lt;code&gt;Equals&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The object virtual method &lt;code&gt;Equals&lt;/code&gt; is a relic of the pre-generic era. If you want to know if two references are the same, call &lt;code&gt;ReferenceEquals&lt;/code&gt;. Otherwise, it is up to the type itself to decide whether it has a "value" that can be equated to another. In such cases, I'd much rather work with &lt;code&gt;IEquatable&amp;lt;T&amp;gt;&lt;/code&gt; anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drop &lt;code&gt;GetHashCode&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Following the section above, if two values are not meaningfully equatable, they're probably not meaningfully hashable either. Can two objects be hashable without being equatable? Maybe there should be an interface &lt;code&gt;IKey&amp;lt;T&amp;gt;&lt;/code&gt; that extends &lt;code&gt;IEquatable&amp;lt;T&amp;gt;&lt;/code&gt; and adds &lt;code&gt;GetHashCode&lt;/code&gt;. Otherwise, an &lt;code&gt;IHashable&lt;/code&gt; interface would do the trick. Maybe this could also serve as an opportunity to support hashes of different lengths: &lt;code&gt;IHashable32&lt;/code&gt;, &lt;code&gt;IHashable64&lt;/code&gt;, or others.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>What would I change in a rewrite of C#?</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Sat, 29 Feb 2020 18:36:02 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/what-would-i-change-in-a-rewrite-of-c-2bno</link>
      <guid>https://dev.to/thebuzzsaw/what-would-i-change-in-a-rewrite-of-c-2bno</guid>
      <description>&lt;p&gt;Just to be clear, despite the title of this post, I love C# and will continue using it for as long as I can. In my opinion, it is the best designed general-purpose programming language available today. No, it's not perfect (as noted by the existence of this post), but I think C# does the &lt;em&gt;least amount wrong&lt;/em&gt;, and it is a joy to work in.&lt;/p&gt;

&lt;p&gt;The purpose of this post is simply to explore what kind of breaking changes would be worth making to the language if the opportunity were to present itself. I am a fan of programming language design. To me, this is just an exercise in design and evaluating the consequences of such design decisions. Not everything listed below is a breaking change; the assumption is that the change would deprecate a bunch of other APIs/behavior, which would be removed.&lt;/p&gt;

&lt;h2&gt;
  
  
  UTF-8 Everywhere
&lt;/h2&gt;

&lt;p&gt;Historically, the choice to use UTF-16 for strings in Java and C# makes sense. I'm not mad about it, but today, the best choice is definitely UTF-8. It often has higher byte-density than UTF-16 (especially considering the programming language itself is English, as are popular protocols like HTTP). The new &lt;code&gt;System.Text.Json&lt;/code&gt; APIs specifically provide ways to bypass  conversion to and from &lt;code&gt;string&lt;/code&gt; because the world outside of C# (mainly the web) has largely settled on UTF-8. The continued use of UTF-16 is a performance liability at this point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methods Outside Classes
&lt;/h2&gt;

&lt;p&gt;Not much to say here. I want to be able to make free-floating methods. Stop insisting everything I do be inside a &lt;code&gt;class&lt;/code&gt; or &lt;code&gt;struct&lt;/code&gt;. OOP is great, but this requirement was an overreach. While we're at it, can I avoid indenting my entire file inside a namespace? Just let me do this up top:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Acme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reader + Writer Paradigm
&lt;/h2&gt;

&lt;p&gt;I really like the trend in recent .NET APIs to separate data types into explicit reader and writer types. Take a look at &lt;code&gt;Channel&amp;lt;T&amp;gt;&lt;/code&gt;. The class is nothing more than a tuple of &lt;code&gt;ChannelReader&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code&gt;ChannelWriter&amp;lt;T&amp;gt;&lt;/code&gt;. This allows me to pass just the reader or just the writer into a method. It is much clearer what can and cannot happen. I want to take this concept and spread it just about every other corner of the language. I would love to have an &lt;code&gt;ArrayReader&amp;lt;T&amp;gt;&lt;/code&gt; or a &lt;code&gt;DictionaryWriter&amp;lt;TKey, TValue&amp;gt;&lt;/code&gt;. There were attempts at this in the early days with things like &lt;code&gt;IReadOnlyCollection&amp;lt;T&amp;gt;&lt;/code&gt;, but they have two problems. First, the names are dishonest. An &lt;code&gt;IReadOnlyDictionary&amp;lt;TKey, TValue&amp;gt;&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; a read-only dictionary; it is simply read-only in a small context, but code elsewhere may very well be writing to it (possibly even concurrently). Second, it's often not that hard to simply cast to a read-write type. Obviously, that'd be a conventional no-no, but the point is that having a clean separation between &lt;code&gt;Reader&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code&gt;Writer&amp;lt;T&amp;gt;&lt;/code&gt; puts distance between the two modes.&lt;/p&gt;

&lt;p&gt;With this design in place, APIs could be much clearer about their intent. There are many APIs, for example, that accept &lt;code&gt;IDictionary&amp;lt;TKey, TValue&amp;gt;&lt;/code&gt;. Will it write to that dictionary? &lt;em&gt;Probably&lt;/em&gt; not, but who can say for sure? I'd feel a lot better if I could send around &lt;code&gt;IDictionaryReader&amp;lt;TKey, TValue&amp;gt;&lt;/code&gt;. In cases like &lt;code&gt;ImmutableDictionary&amp;lt;TKey, TValue&amp;gt;&lt;/code&gt;, there simply wouldn't even be an &lt;code&gt;IDictionaryWriter&amp;lt;TKey, Value&amp;gt;&lt;/code&gt; anywhere! You'd call transformation methods that return a new &lt;code&gt;IDictionaryReader&amp;lt;TKey, TValue&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The longer I code in C#, the more I wish arrays were immutable. I'm not fully sold on F# or functional programming in general, but if some kind of &lt;code&gt;ArrayReader&amp;lt;T&amp;gt;&lt;/code&gt; were available (again, such that it couldn't just be cast to the writer version), I'd like that. So many legacy APIs (and even new ones) accept &lt;code&gt;T[]&lt;/code&gt;, which means I am at the API's mercy as to whether things inside will change. It feels like a subtle inconsistency that strings are immutable while arrays are not, but I get why it played out that way.&lt;/p&gt;

&lt;p&gt;Note that I am aware of &lt;code&gt;ReadOnlySpan&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code&gt;ReadOnlyMemory&amp;lt;T&amp;gt;&lt;/code&gt;. They are great but do not fully accomplish what I described above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strict Nullability Rules
&lt;/h2&gt;

&lt;p&gt;I love that C# 8 is tackling the problem of null references. I am adopting it into my current projects with great success, but this really should have been there from the beginning. The issue with C# 8 is that it is an opt-in mechanic that must remain compatible with code that did not opt-in. Again, I'm not criticizing the .NET team: adding this kind of feature this late into the ecosystem is a huge undertaking, but this post is about my &lt;em&gt;dream&lt;/em&gt; version of C#. :)&lt;/p&gt;

&lt;p&gt;I know people are a fan of things like &lt;code&gt;Maybe&amp;lt;T&amp;gt;&lt;/code&gt; or &lt;code&gt;Optional&amp;lt;T&amp;gt;&lt;/code&gt;. I've just always been a fan of leveraging &lt;code&gt;null&lt;/code&gt; for that purpose. How great would it be if every single API used &lt;code&gt;?&lt;/code&gt; to denote nullability? Let's get rid of all that code that checks for &lt;code&gt;null&lt;/code&gt; (unless, of course, you're working with the &lt;code&gt;T?&lt;/code&gt; variant). I think I would even do things a little differently from C# 8. If I have a &lt;code&gt;string? data&lt;/code&gt; variable, rather than trying to make the compiler super duper smart about if or when the variable is &lt;code&gt;null&lt;/code&gt;, I think nullable types should have a one-way &lt;em&gt;conditional cast&lt;/em&gt; to a non-nullable type. I'm not sure what the code would look like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Maybe something like this...?&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;DoTheThing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;nonNull&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// nonNull would only be visible inside here.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// nonNull could not be used here.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I just think it would be simpler both for humans and compilers to understand where the transition happens and what contexts the non-null value exists in. The variable &lt;code&gt;data&lt;/code&gt; would be more of a wrapper than a value (much like how they are for &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt;) with fewer implicit casts to the non-null variant.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;defer&lt;/code&gt; keyword
&lt;/h2&gt;

&lt;p&gt;There is actually an &lt;a href="https://github.com/dotnet/csharplang/issues/1398"&gt;open issue&lt;/a&gt; for this feature right now. I'm excited, provided it is done right. This keyword would effectively become a fancy &lt;code&gt;finally&lt;/code&gt; block to help deal with objects that do not follow the &lt;code&gt;IDisposable&lt;/code&gt; flow. So, today, you write code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Do all the things.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I don't like that the entire body of work is contained in that try block, which also results in another level of indentation. I would much rather write code like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Do all the things.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are workarounds today, but I do not like that they largely entail extra objects and/or delegates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SemaphoreReleaser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Custom type.&lt;/span&gt;

&lt;span class="c1"&gt;// Do all the things.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At least, &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement"&gt;in C# 8&lt;/a&gt;, it still avoids the new block/indentation thanks to the freestanding &lt;code&gt;using&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  To Be Continued
&lt;/h2&gt;

&lt;p&gt;I'm sure I'll think of more ideas to share in the future. I can turn this into a series if there's interest. Feedback welcome! Have a great day!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Converting Dictionaries in System.Text.Json</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Wed, 26 Feb 2020 05:02:30 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/converting-dictionaries-in-system-text-json-474b</link>
      <guid>https://dev.to/thebuzzsaw/converting-dictionaries-in-system-text-json-474b</guid>
      <description>&lt;p&gt;Like many out there, I'm a long-time consumer of &lt;code&gt;Newtonsoft.Json&lt;/code&gt;. It's simple and powerful, so it surprised me to learn that .NET Core 3 would be introducing its own JSON library. What surprised me more was learning that the man behind &lt;code&gt;Newtonsoft.Json&lt;/code&gt; himself would be involved with designing this new library. This new library, &lt;code&gt;System.Text.Json&lt;/code&gt;, was built with a specific purpose in mind: performance with JSON-related functionality in ASP.NET Core. It promises reduced allocations and higher throughput.&lt;/p&gt;

&lt;p&gt;The design of this new library is somewhat off-putting for many. Right out of the gate, I wondered what happened to &lt;code&gt;JObject&lt;/code&gt;, &lt;code&gt;JArray&lt;/code&gt;, and &lt;code&gt;JToken&lt;/code&gt;. They're just... gone... with no real replacement. The new library has &lt;code&gt;JsonElement&lt;/code&gt;, but it's largely a read-only component. It is only created as part of a large parse operation; I can't just create JSON things and glue them together like I could with Newtonsoft.&lt;/p&gt;

&lt;p&gt;I spent more time with it and slowly grew accustomed to its design philosophy. I no longer miss &lt;code&gt;JObject&lt;/code&gt; because it was a thin wrapper over things I already have in .NET anyway. What is a JSON object really? It's just a &lt;code&gt;Dictionary&amp;lt;string, object&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;43&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Western Union"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"isEnabled"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"things"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"stuff"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Cool. Simple enough. I can also serialize custom objects with arbitrary properties to accomplish the same things. With this in mind, I kind of see the old Newtonsoft classes as crutches more than anything else. They offer feel-good measures for directly crafting JSON objects and arrays. (And I'm not faulting anyone for sticking with that paradigm. It's pretty easy to read.)&lt;/p&gt;

&lt;p&gt;However, I was caught off guard when I went to deserialize a dictionary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{\"49fc2162-744a-4a42-b685-ea1e30ce2a2f\": 99}"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deserialize&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This code here throws a &lt;code&gt;NotSupportedException&lt;/code&gt;. It points out that having a non-string for the &lt;code&gt;TKey&lt;/code&gt; is simply unacceptable. This... is a problem. I work with &lt;code&gt;Guid&lt;/code&gt; extensively (at home and at work) and &lt;em&gt;often&lt;/em&gt; use it as a dictionary key. I'm generally not OK with having to convert JSON to a string dictionary first and then to a non-string dictionary as a second step. It seems I am &lt;a href="https://github.com/dotnet/corefx/issues/40120"&gt;not alone&lt;/a&gt; in experiencing frustration at this.&lt;/p&gt;

&lt;p&gt;However, as much as I love to sit and complain about others' hard work, I decided to just do something about it. The documentation for creating your own JSON converters is &lt;a href="https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to"&gt;pretty good&lt;/a&gt;. So, I set out to make my own, and I am pleased with the result so far. Now I can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;JsonSerializerOptions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Converters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DictionaryJsonConverterFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{\"49fc2162-744a-4a42-b685-ea1e30ce2a2f\": 99}"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deserialize&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Back in business! If you are interested in my implementation, the code is all &lt;a href="https://github.com/TheBuzzSaw/KellySharp/tree/master/KellySharp/DictionaryJsonConverter"&gt;here&lt;/a&gt; with a small explanation &lt;a href="https://github.com/TheBuzzSaw/KellySharp/blob/master/KellySharp/DictionaryJsonConverter/Usage.md"&gt;here&lt;/a&gt;. It's public domain. Knock yourself out.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Why are these the gitignore rules for VS Code?</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Sun, 15 Dec 2019 18:57:07 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/why-are-these-the-gitignore-rules-for-vs-code-3p03</link>
      <guid>https://dev.to/thebuzzsaw/why-are-these-the-gitignore-rules-for-vs-code-3p03</guid>
      <description>&lt;p&gt;If you search for good &lt;code&gt;.gitignore&lt;/code&gt; rules for Visual Studio Code, you often come across these.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;##
## Visual Studio Code
##
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I tried using them for a while, but they just lead to problems. It is the equivalent of committing the &lt;code&gt;.user&lt;/code&gt; files in other .NET projects. The file &lt;code&gt;launch.json&lt;/code&gt;, for example, contains my own command-line arguments, environment variables, etc. Why would I want those committed? Why would I want changes from other developers overriding mine all the time? Who decided this was a good idea?&lt;/p&gt;

&lt;p&gt;It's particularly annoying because &lt;code&gt;dotnet new gitignore&lt;/code&gt; imports these questionable rules. I just block the entire folder now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.vscode/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If I ever clone my repo from scratch, VS Code offers to whip up a new set of files for me anyway. Are there other languages/environments where committing these files is extremely beneficial?&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>git</category>
    </item>
    <item>
      <title>How to Conditionally Target WinExe</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Thu, 28 Nov 2019 22:35:59 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/only-target-winexe-sometimes-4mfn</link>
      <guid>https://dev.to/thebuzzsaw/only-target-winexe-sometimes-4mfn</guid>
      <description>&lt;p&gt;When creating cross-platform games in .NET Core, you'll typically use the &lt;code&gt;dotnet new console&lt;/code&gt; template for the project. When creating a console app, you end up with a project file like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Project&lt;/span&gt; &lt;span class="na"&gt;Sdk=&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.NET.Sdk"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;OutputType&amp;gt;&lt;/span&gt;Exe&lt;span class="nt"&gt;&amp;lt;/OutputType&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;netcoreapp3.0&lt;span class="nt"&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Running this application under Windows results in a console window showing up even if the bulk of the application runs inside a graphical window (created by SDL or some other middleware). The console window is fine for development but no good when it comes time to ship the application. Unlike macOS or Linux, applications in Windows have a flag embedded into the binary itself dictating whether it should spawn a console window.&lt;/p&gt;

&lt;p&gt;Before .NET Core 3.0 was released, I could only find one real option to deal with this: the tool &lt;code&gt;editbin.exe&lt;/code&gt;, which ships with Visual Studio (not VS Code).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;editbin.exe /subsystem:windows yourapp.exe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And this works, but I hate that my build environment requires &lt;code&gt;editbin.exe&lt;/code&gt; be installed and added to my &lt;code&gt;PATH&lt;/code&gt;. It's just more stuff that can go wrong; I wanna keep things simple.&lt;/p&gt;

&lt;p&gt;Thankfully, .NET Core 3.0 introduced a new way to solve this problem: simply change your &lt;code&gt;OutputType&lt;/code&gt; to &lt;code&gt;WinExe&lt;/code&gt; in your &lt;code&gt;.csproj&lt;/code&gt; file! I much prefer this solution because it brings me back to only needing the .NET Core SDK and nothing else. Complexity is the enemy, and I will slay it whenever I can.&lt;/p&gt;

&lt;p&gt;However, permanently changing my &lt;code&gt;OutputType&lt;/code&gt; complicates things: I &lt;em&gt;want&lt;/em&gt; that console window almost all the time during development. Not only does it let me see my console debug output, it gives me another handy way to close the application in case it hangs or something: I can just close the console window itself. So, ideally, I want the &lt;code&gt;OutputType&lt;/code&gt; to be &lt;code&gt;Exe&lt;/code&gt; &lt;em&gt;except&lt;/em&gt; when publishing my application.&lt;/p&gt;

&lt;p&gt;So, initially, I created my script &lt;code&gt;publish.cmd&lt;/code&gt; to contain this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet publish -c Release -r win-x64 -p:CopyOutputSymbolsToPublishDirectory=false -p:OutputType=WinExe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And this works... but not really. The problem is that the moment you introduce a dependency to your project, this path fails. Let's say you are building a shared library the same time you are building your desktop application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ProjectReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"..\Kelly.Shared\Kelly.Shared.csproj"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You will suddenly run into this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CSC : error CS5001: Program does not contain a static 'Main' method suitable for an entry point [C:\Users\kelly\Documents\Kelly.Shared\Kelly.Shared.csproj]

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What is going on here? It turns out that when you specify &lt;code&gt;-p:OutputType=WinExe&lt;/code&gt;, it happens &lt;em&gt;globally&lt;/em&gt;. The property is propagated to &lt;em&gt;all&lt;/em&gt; projects being built. So, your shared library is no longer happy to just be a library; it wants to be an executable! And that just can't happen because, as the error points out, it has no &lt;code&gt;Main&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;So, back to the drawing board. How can I clearly indicate that I want &lt;em&gt;only&lt;/em&gt; &lt;code&gt;Kelly.Client&lt;/code&gt; to be &lt;code&gt;WinExe&lt;/code&gt;? Well, I solved it by introducing a property into my project that no other project cares about.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;KellyClientOutputType&amp;gt;&lt;/span&gt;Exe&lt;span class="nt"&gt;&amp;lt;/KellyClientOutputType&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;OutputType&amp;gt;&lt;/span&gt;$(KellyClientOutputType)&lt;span class="nt"&gt;&amp;lt;/OutputType&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;netcoreapp3.0&lt;span class="nt"&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now my project looks to the property &lt;code&gt;KellyClientOutputType&lt;/code&gt; to know what the output type is. This means I can alter my script to change this other property, and it will not affect any dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rmdir /s /q bin\Release
rmdir /s /q obj\Release
dotnet publish -c Release -r win-x64 -p:CopyOutputSymbolsToPublishDirectory=false -p:KellyClientOutputType=WinExe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Voila. Now I can just run this script whenever I wish to make a clean build that I want to share with outside parties.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Building a Better Library Loader in C# - Part 3</title>
      <dc:creator>Kelly Brown</dc:creator>
      <pubDate>Thu, 18 Jul 2019 03:50:27 +0000</pubDate>
      <link>https://dev.to/thebuzzsaw/building-a-better-library-loader-in-c-part-3-2hkc</link>
      <guid>https://dev.to/thebuzzsaw/building-a-better-library-loader-in-c-part-3-2hkc</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/thebuzzsaw/building-a-better-library-loader-in-c-part-2-3ek"&gt;part 2&lt;/a&gt;, I went over the creation of a type at run-time by way of &lt;code&gt;System.Reflection.Emit&lt;/code&gt;. We are able to define an interface we want to use, and our handy dandy &lt;code&gt;LoadLibrary&amp;lt;T&amp;gt;&lt;/code&gt; method will take care of all the details for us. That, by itself, is pretty magical.&lt;/p&gt;

&lt;p&gt;But we're not done. We need a few quality-of-life improvements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Returning Strings
&lt;/h2&gt;

&lt;p&gt;Let's go back to our SQLite interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ISqlite3&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how that &lt;code&gt;Open&lt;/code&gt; method takes a &lt;code&gt;string&lt;/code&gt; for one of its parameters? It really &lt;em&gt;shouldn't&lt;/em&gt; work because &lt;code&gt;System.String&lt;/code&gt; is a radically different data structure from the &lt;code&gt;const char*&lt;/code&gt; that &lt;code&gt;sqlite3_open&lt;/code&gt; &lt;a href="https://www.sqlite.org/c3ref/open.html"&gt;expects&lt;/a&gt;. The first problem is that &lt;code&gt;System.Char&lt;/code&gt; is 2 bytes, and the &lt;code&gt;char&lt;/code&gt; in C is 1 byte. The second problem is that strings/arrays in .NET embed their length, and C strings use null-termination.&lt;/p&gt;

&lt;p&gt;Thankfully, .NET foresaw this and &lt;a href="https://docs.microsoft.com/en-us/dotnet/standard/native-interop/type-marshaling#default-rules-for-marshaling-common-types"&gt;took care of the issue for us&lt;/a&gt;. So, this methods works as you would expect! You can simply call &lt;code&gt;sqlite3.Open("stuff.sqlite", out var db);&lt;/code&gt; without difficulty because your string is automatically converted to a null-terminated C string that your C library can actually handle.&lt;/p&gt;

&lt;p&gt;However, what if we wanted a method that &lt;em&gt;returns&lt;/em&gt; a string? Let's look at &lt;code&gt;sqlite3_errmsg&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;Errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have bad news for you. If you call this, your program will crash. If it doesn't crash, it'll behave badly regardless. The nice type marshaling we had for values going in apparently does not apply to values coming out. So, how do we fix this? Well, since the C function returns a pointer (&lt;code&gt;const char*&lt;/code&gt;), we need to capture it as a pointer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="nf"&gt;Errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great. How do I get a string out of that? Well, if you're using .NET Core, &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.ptrtostringutf8?view=netcore-2.2#System_Runtime_InteropServices_Marshal_PtrToStringUTF8_System_IntPtr_System_Int32_"&gt;the answer is simple&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="n"&gt;cString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cString&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;IntPtr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Zero&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PtrToStringUTF8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're not using .NET Core... shame on you. Start using .NET Core immediately! If you absolutely cannot use .NET Core (or a sufficiently high enough version of .NET Standard), you are going to have to parse the string yourself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GetStringTheHardWay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="n"&gt;cString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cString&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;IntPtr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Zero&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;++);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToArray&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK, so, now we have a way to read strings returned from C functions, but this is still too much work. Now, &lt;strong&gt;every time&lt;/strong&gt; I want a string from my method, I have to call &lt;code&gt;GetString(returnedValue)&lt;/code&gt;. That's no good! I want to be lazier than that! So, let's revisit our code generator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;ILGenerator&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;methodBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetILGenerator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ldarg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Arg 0 is 'this'. Don't need that one.&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is64BitProcess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ldc_I8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToInt64&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ldc_I4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToInt32&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EmitCalli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Calli&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CallingConvention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cdecl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReturnType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parameterTypes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Calli&lt;/code&gt; instruction places the C function's return value onto the stack, and the subsequent &lt;code&gt;Ret&lt;/code&gt; instruction forwards it onto the caller. There is an opportunity here: we know, ahead of time, what the return type is. Why not just handle the conversion right here? If we know that the method on the interface wants to return &lt;code&gt;string&lt;/code&gt;, we can take care of returning &lt;code&gt;IntPtr&lt;/code&gt; internally and converting it before returning it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This should be stored outside the loop iterating over the interface methods.&lt;/span&gt;
&lt;span class="n"&gt;MethodInfo&lt;/span&gt; &lt;span class="n"&gt;getStringMethod&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WhateverClassHasTheMethod&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;GetMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;ILGenerator&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;methodBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetILGenerator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ldarg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Arg 0 is 'this'. Don't need that one.&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is64BitProcess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ldc_I8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToInt64&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ldc_I4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToInt32&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;returnsString&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReturnType&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EmitCalli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Calli&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CallingConvention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cdecl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;returnsString&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReturnType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parameterTypes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;returnsString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getStringMethod&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you see what we did? The return type sent off to &lt;code&gt;EmitCalli&lt;/code&gt; now has special treatment. If we ultimately want a &lt;code&gt;string&lt;/code&gt; to come back, we capture an &lt;code&gt;IntPtr&lt;/code&gt; first. Since that &lt;code&gt;IntPtr&lt;/code&gt; value is on top of the stack after the &lt;code&gt;Calli&lt;/code&gt; instruction, it is in the right position to serve as an argument for the call to &lt;code&gt;GetString&lt;/code&gt;. How convenient! The call to &lt;code&gt;GetString&lt;/code&gt; will place the &lt;code&gt;string&lt;/code&gt; result onto the stack, and then our &lt;code&gt;Ret&lt;/code&gt; instruction will return it to the caller.&lt;/p&gt;

&lt;p&gt;Voila. Methods that return &lt;code&gt;string&lt;/code&gt; work fine now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Library Cleanup
&lt;/h2&gt;

&lt;p&gt;Remember way back in &lt;a href="https://dev.to/thebuzzsaw/building-a-better-library-loader-in-c-part-1-1446"&gt;part 1&lt;/a&gt; when we talked about loading and unloading libraries? Our fancy-shmancy &lt;code&gt;LoadLibrary&amp;lt;T&amp;gt;&lt;/code&gt; happily loads up the library but leaves us without a way to unload the library. That may not matter to many developers. It's quite normal for games to load up libraries, use them for the entire lifetime of the application, and then skip unloading them at the end. Regardless, I think it's best we at least offer up &lt;em&gt;some way&lt;/em&gt; to unload these libraries as there are applications out there that need to load and unload libraries over time.&lt;/p&gt;

&lt;p&gt;There are several approaches we can take here. I suggest leveraging &lt;code&gt;IDisposable&lt;/code&gt; as it is idiomatic and brings several benefits along with it. The top benefit (in my mind) is the ability to put your library into a &lt;code&gt;using&lt;/code&gt; block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ISqlite3&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LoadLibrary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ISqlite3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"custom_sqlite3.dll"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GetSqliteFunctionName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my_data.sqlite"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another perk is that we can enforce this in the &lt;code&gt;LoadLibrary&amp;lt;T&amp;gt;&lt;/code&gt; definition itself. Forgetting to mark your interface as &lt;code&gt;IDisposable&lt;/code&gt; will result in a compiler error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ISqlite3&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDisposable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;LoadLibrary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;methodNameToFunctionName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IDisposable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, let's make a helper method to implement the &lt;code&gt;Dispose&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;CreateDisposeMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;TypeBuilder&lt;/span&gt; &lt;span class="n"&gt;typeBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;IntPtr&lt;/span&gt; &lt;span class="n"&gt;libraryHandle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;MethodBuilder&lt;/span&gt; &lt;span class="n"&gt;methodBuilder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;typeBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DefineMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDisposable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;MyMethodAttributes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;typeBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DefineMethodOverride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;methodBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDisposable&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;GetMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDisposable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

    &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;ptrType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is64BitProcess&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;ConstructorInfo&lt;/span&gt; &lt;span class="n"&gt;intPtrConstructor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;GetConstructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ptrType&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="n"&gt;MethodInfo&lt;/span&gt; &lt;span class="n"&gt;closeMethod&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RuntimeInformation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsOSPlatform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OSPlatform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Windows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;
        &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WinLoader&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;GetMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WinLoader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FreeLibrary&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UnixLoader&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;GetMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UnixLoader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="n"&gt;ILGenerator&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;methodBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetILGenerator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is64BitProcess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ldc_I8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;libraryHandle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToInt64&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ldc_I4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;libraryHandle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToInt32&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Newobj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;intPtrConstructor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;closeMethod&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pop&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Toss the returned int.&lt;/span&gt;
    &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, this method has to construct the &lt;code&gt;IntPtr&lt;/code&gt; instance because there is no way to embed a constant &lt;code&gt;IntPtr&lt;/code&gt; into the code. As I mentioned before, I recommend just using &lt;a href="https://sharplab.io/"&gt;SharpLab&lt;/a&gt; in helping to determine what IL you want to emit. I'm no IL expert; I just write C# code for what I want to accomplish and study the resulting IL.&lt;/p&gt;

&lt;p&gt;Just remember to call &lt;code&gt;CreateDisposeMethod&lt;/code&gt; somewhere in your &lt;code&gt;LoadLibrary&amp;lt;T&amp;gt;&lt;/code&gt; method, and you're gold. In part 4, we'll do more upgrades specific to game dev. :)&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
