{"id":75,"date":"2020-03-15T17:42:12","date_gmt":"2020-03-15T16:42:12","guid":{"rendered":"https:\/\/intsight.com\/?p=75"},"modified":"2023-08-15T22:28:51","modified_gmt":"2023-08-15T20:28:51","slug":"un-ejemplo-de-estructura","status":"publish","type":"post","link":"https:\/\/intsight.com\/index.php\/2020\/03\/15\/un-ejemplo-de-estructura\/","title":{"rendered":"Un ejemplo de estructura"},"content":{"rendered":"<p><span style=\"font-variant: small-caps;\">Para ver<\/span> algo m\u00e1s de las nuevas posibilidades de las estructuras de C#, voy a mostrar una clase sencilla que utilizo en Iridium, un motor de valoraci\u00f3n de swaps, en su versi\u00f3n nativa para .NET Core. La estructura (\u00a1qu\u00e9 sorpresa!) sirve para representar fechas pero, a diferencia de <code>DateTime<\/code>, sin la parte de la hora.<\/p>\n<p>Internamente, una fecha se representa como el n\u00famero de d\u00edas transcurridos desde el uno de enero del a\u00f1o 1. Como son fechas para software financiero, me la trae al viento los problemas de cambio de calendario. Con estas premisas, puedo representar el n\u00famero de d\u00edas con un valor entero de 32 bits, con lo que mi tipo <code>Date<\/code> ocupa la mitad del espacio que un <code>DateTime<\/code>. Esta es la declaraci\u00f3n de la estructura y de su \u00fanico campo de estado:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">\/\/\/ &lt;summary&gt;A date with efficient operations.&lt;\/summary&gt;\npublic readonly struct Date : IEquatable&lt;Date&gt;, IComparable&lt;Date&gt;\n{\n    \/\/\/ &lt;summary&gt;Number of days since Jan 1st, 1.&lt;\/summary&gt;\n    private readonly int date;\n    public Date(int year, int month, int day) { ... }\n}<\/pre>\n<p>Para ganar velocidad, adem\u00e1s, el constructor no verifica que los componentes de una fecha sean correctos: en Iridium, eso es responsabilidad del generador de cupones y otras partes del c\u00f3digo que generan fechas.<\/p>\n<p>Ahora viene la parte m\u00e1s interesante del tipo de datos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public void Deconstruct(\n     out int year, out int month, out int day) { ... }<\/pre>\n<p>Un deconstructor es un m\u00e9todo que permite, precisamente, extraer en una sola operaci\u00f3n las partes integrantes de una instancia de un tipo. Se introdujeron pensando en las tuplas, pero en realidad se pueden usar con cualquier clase o estructura, y es una pena que <code>DateTime<\/code> no cuente con uno de estos m\u00e9todos. Gracias al deconstructor, podemos ejecutar instrucciones como la siguiente:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">var (y1, m1, day1) = fromDate;<\/pre>\n<p>Si tuviese que usar <code>DateTime<\/code>, tendr\u00eda que llamar por separado a las tres propiedades <code>Year<\/code>, <code>Month<\/code> y <code>Day<\/code> de la fecha. \u00bfEl problema? Pues que para recuperar el a\u00f1o a partir de la representaci\u00f3n interna hay que ejecutar un peque\u00f1o algoritmo que lleva su tiempo. Si luego quiero el mes, no importa: tengo que volver a ejecutar la parte que extrae el a\u00f1o. Y lo mismo pasa al pedir el d\u00eda del mes. Con el deconstructor, en cambio, s\u00f3lo tengo que descomponer la fecha en partes una sola vez, y obtengo los tres componentes. De hecho, la implementaci\u00f3n de mi propiedad <code>Day<\/code> se permite el lujo de usar internamente el deconstructor:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public int Day\n{\n    get\n    {\n        Deconstruct(out _, out _, out int d);\n        return d;\n    }\n}<\/pre>\n<p>Los subrayados son comodines para descartar el a\u00f1o y el mes.<\/p>\n<p>\u00bfM\u00e1s cosas que pueden interesar? Por ejemplo, se permiten las conversiones de tipo entre <code>Date<\/code> y <code>DateTime<\/code>, en ambos sentidos, y permito convertir un valor <code>Date<\/code> en un n\u00famero (la conversi\u00f3n inversa se consigue m\u00e1s elegantemente con un constructor adicional):<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public static explicit operator DateTime(Date d) =&gt;\n    new DateTime(d.date * TicksPerDay);\npublic static explicit operator Date(DateTime d) =&gt;\n    new Date((int)(d.Ticks \/ TicksPerDay));\npublic static explicit operator int(Date d) =&gt; d.date;<\/pre>\n<p>El c\u00f3digo completo de la clase puede descargar desde <a href=\"http:\/\/marteens.com\/downloads\/Date.cs\" target=\"_blank\" rel=\"noopener noreferrer\">este enlace<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Para ver algo m\u00e1s de las nuevas posibilidades de las estructuras de C#, voy a mostrar una clase sencilla que utilizo en Iridium, un motor de valoraci\u00f3n de swaps, en su versi\u00f3n nativa para .NET Core. La estructura (\u00a1qu\u00e9 sorpresa!) sirve para representar fechas pero, a diferencia de DateTime, sin la parte de la hora. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":79,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[11,13,12,5],"class_list":["post-75","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c","tag-date","tag-deconstructor","tag-iridium","tag-struct"],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/intsight.com\/wp-content\/uploads\/2020\/03\/calendar.png?fit=360%2C355&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/75","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/comments?post=75"}],"version-history":[{"count":23,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/75\/revisions"}],"predecessor-version":[{"id":1379,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/75\/revisions\/1379"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/media\/79"}],"wp:attachment":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/media?parent=75"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/categories?post=75"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/tags?post=75"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}