
Cuando hace unas semanas ScottGu anunció la Preview 3 de ASP.NET MVC, quedé muy sorprendido de que al final no viniera con soporte para Visual Web Developer Express 2008, sobre todo teniendo en cuenta que un mes antes había adelantado este acontecimiento para los que estamos probando la plataforma MVC con esta herramienta.
Pero no, era una falsa alarma. Scott había olvidado comentarlo, y días más tarde rectificaba en un nuevo post en el que comunicaba que sí sería posible usar la Preview 3 desde la versión Express de Web Developer sin necesidad de usar plantillas específicas.
Desde entonces estaba deseando tener un ratillo para probarlo, y por fin ha llegado el momento.
En primer lugar, he de aclarar que, aunque pueda parecer lo contrario, no se trata de que el equipo de Microsoft haya introducido cambios en la plataforma MVC para hacerla compatible con la versión Express, sino al revés. Son los nuevos cambios introducidos en el IDE, y principalmente su recién estrenado soporte a proyectos de tipo Aplicación Web, los que hacen posible que funcione directamente sobre esta herramienta.
Y este es el motivo de que, antes que nada, sea necesario instalar el SP1 de .NET Framework 3.5 y de las herramientas Express (aún en Beta). Y si váis a hacerlo, mucho ojo, que todas las páginas donde aparece para descargar aparece llena de warnings; en otras palabras, no recomiendan su instalación en máquinas de verdad, sólo en entornos de prueba. Pero no os preocupéis, que para eso estoy yo ;-)
Después de un proceso algo lento y un par de reinicios del equipo, el Service Pack 1 Beta queda instalado sin problemas. Sólo falta descargar y montar la Preview 3 de ASP.NET MVC para que al ir a crear un nuevo proyecto desde Visual Web Developer aparezcan la plantilla MVC, entre otras novedades:

Y para probar, nada mejor que la aplicación de demostración sobre Northwind que preparó Phil Haack hace unas semanas. Salvo un ligero error de carga debido a que la versión Express no soporta la creación de proyectos de solución (no podremos probar los tests unitarios integrados en VS2008), todo funciona a la perfección.

Sí señor. Ahora sí que podemos seguir jugando. :-)
Publicado en: www.variablenotfound.com.
Publicado por José M. Aguilar a las 10:20 p. m.
Etiquetas: asp.net, aspnetmvc, desarrollo, vs2008, web

Hoy por ejemplo, desarrollando con VbScript en un entorno propietario embebido en un sistema de gestión empresarial hemos necesitado crear GUIDs y hemos visto que el lenguaje no dispone de esta capacidad, a diferencia de .Net o Java, que proporcionan vías para conseguirlo de forma muy sencilla.
Preguntándole a Google, que todo lo sabe, he encontrado varias soluciones aplicables de forma directa.
La primera, es usar funciones propias del motor de base de datos. En nuestro caso concreto, la solución está conectada a un SQL Server, que afortunadamente dispone desde la versión 2000 de una función integrada de generación de GUIDs. Así pues, podríamos utilizar un código como el siguiente:
' Obtiene un nuevo GUID
' Parámetro: una conexión abierta
function ObtenerGUID(conn)
dim rs
set rs = conn.Execute("Select NEWID()")
if (not rs.eof) then
ObtenerGUID = rs(0)
end if
end function
Pero, ¿y si no usas SQL Server? No pasa nada, prácticamente todos los motores de bases de datos incorporan algún mecanismo equivalente, como MySQL ("
UUID()
") y Oracle ("SYS_GUID()
").En este momento podríamos decir que tenemos una buena solución... siempre que tengamos a mano una conexión a una base de datos capaz de generar un GUID. ¿Y si no fuera este el caso? Aquí va otro código que utilizando un objeto
Scriptlet.TypeLib
, utilizado por Windows como soporte a los lenguajes de scripting:' Obtiene un nuevo GUID
Function ObtenerGUID()
dim typeLib, guid
set typeLib = CreateObject("Scriptlet.TypeLib")
guid = typeLib.Guid
ObtenerGUID= left(guid, len(guid)-2)
set typeLib = Nothing
End Function
También hay quien utiliza llamadas a UUIDGEN.EXE, una utilidad proporcionada normalmente con kits de desarrollo de .NET y los entornos Visual Studio, generando el GUID sobre un archivo de texto para más tarde leerlo desde el script, pero me ha parecido una solución demasiado compleja para el problema.
Por último he encontrado unos ejemplos de código en el centro de soporte de Microsoft que muestran varias maneras de crear identificadores únicos, aunque me quedo con la más completa, consistente en generar la secuencia de caracteres aleatorios:
' Obtiene un GUID tipo Windows
' 8+4+4+4+12 caracteres A-Z y 0-9
Function CreateWindowsGUID()
CreateWindowsGUID = CreateGUID(8) & "-" & _
CreateGUID(4) & "-" & _
CreateGUID(4) & "-" & _
CreateGUID(4) & "-" & _
CreateGUID(12)
End Function
' Obtiene un GUID del tamaño indicado
' Parámetro: longitud del GUID
Function CreateGUID(tmpLength)
Randomize Timer
Dim tmpCounter,tmpGUID
Const strValid = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
For tmpCounter = 1 To tmpLength
tmpGUID = tmpGUID & Mid(strValid, Int(Rnd(1) * Len(strValid)) + 1, 1)
Next
CreateGUID = tmpGUID
End Function
Publicado en: www.variablenotfound.com.
Publicado por José M. Aguilar a las 10:05 p. m.
Etiquetas: desarrollo, programación, scripting, trucos

Pero para que quede claro lo que pretendemos, primero un ejemplo del resultado que vamos a conseguir:
La forma de conseguirlo es bastante sencilla. Basta con establecer, en las propiedades de estilo de los cuadros de edición una imagen de fondo con el icono que queremos incluir, y dejar un espaciado por la izquierda (padding-left) equivalente al ancho del mismo para que la introducción del texto comience a partir de ese punto.
Por ejemplo, si definimos las siguientes clases en el CSS de nuestra página (y suponiendo que la ruta de las imágenes sea correcta, claro):
.lupa
{
background: white url(icono_lupa.gif) no-repeat 2px center;
padding: 2px 2px 2px 18px;
}
.telefono
{
background: white url(icono_telefono.gif) no-repeat 2px center;
padding: 2px 2px 2px 18px;
}
Como se puede observar, se establece un fondo blanco con una imagen cuya URL se especifica (icono_xxxx.gif), mostrada sin repetición (no-repeat), posicionada en coordenada horizontal 2px y centrada verticalmente. El padding izquierdo será de 18px para que comience ahí el área de edición, a la derecha de la imagen.
Podremos utilizar después en nuestro HTML un código como el siguiente para conseguir que los cuadros de edición apararezcan "adornados" como nos interese en cada momento eligiendo para cada uno de ellos la clase CSS apropiada:
<input type="text" class="lupa" />
<input type="text" class="telefono" />
Espero que esto responda la duda, Joaquín.
Y por cierto, he utilizado esta técnica en el buscador del encabezado del blog, que lo tenía un poco soso...
Publicado en: www.variablenotfound.com.
Box2DFlashAS3 es un port para ActionScript 3.0 de una librería originalmente escrita para C++, Box2D. Ahí van unas demostraciones de sus posibilidades (pulsad las teclas izquierda y derecha para cambiar la demo, "R" para resetear la vista y también podéis arrastrar objetos con el ratón):
Hace unos meses se publicó su última revisión, la 4.1.3, y se distribuye bajo licencia zlib/libpng, lo que permite su libre utilización incluso con fines comerciales.
Publicado en: www.variablenotfound.com.
Publicado por José M. Aguilar a las 10:01 p. m.
Etiquetas: curiosidades, desarrollo, motores de física

![[ING] ASP.NET Page Life Cycle en blog de Kris Van Der Mast](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT5f1ddJsQrs3L6f6WkA0piXPTgq-nmnSEi1vOjm4ICrWJpFQVEbH-Qb050rcuvTn9Q_711qoUE7YLLj78DghBPF40_BJjx1qA8R2A8w1roSidzUwUl1CVw_kOk3zzxsO90sFTmg/s400/aspnetpagelifecycle.png)
Entre otras cosas, se pone de manifiesto la simplicidad de este modelo frente al complejo ciclo de vida de una página utilizando la tecnología Webforms.
Y por cierto, podéis descargar la presentación completa que realizaron en el DevConnections, aunque eso sí, en inglés.
Publicado en: www.variablenotfound.com.
![[ING] Ir al sitio web de jQuery](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9HX3lmL5_rFpuxL5fKsuGpa8t5IWmEFyfB6iow00W8BI2XA8s5EVgZnwTZaGJBy9ItMXS0GunTmbCsz89Ou6N4qCsGnRLgPRJUpw3XuoMP_TOt_OT-tmwRjRW3NZ0SgptAjHy2g/s400/jQuery-logo.gif)
Como ya sabemos los PageMethods son métodos estáticos definidos dentro de la clase de una página, es decir, en su codebehind, y que son accesibles desde cliente utilizando Ajax (en minúsculas!).
Hace más de un año ya estuve comentando cómo hacerlo utilizando la propia infraestructura de ASP.NET Ajax y sus librerías de scripting para hacerlo muy fácilmente. De forma muy breve, todo consistía en crear el método estático al que se deseaba acceder, decorarlo con el atributo
WebMethod
, e incluir en la página un ScriptManager
con estableciéndole la propiedad EnablePageMethods=true
; a partir de ese momento, podíamos invocarlo desde cliente usando javascript de forma muy directa.Sin embargo, el uso de estándares como JSON hace posible la invocación de WebMethods desde scripting sin necesidad de recurrir a la magia del
ScriptManager
. De hecho, y como vamos a ver más adelante, vamos a realizar la llamada al método utilizando Ajax desde una página HTML pura, sin controles de servidor ni otros edulcorantes proporcionados por ASP.NET.Desarrollaremos un ejemplo completo (esta vez en VB.NET, por cambiar un poco), que demuestre cómo podemos crear un
PageMethod
en una página (default.aspx), e invocarlo desde otra (pagina.htm) usando la librería jQuery para comunicar ambos componentes. 1. Definición del PageMethod
Como ya comenté en el post al que hacía referencia antes, un PageMethod se define en la clase asociada a una página .aspx (su code-behind) y es un método normal y corriente, aunque obligatoriamente será estático y público. Además, debe presentar el atributoWebMethod()
, que lo identifica como accesible a través llamadas HTTP.El siguiente código muestra el PageMethod que vamos a utilizar. Se supone que partimos de una página Default.aspx totalmente vacía (de hecho, no vamos a crear nada más dentro), y que el siguiente código corresponde al archivo Default.aspx.vb:
Imports System.Web.Services
Partial Public Class _Default
Inherits System.Web.UI.Page
<WebMethod()> _
Public Shared Function Saludame(ByVal Nombre As String) As String
Return "Hola a " + Nombre _
+ " desde el servidor, son las " _
+ DateTime.Now.ToString("hh:mm:ss")
End Function
End Class
Se puede observar que el método recibirá un parámetro, el nombre del destinatario del mensaje de saludo. Una vez que lo tenemos definido de esta forma, siempre que el proyecto esté correctamente configurado, el método es accesible en la dirección "Default.aspx/Saludame" para todo aquél que quiera utilizarlo, siempre que siga ciertas reglas.
2. Creamos la página "cliente"

En lugar de mostrar el código fuente de la página HTML (pagina.html) completo, voy a hacerlo por partes, y saltándome algunas porciones que no tienen demasiado interés. En primer lugar va la correspondiente al interfaz, que es bastante simple:
<body>
<form>
<input type="text" id="nombre" />
<input type="button" value="¡Pulsa!"
onclick="llamar();" />
<br />
<strong>Mensajes obtenidos:</strong><br />
<label id="lblMensajes" />
</form>
</body>
Como se puede intuir, la función
llamar()
, invocada al hacer click sobre el botón, será la que realice la conexión con el servidor, le envíe el nombre contenido en el cuadro de edición, e introduzca la respuesta en la etiqueta lblMensajes
, que actuará como contenedor.Vamos ahora con la porción de página donde se desarrolla la acción. Primero se incluye jQuery en la página, y acto seguido creamos la función
llamar()
que hemos comentado anteriormente:<script type="text/javascript"
src="scripts/jquery-1.2.6.min.js" ></script>
<script type="text/javascript">
function llamar()
{
$.ajax({
type: "POST",
data: "{ Nombre: '" + $("#nombre").val() + "'}" ,
url: "Default.aspx/Saludame",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("#lblMensajes").append(msg);
$("#lblMensajes").append("<br />");
},
error: function(msg) { alert("Algún problema debe haber..."); }
});
}
</script>
Los parámetros de llamada a la función ajax() de jQuery son los siguientes:
type
, la petición HTTP es de tipo POST. Es obligatorio para acceder a los PageMethods por motivos de seguridad.data
contiene una representación JSON de los parámetros enviados al método. En este caso, vemos que se compone de forma dinámica inyectándole el valor del cuadro de edición (obtenido a su vez utilizando un selector jQuery y el método val()). Fijaos que esta representación define un objeto anónimo cuyas propiedades deberán coincidir con los parámetros del método; para este ejemplo, un valor correcto dedata
sería"{ Nombre: 'Juan' }"
.url
contiene la dirección del método. Observad que es el nombre de la página seguido del nombre del método.- El
content-type
indica el tipo de contenido que enviamos al servidor; en este caso, dado que le vamos a enviar JSON codificado en utf-8 debe ser "application/json; charset=utf-8". - Con
dataType
indicamos al servidor qué tipo de respuesta estamos esperando. Dado que la trataremos también desde script, será más sencillo si es JSON. success
contiene una función anónima que recibe como parámetro la respuesta del servidor. En este caso, hemos implementado su inclusión en la etiqueta que habíamos preparado para mostrar los mensajes del servidor.- de la misma forma, en
error
implementamos lo que queremos que haga el sistema cuando se produzca un problema. En este caso sólo avisamos.
Y... ¡listo para funcionar!
Fijaos en un detalle importante: nada impide la invocación de PageMethods desde páginas distintas a donde se han definido, cosa que con el comportamiento estándar del
ScriptManager
y su EnablePageMethods=true
sería imposible.Finalmente, recordar que para que todo esto funcione el proyecto web debe estar correctamente configurado para trabajar con las extensiones Ajax. Las plantillas de proyectos de Visual Studio 2008 ya vienen preparadas de forma predeterminada, pero si usas VS2005 deberás crear el proyecto usando las plantillas para aplicaciones Web con Ajax, o retocar a mano el web.config.
Puedes descargar el proyecto de prueba para VS2005.
Publicado en: www.variablenotfound.com.

El concepto es parecido a los antipatrones de programación, aunque funcionan a un nivel todavía más sutil, pues no describe situaciones completas sino indicios. De hecho, el uso de esta metáfora sensorial respecto a un código, es decir, que éste desprenda cierto tufillo, indica que sería conveniente realizar una revisión en profundidad para ver si hay que refactorizar, pero no implica que necesariamente haya algo incorrecto. Además, dado que trata de algo tan personal y específico como el código fuente, a veces las señales son bastante subjetivas y dependientes de lenguajes y tecnologías concretas.
Existen multitud de listas y clasificaciones, aunque es muy interesante la realizada por Mika Mäntylä, investigador de la universidad de Helsinki, ha creado una taxonomía que agrupa code smells relacionados en cinco categorías en función del efecto que pueden provocar:
- The bloaters (los infladores), que agrupa 'aromas' que indican el crecimiento excesivo de algún aspecto que hacen incontrolable el código.
- Long method (método extenso) que precisa de su reducción para ser más legible y mantenible.
- Large class (clase larga), con síntomas y consecuencias muy similares al caso anterior.
- Primitive obsession (obsesión por tipos primitivos), cuyo síntoma es la utilización de tipos primitivos para almacenar datos de entidades pequeñas (por ejemplo, usar un long para guardar un número de teléfono).
- Long parameter list (lista de parámetros larga), que incrementan la complejidad de un método de forma considerable.
- Dataclumps (grupos de datos), o uso de un cunjunto de variables o propiedades de tipos primitivos en lugar de crear una clase apropiada para almacenar los datos, lo que a su vez provoca el incremento de parámetros en métodos y clases.
- The Object-Orientation Abusers (los maltratadores de la orientación a objetos), que aglutina code smells que indican que no se está aprovechando la potencia de este paradigma:
- Switch statements (sentencias Switch), que podrían indicar una falta de utilización de mecanismos de herencia.
- Temporary field (campo temporal), que se salta el principio de encapsulamiento y ocultación de variables haciendo que éstas pertenezcan a la clase cuando su ámbito debería ser exclusivamente el método que las usa.
- Refused bequest (rechazo del legado), cuando una subclase 'rechaza' métodos o propiedades heredadas, atentando directamente contra uno de los principales pilares de la OOP.
- Alternative Classes with Different Interfaces (clases alternativas con distintos interfaces) indica la ausencia de interfaces comunes entre clases similares.
- The change preventers (los impedidores de cambios)
- Divergent Change (cambio divergente), que hace que sean implementadas dentro de la misma clase funcionalidades sin ninguna relación entre ellas, lo que sugiere extraerlas a una nueva clase.
- Shotgun surgery (cirujía de escopeta), ocurre cuando un cambio en una clase implica modificar varias clases relacionadas.
- Parallel Inheritance Hierarchies (jerarquías de herencia paralelas), paralelismo que aparece cuando cada vez que se crea una instancia de una clase es necesario crear una instancia de otra clase, evitable uniendo ambas en una úncia clase final.
- The Dispensables (los prescindibles), pistas aportadas por porciones de código innecesarias que podrían y deberían ser eliminadas:
- Lazy class (clase holgazana), una clase sin apenas responsabilidades que hay que dotar de sentido, o bien eliminar.
- Data class (clase de datos), cuando una clase sólo se utiliza para almacenar datos, pero no dispone de métodos asociados a éstos.
- Duplicate code (código duplicado), presencia de código duplicado que dificulta enormemente el mantenimiento.
- Dead code (código muerto), aparición de código que no se utiliza, probablemente procedente de versiones anteriores, prototipos o pruebas.
- Speculative generality (generalización especulativa), ocurre cuando un código intenta solucionar problemas más allá de sus necesidades actuales.
- The couplers (Los emparejadores), son code smells que alertan sobre problemas de acoplamiento componentes, a veces excesivo y otras demasiado escaso.
- Features envy (envidia de características), que aparece cuando existe un método de una clase que utiliza extensivamente métodos de otra clase y podría sugerir la necesidad de moverlo a ésta.
- Inappropriate intimacy (intimidad inapropiada), ocurre cuando dos clases de conocen demasiado y usan con demasiada confianza, y a veces de forma inapropiada, sus miembros (en la acepción POO del término ;-))
- Message Chains (cadenas de mensajes), aroma desprendido por código que realiza una cadena de llamadas a métodos de clases distintas utilizando como parámetros el retorno de las llamadas anteriores, como
A.getB().getC().getD().getTheNeededData()
, que dejan entrever un acoplamiento excesivo de la primera clase con la última. - Middle man (intermediario), que cuestiona la necesidad de tener clases cuyo único objetivo es actuar de intermediaria entre otras dos clases.
Aunque agrupadas bajo otros criterios, existe una interesante relación de code smells y la refactorización a aplicar en cada caso, que ayuda a determinar las acciones correctivas oportunas una vez se haya comprobado que hay algo que no va bien.
Y ahora, ¿piensas que tu código no huele a nada? ;-P
Publicado en: http://www.variablenotfound.com/.
Publicado por José M. Aguilar a las 10:12 p. m.
Etiquetas: buenas prácticas, desarrollo, programación

Y aunque pueda parecer similar a FxCop, Microsoft Source Analysis for C# se centra en el análisis de código fuente y no en ensamblados, lo que hace que pueda afinar mucho más en las reglas de codificación.
Incluye sobre 200 buenas prácticas, cubriendo aspectos como:
- Layout (disposición) de elementos, instrucciones, expresiones y consultas
- Ubicación de llaves, paréntesis, corchetes, etc.
- Espaciado alrededor de palabras clave y operadores
- Espaciado entre líneas
- Ubicación de parámetros en llamadas y declaraciones de métodos
- Ordenación de elementos de una clase
- Formateo de documentación de elementos y archivos
- Nombrado de campos y variables
- Uso de tipos integrados
- Uso de modificadores de acceso
- Contenidos permitidos en archivos
- Texto de depuración

Tras su descarga e instalación, que puede realizarse desde esta dirección, la herramienta se integra en Visual Studio 2005 y 2008, aunque también puede utilizarse desde la línea de comandos o MSBuild.
Publicado en: www.variablenotfound.com.
Publicado por José M. Aguilar a las 12:49 p. m.
Etiquetas: buenas prácticas, c#, desarrollo, herramientas, vs2008

4. Emoticonos corporales y otras extensiones
Aunque en su nacimiento los emoticonos sólo intentaban simular gestos faciales, existen una interesante variedad de ellos que simulan cuerpos completos y posturas que, de la misma manera, transmiten contenido de tipo emocional.Por ejemplo, los siguientes emoticonos representan a una persona arrodillada o haciendo reverencias en esta postura. Siempre la letra "o" aparece como cabeza, le sigue el tronco y un brazo en el suelo y finalmente las piernas flexionadas:
orz, _| ̄|○, OTL Or2, Orz, On_, OTZ, O7Z, Sto, Jto, _no
Estos emoticonos suelen representar ideas distintas en función de la cultura. En Japón, se interpreta como fracaso y desesperación; los usuarios Chinos, en cambio, lo usan más frecuentemente para expresar admiración a la consecución de un objetivo. Hay también quien lo utiliza para mostrar una risa extrema ("retorcerse de risa").
Otros de este tipo podrían ser:
O-&-< | Persona con los brazos cruzados |
~~~~\0/~~~~ | Ahogándose |
Pero hay muchos más, y algunos son obras de arte: posturas, retratos de celebridades, objetos... De hecho, algunos de ellos podrían describirse mejor como arte ASCII que como emoticonos, pues no llevan asociadas emociones y se trata simplemente de adornos textuales:
Cuerpos... | |
(:-))-|-< | Cuerpo completo |
X=(;-))-|8-<= | Novia |
Celebridades... | |
( 8^(l) | Homer Simpson |
=:o] | Bill Clinton |
@:-() | Elvis Presley |
Objetos... | |
@>+-+-- | Una rosa |
<')))))><< | Un pez |
... |
En Canonical Smiley List hay 2227 emoticonos de este tipo.
5. Emoticonos zurdos

No suelen utilizarse demasiado dado que suelen provocar confusión en los lectores, acostumbrados a la orientación habitual.

6. Emoticonos asiáticos
En 1986 surgieron en Japón una nueva familia de emoticonos, que se popularizaron muy rápidamente entre los países de Asia del este. Las dos diferencias principales respecto a los habituales en el mundo occidental son, en primer lugar, que pueden entenderse fácilmente sin necesidad de tumbar la cabeza hacia un lado y, en segundo lugar, que la expresión o emoción suele representarse eligiendo caracteres diversos para los ojos, en lugar de la boca. Algunos ejemplos simples:(^_^) | Sonrisa |
(T_T) | Llorando |
(o_#) | Magullado |
(O_O) | Sorprendido |
(~o~) | Un bostezo |
(Puedes encontrar más aquí)
Existen también otros emoticonos que hacen uso de los juegos de caracteres especiales que es necesario tener instalados en el ordenador:
![]() | Lanzando un suriken |
![]() | Escribiendo |
![]() | ¡Salud! |
(Aquí hay muchos más, pero para verlos necesitarás instalar el paquete de idioma japonés en tu máquina)
7. Emoticonos... ¿patentados?

Poco después, el 2 de enero de 2001, lanzaron una nota de prensa anunciando que emprenderían acciones legales contra los usuarios de Internet que utilizaran este símbolo en sus mensajes de correo electrónico, y que ya habían cursado un total de 7 millones de denuncias individuales.
En realidad, no se trataba más que de una broma, una forma de llamar la atención y dar a conocer su compañía, dedicada a la comercialización de material gráfico con mensajes humorísticos. Incluso el director de la compañía, Edward Lawrence Kersten, indicó que estaba considerando cambiar su propio nombre a :-( pues "le apetecía que su nombre simbolizara la infelicidad".
Sin embargo, no todo el mundo entendió la broma, y se generó un inmenso revuelo a nivel mundial, acusando a la compañía de querer apropiarse de un bien universal. Tanto fue así que un mes más tarde publicaron otra nota de prensa, en la que, también en tono jocoso, la empresa se comprometía con la comunidad global de internet a permitir el uso legal del emoticono en el email, vendiéndolos a través de su propia web bajo el nombre comercial Frownies™ y siempre que los usuarios se comprometieran en el cumplimiento de una desmadrada licencia de usuario final.

También es conocido que los emoticonos :-) y :) están registrados en Finlandia. Igualmente han sido polémicos otros registros y patentes relacionadas, como las efectuadas por Cingular en 2006 relativo a su uso en teléfonos móviles, o la solicitud de patente de Microsoft sobre la forma de crear y trasmitir emoticonos personalizados.
8. Emoticonos y accesibilidad
Desde el punto de vista de la accesibilidad un emoticono es exactamente igual que cualquier otro elemento no textual, por lo que debe prestársele especial atención para asegurar el acceso universal a la información.Las WCAG 1.0 (Pautas de Accesibilidad al Contenido Web) recoge como prioridad de nivel 1 proporcionar un texto equivalente para todo contenido no textual, incluyendo, expresamente, a los smileys o emoticonos entre ellos, a los que considera como arte ASCII.
Por ejemplo, el test automatizado Web Accessibility Checker incluye como problema el uso excesivo de emoticonos, o el hecho de no rodear éstos entre etiquetas como sigue:
<abbr title="emoticono de sonrisa">:-)</abbr>
Punto extra: ¿y el futuro?
Hoy en día los emoticonos basados en texto están siendo sustituidos por versiones gráficas, con efectos y animaciones e incluso sonidos. Aplicaciones de uso muy común, como procesadores de texto o clientes de mensajería instantánea realizan la conversión al modelo gráfico de forma automática, e incluyen atajos o botones en sus interfaces para incluirlos, por lo que es probable que en unos años los iconos textuales pasen a ser historias de veteranos nostálgicos, como muchas otras.Lo que sin duda perdudará será el concepto, la necesidad de añadir el contenido emocional a los mensajes escritos, sea cual sea su forma.
¡Larga vida al emoticono!
Fuentes:
- Language Logs, the prehistory of emoticons
- Wikipedia: Emoticons
- Emoticonos en Wikipedia
- El País: 25 años guiñando
- Internet Movie Database (IMDb)
- Web Accessibility Initiative (WAI)
Publicado en: http://www.variablenotfound.com/.
Publicado por José M. Aguilar a las 10:35 p. m.
Etiquetas: curiosidades, emoticonos, historias, servicios on-line, tecnología

Y probablemente debido a su cotidianeidad, hasta ahora no les había prestado demasiada atención. Sin embargo, cuando he buscado un poco de información sobre ellos, he encontrado algunas curiosidades que creo que vale la pena conocer.
1. Sobre el término emoticono
El término emoticono es la traducción del portmanteau inglés "emoticon", fusión de "emotion" + "icon", en clara referencia a que se trata de un icono para representar emociones. Fue introducido por David W. Sanderson en su libro "Smileys" publicado en 1993, años después de la popularización de los mismos.
La 22ª edición del Diccionario de la Real Academia Española, del año 2001, definió el término emoticono como:
"Símbolo gráfico que se utiliza en las comunicaciones a través del correo electrónico y sirve para expresar el estado de ánimo del remitente"Accediendo a la definición, sin embargo, se puede comprobar que ésta ha sido enmendada y la próxima edición contará con una más acorde con la realidad, donde se deja notar el avance tecnológico producido desde entonces:
"Representación de una expresión facial que se utiliza en mensajes electrónicos para aludir al estado de ánimo del remitente"De la misma forma, en la actualidad se acepta el término emoticón (con plural emoticones), pero parece ser que puede ser eliminado en futuras ediciones del diccionario.
2. Antecedentes históricos
La necesidad de asociar sentimientos y emociones a textos escritos existía mucho antes de la creación de los emoticonos y de la aparición de las redes de ordenadores. De hecho, se conocen apariciones anteriores de conceptos similares, aunque adaptados al medio del momento.Está documentado el uso, en abril de 1857, del código numérico "73" como una forma de añadir a un mensaje escrito en código Morse un afectuoso "love and kisses", que más adelante pasó a formalizarse como "best regards". Ya más adelante, a principios del siglo XX, se volvió a añadir este amoroso sentimiento, codificándolo como "88".


Este mismo signo fue descrito también por Vladimir Nabovok, escritor de origen ruso conocido, sobre todo, por ser el autor de la famosa novela Lolita, en una entrevista realizada por el New York Times en abril de 1969, donde respondía a una cuestión sobre su valoración respecto a otros escritores de la época y anteriores:
I often think there should exist a special typographical sign for a smile -- some sort of concave mark, a supine round bracket which I would now like to trace in reply to your question.
_______________________________________
A menudo pienso que debería existir un símbolo tipográfico especial para una sonrisa -- algo parecido a una marca cóncava, un paréntesis tendido que me gustaría registrar como respuesta a su pregunta.

Today You'll laugh :-) You'll cry :-( You'll love <3 'Lili'
_______________________________________
Hoy reirás :-) Llorarás :-( Amarás <3 'Lili'

3. El origen de los emoticonos en comunicaciones digitales
En abril de 1979, Kevin MacKenzie sugirió a los suscriptores de MsgGroup, una de las primeras listas de distribución de ARPANET, el origen de la Internet de hoy en día, la utilización de algún mecanismo para indicar emociones en el inexpresivo correo electrónico. Concretamente, se le atribuye el uso del símbolo "-)" para indicar contenidos irónicos en su mensaje:Perhaps we could extend the set of punctuation we use, i.e.: If I wish to indicate that a particular sentence is meant with tongue-in-cheek, I would write it so:Aunque su propuesta concreta no fue acogida con especial entusiasmo, los pioneros de las redes de comunicación comenzaron a utilizar variantes de estas expresiones en sus mensajes, la mayoría de las cuales no ha trascendido hasta la actualidad.
"Of course you know I agree with all the current administration's policies -)."
The "-)" indicates tongue-in-cheek.
_______________________________________
Quizás deberíamos extender el conjunto de signos de puntuación que utilizamos, por ejemplo: si quiero indicar que una frase en particular debe ser entendida como una ironía, la escribiría así:
"Por supuesto, sabes que estoy de acuerdo con todas las políticas actuales de la administración -)"
El "-)" indica que el mensaje es irónico.
Más tarde, en septiembre de 1982, Scott Fahlman envió el siguiente mensaje a un tablón de la BBS de la Universidad Carnegie Melon:
19-Sep-82 11:44 Scott E Fahlman :-)
From: Scott E Fahlman
I propose that the following character sequence for joke markers:
:-)
Read it sideways. Actually, it is probably more economical to mark
things that are NOT jokes, given current trends. For this, use
:-(
_______________________________________
Propongo la siguiente secuencia de caracteres para marcar las bromas:
:-)
Leedlo inclinando la cabeza. En realidad, probablemente sea más económico marcar lo que NO sea broma, dada la tendencia actual. En este caso, usad
:-(

Estos emoticonos sí fueron aceptados, y a partir de ese momento comenzó su utilización de forma masiva. Por esta razón, se considera a Fahlman como el padre de los emoticonos tal y como hoy los conocemos, aunque no todo el mundo está de acuerdo con ello.
Él mismo afirma en un artículo que es el inventor del emoticono lateral... o al menos uno de ellos. Pero sí está seguro de haber sido el primero en utilizar la secuencia :-) para indicar una broma en el medio digital.
4. Emoticonos corporales y otras extensiones
Continuar leyendo en 8 curiosidades que quizás no conocías sobre los emoticonos, segunda parte.Publicado por José M. Aguilar a las 10:30 p. m.
Etiquetas: curiosidades, emoticonos, historias, servicios on-line, tecnología

Bueno, en cualquier caso, es buen momento para recapitular un poco y reflexionar sobre el camino recorrido desde mayo de 2006, cuando con cierto recato publicaba mi post inaugural en la dirección de Blogger jmaguilar.blogspot.com.
Hasta el momento podríamos hablar de dos periodos:
Año 1: la travesía del desierto (mayo 2006 - mayo 2007). Supongo que todos los que mantenéis un blog entenderéis esta expresión (bueno, quizás salvo los propiciados por las grandes productoras o personal especialmente mediático).
La principal característica de este periodo fue la ausencia casi total de lectores. Salvo algún inexplicable pico puntual de visitas como el obtenido por el post sobre Google Image Labeler, durante nueve meses estuve prácticamente escribiendo para mí.
Tampoco tenía demasiado tiempo para dedicarle, pero de vez en cuando lo daba de alta en buscadores y sitios de referencia para lograr una mayor difusión, aunque lo cierto es que estas acciones no resultaban demasiado efectivas.
Fue a finales de marzo de 2007, casi cumpliendo ya el primer año, cuando el maestro Juanjo Navarro (¡gracias, Juanjo!) me incluyó en el agregador Planeta Código e hizo referencia en su blog Más que código a mi serie de posts sobre técnicas de spam, lo que supuso un fuerte empujón para dar a conocer el blog y difundir un poco sus contenidos.Año 2: el despegue (mayo 2007 - mayo 2008). Coincidiendo con un aumento de disponibilidad de tiempo libre, comenzamos el segundo año de vida adquiriendo el nombre de dominio variablenotfound.com y activando Feedburner para la gestión de feeds, pues hasta ese momento no había prestado demasiada atención a los suscriptores (!).
Pero no quedaron ahí los cambios. A finales de 2007, por cortesía de Javier Cantos (¡gracias, Javi!), por fin pude dejar atrás el diseño basado en una plantilla estándar de Blogger y, tras encarnizada batalla, conseguí que el blog luciera así de bien.
También resultó decisiva la inclusión del blog en otros agregadores como Planet WebDev (¡gracias, Héctor!) o crosspostear en Geeks.ms (¡gracias, Rodrigo!).
Como consecuencia de todo esto, este año se ha producido un incremento brutal del número de visitas(es obvio, partía de cero ;-D)), rozando en la actualidad la cifra de 10.000 al mes, sólo a variablenotfound.com. Aunque no sé si es causa o consecuencia de lo anterior, durante este año he sufrido también varios meneos que bien podría calificar de terremotos, y muchos enlaces, algunos desde fuentes de gran relevancia como Microsiervos, Genbeta, o Error500.
En cuanto a los suscriptores de feeds, la siguiente gráfica muestra el estado a día de hoy, y cómo nos vamos acercando a los 400, una cifra impensable ni en mis aspiraciones más optimistas, y a mi entender impresionante dada la temática tan específica del blog.
Pero, ¿vale la pena esto? Haciendo un cálculo rápido y tirando muy por lo bajo, si hubiera necesitado sólo un par de horas por cada uno de los 158 posts que he publicado hasta el momento (os aseguro que la media es mucho más alta, sumando el tiempo de escribir, estudiar, maquetar, comprobar, buscar fuentes...), llevaría dedicadas al blog más de 300 horas; en el mundo laboral, supondría un par de meses a jornada completa. Fuerte, ¿eh?
Menos mal que desde el punto de vista económico el blog es todo un éxito. De hecho, acabo de cambiar de coche gracias a los ingresos generados por AdSense, y espero en breve adquirir un apartamentito en la playa a cargo los importantes beneficios que me reporta Amazon.

Obviamente a nadie le amarga un dulce, y ya que se dedica tiempo a ello no estaría mal rentabilizarlo un poco, pero está claro que si merece o no la pena seguir con Variable not found no depende de los ingresos económicos generados, sino de otros factores.
Durante este tiempo he aprendido como nunca lo había hecho. La escritura de un post con un contenido técnico medianamente complejo requiere una asimilación mucho más profunda de la que se consigue con una simple lectura; también la creación de ejemplos, comprobaciones, o la búsqueda de información, resulta muy enriquecedora. Si a esto, además, se une las aportaciones y retroalimentación de los lectores vía comentarios o contacto directo, os puedo asegurar que la experiencia es alucinante.
Y es precisamente en esto último donde se encuentra la mayor recompensa, en los cientos de lectores que visitan Variable not found cada día, vía web o lector RSS, y animan a continuar en la brecha.
Gracias a todos, y espero que sigáis por aquí, buscando la variable.
Publicado en: www.variablenotfound.com.
Publicado por José M. Aguilar a las 10:09 p. m.
Etiquetas: aniversario, autobombo, blogging, historias

Además de seguir tapando huecos en la pared, nos valdrá para tener a mano una referencia rápida (muy rápida) de jQuery, donde encontraremos funciones, selectores, eventos, métodos de manipulación, efectos y utilidades de esta magnífica librería javascript.
Publicado en: www.variablenotfound.com.

Como recordaréis, hasta ese momento las acciones no tenían tipo de retorno, pero han replanteado el diseño para hacerlo más flexible, testable y potente. Así, pasamos de definir las acciones de esta forma:
public void Index()
{
RenderView("Index");
}
a esta otra:
public ActionResult Index()
{
return RenderView();
}
En el código anterior destacan dos aspectos. En primer lugar que la llamada a
RenderView()
no tiene parámetros; el sistema mostrará la vista cuyo nombre coincida con el de la acción que se está ejecutando (Index, en este caso). En segundo lugar, que la llamada a RenderView()
retorna un objeto ActionResult
(o más concretamente un descendiente, RenderViewResult
), que será el devuelto por la acción.De la misma forma, existen tipos de ActionResult concretos para retornar el resultado de las acciones más habituales:
RenderViewResult
, retornado cuando se llama desde el controlador aRenderView()
.ActionRedirectResult
, retornado al llamar aRedirectToAction()
HttpRedirectResult
, que será la respuesta a unRedirect()
EmptyResult
, que intuyo que será para casos en los que no hay que hacer nada (!), aunque todavía no le he visto mucho el sentido...
Además de las citadas anteriormente, una de las ventajas de retornar estos objetos desde los controladores es que podemos crear nuestra clase, siempre heredando de
ActionResult
, e implementar comportamientos personalizados.Esto es lo que ha hecho el genial Phil Haack en dos ejemplos recientemente publicados en su blog.
El primero de ellos, publicado en el post "Writing A Custom File Download Action Result For ASP.NET MVC" muestra una implementación de una acción cuya invocación hace que el cliente descargue, mediante un download, el archivo indicado, en su ejemplo, el archivo CSS de su sitio web:
public ActionResult Download()
{
return new DownloadResult
{ VirtualPath="~/content/site.css",
FileDownloadName = "TheSiteCss.css"
};
}
La clase
DownloadResult
una descendiente de ActionResult
, en cuya implementación encontraremos, además de la definición de las propiedades VirtualPath
y FileDownloadName
, la implementación del método ExecuteResult
, que será invocado por el framework al finalizar la ejecución de la acción, y donde realmente se realiza el envío al cliente del archivo, con parámetro content-disposition convenientemente establecido:public class DownloadResult : ActionResult
{
public DownloadResult()
{
}
public DownloadResult(string virtualPath)
{
this.VirtualPath = virtualPath;
}
public string VirtualPath { get; set; }
public string FileDownloadName { get; set; }
public override void ExecuteResult(ControllerContext context)
{
if (!String.IsNullOrEmpty(FileDownloadName)) {
context.HttpContext.Response.AddHeader("content-disposition",
"attachment; filename=" + this.FileDownloadName)
}
string filePath = context.HttpContext.Server.MapPath(this.VirtualPath);
context.HttpContext.Response.TransmitFile(filePath);
}
}
El segundo ejemplo, publicado en el post "Delegating Action Result", vuelve a demostrar otro posible uso de los ActionResults creando un nuevo descendiente,
DelegatingResult
, que puede ser retornado desde las acciones para indicar qué operaciones deben llevarse a cabo por el framework.El siguiente código muestra cómo retornamos un objeto de este tipo, inicializado con una lambda:
public ActionResult Hello()
{
return new DelegatingResult(context =>
{
context.HttpContext.Response.AddHeader("something", "something");
context.HttpContext.Response.Write("Hello World!");
});
}
Como veremos a continuación, el constructor de este nuevo tipo recibe un parámetro de tipo
Action<ControllerContext>
y lo almacenará de forma local en la propiedad Command
, postergando su ejecución hasta más adelante; será la sobreescritura del método ExecuteResult
la que ejecutará el comando:public class DelegatingResult : ActionResult
{
public Action<ControllerContext> Command { get; private set; }
public DelegatingResult(Action<ControllerContext> command)
{
this.Command = command;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
Command(context);
}
}
Puedes ver el código completo de ambos ejemplos, así como descargar proyectos de prueba en los artículos originales de Phil Haack:
Por último, recordar que todos estos detalles son relativos a la última actualización de la preview de esta tecnología y podrían variar en futuras revisiones.
Publicado en: www.variablenotfound.com.
Publicado por José M. Aguilar a las 10:00 p. m.
Etiquetas: .net, asp.net, aspnetmvc, c#, desarrollo, programación
Fisix, por ejemplo, es un motor de física en 2 dimensiones desarrollado en ActionScript 3.0 para desarrolladores de juegos o simuladores en Flash. Aunque en su web podéis encontrar más demos, incrusto una aquí para que os hagáis a la idea de lo que puede llegar a conseguirse con esta librería (podéis probar a arrastrar la muñeca por la pantalla o interactuar con los objetos).
Actualmente se encuentra en su versión alfa 0.5, y puede ser utilizado sin coste exclusivamente en proyectos no comerciales; para otros usos hay que contactar con el autor. En cualquier caso, por el tiempo que ha pasado desde su última actualización, parece que no está muy al día.
Publicado en: www.variablenotfound.com.
Publicado por José M. Aguilar a las 9:55 p. m.
Etiquetas: curiosidades, desarrollo, motores de física

Como sabemos, si desde una aplicación queremos obtener una descripción comprensible de un elemento de una enumeración, normalmente no podemos realizar una conversión directa (
elemento.ToString()
) del mismo, pues obtenemos los nombres de los identificadores usados a nivel de código. La solución habitual, hasta la llegada de C# 3.0 consistía en incluir dentro de alguna clase de utilidad un conversor estático que recibiera como parámetro en elemento de la enumeración y retornara un string, algo así como:
public static string EstadoProyecto2String(EstadoProyecto e)
{
switch (e)
{
case EstadoProyecto.PendienteDeAceptacion:
return "Pendiente de aceptación";
case EstadoProyecto.EnRealizacion:
return "En realización";
case EstadoProyecto.Finalizado:
return "Finalizado";
default:
throw
new ArgumentOutOfRangeException("Error: " + e);
}
}
Este método, sin embargo, presenta algunos inconvenientes. En primer lugar, dado el tipado fuerte del parámetro de entrada del método, es necesario crear una función similar para cada enumeración sobre la que queramos realizar la operación.
También puede resultar peligroso separar la definición de la enumeración del método que transforma sus elementos a cadena de caracteres, puesto que puede perderse la sincronización entre ambos cuando, por ejemplo, se introduzca un nuevo elemento en ella y no se actualice el método con la descripción asociada.
La solución, que como he comentado me pareció muy interesante, consiste en decorar cada elemento de la enumeración con un atributo que describa al mismo, e implementar un método de extensión sobre la clase base
System.Enum
para obtener estos valores. Veamos cómo.Ah, una cosa más. Aunque los ejemplos están escritos en C#, se puede conseguir exactamente el mismo resultado en VB.NET simplemente realizando las correspondientes adaptaciones sintácticas. Podrás encontrarlo al final del post.
1. Declaración de la enumeración
Vamos a usar el atributoSystem.ComponentModel.DescriptionAttribute
, aunque podríamos usar cualquier otro que nos interese, o incluso crear nuestro propio atributo personalizado. El código de definición de la enumeración sería así:
using System.ComponentModel;
public enum EstadoProyecto
{
[Description("Pendiente de aceptación")] PendienteDeAceptacion,
[Description("En realización")] EnRealizacion,
[Description("Finalizado")] Finalizado,
[Description("Facturado y cerrado")] FacturadoYCerrado
}
2. Implementación del método de extensión
Ahora vamos a crear el método de extensión (¿qué son los métodos de extensión?) que se aplicará a todas las enumeraciones.Fijaos que el parámetro de entrada del método está precedido por la palabra reservada
this
y el tipo es System.Enum
, por lo que será aplicable a cualquier enumeración.
using System;
using System.ComponentModel;
using System.Reflection;
public static class Utils
{
public static string GetDescription(this Enum e)
{
FieldInfo field = e.GetType().GetField(e.ToString());
if (field != null)
{
object[] attribs =
field.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attribs.Length > 0)
return (attribs[0] as DescriptionAttribute).Description;
}
return e.ToString();
}
}

GetDescription()
, que nos devolverá el texto asociado al elemento de la enumeración; si éste no existe, es decir, si no se ha decorado el elemento con el atributo apropiado, nos devolverá el identificador utilizado.De esta forma eliminamos de un plumazo los dos inconvenientes citados anteriormente: la separación entre la definición de la enumeración y los textos descriptivos, y la necesidad de crear un conversor a texto por cada enumeración que usemos en nuestra aplicación.
Y por cierto, el equivalente en VB.NET completo sería:
Imports System.ComponentModel
Imports System.Reflection
Imports System.Runtime.CompilerServices
Module Module1
Public Enum EstadoProyecto
<Description("Pendiente de aceptación")> PendienteDeAceptacion
<Description("En realización")> EnRealizacion
<Description("Finalizado")> Finalizado
<Description("Facturado y cerrado")> FacturadoYCerrado
End Enum
<Extension()> _
Public Function GetDescription(ByVal e As System.Enum) As String
Dim field As FieldInfo = e.GetType().GetField(e.ToString())
If Not (field Is Nothing) Then
Dim attribs() As Object = _
field.GetCustomAttributes(GetType(DescriptionAttribute), False)
If attribs.Length > 0 Then
Return CType(attribs(0), DescriptionAttribute).Description
End If
End If
Return e.ToString()
End Function
End Module
Publicado en: www.variablenotfound.com.

El archivo distribuido, un zip, contiene siete chuletas en formato PDF:
- Extensiones a los tipos
String
yObject
- Extensiones a los tipos
Number
yError
- Referencia del tipo
DomEvent
- Extensiones al tipo
DomElement
- Extensiones a los tipos
Date
yBoolean
- Eventos del ciclo de vida en cliente
- Extensiones al tipo
Array
Publicado en: www.variablenotfound.com.
Publicado por José M. Aguilar a las 10:01 p. m.
Etiquetas: ajax, asp.net, chuletas, desarrollo, javascript, programación

C# 3.0 nos trae otra sorpresa, también relacionada con el establecimiento de valores iniciales de elementos: los inicializadores de colecciones. Aunque esta característica también estaba prevista para VB.Net 9.0, al final fue desplazada a futuras versiones por problemas de tiempo.
Para inicializar una colección, hasta ahora era necesario en primer lugar crear la clase correspondiente para, a continuación, realizar sucesivas invocaciones al método
Add()
con cada uno de los elementos a añadir: List<string> ls = new List<string>();
ls.Add("Uno");
ls.Add("Dos");
ls.Add("Tres");
C# 3.0 permite una alternativa mucho más elegante y rápida de codificar, simplemente se introducen los elementos a añadir a la colección entre llaves (como se hacía con los inicializadores de arrays o los nuevos inicializadores de objetos), separados por comas, como en el siguiente ejemplo:
List<string> ls =
new List<string>() { "Uno", "Dos", "Tres" };
Si desensamblamos el ejecutable resultante, podremos ver que es el compilador el que ha añadido por nosotros los
Add()
de cada uno de los elementos después de instanciar la colección:
newobj instance void class
[mscorlib]System.Collections.Generic.List`1<string>::.ctor()
stloc.s '<>g__initLocal0'
ldloc.s '<>g__initLocal0'
ldstr "Uno"
callvirt instance void class
[mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
nop
ldloc.s '<>g__initLocal0'
ldstr "Dos"
callvirt instance void class
[mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
nop
ldloc.s '<>g__initLocal0'
ldstr "Tres"
callvirt instance void class
[mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
nop
Uniendo esto ahora con los inicializadores de objetos que ya tratamos un post anterior, fijaos en la potencia del resultado:
List<Persona> lp = new List<Persona>
{
new Persona { Nombre="Juan", Edad=34 },
new Persona { Nombre="Luis", Edad=53 },
new Persona { Nombre="José", Edad=23 }
};
Efectivamente, cada elemento es una nueva instancia de la clase Persona, con las propiedades que nos interesan inicializadas de forma directa. De hacerlo con los métodos tradicionales, para conseguir el mismo resultado deberíamos utilizar muuuchas más líneas de código.
Otro ejemplo que demuestra aún más la potencia de esta característica:
var nums = new SortedList
{
{ 34, "Treinta y cuatro" },
{ 12, "Doce" },
{ 3, "Tres" }
};
foreach (var e in nums)
Console.WriteLine(e.Key + " " + e.Value);
En el código anterior podemos ver, primero, el uso de variables locales de tipo implícito, para ahorrarnos tener que escribir más de la cuenta. En segundo lugar, se muestra cómo se inicializa una colección cuyo método
Add()
requiere dos parámetros. En el caso de un SortedList<TKey, TValue>
, su método Add()
requiere la clave de ordenación y el valor del elemento.(Obviamente, el resultado de la ejecución del código anterior será la lista ordenada por su valor numérico (Key))
En conclusión, se trata de otra de las innumerables ventajas que nos ofrece la nueva versión de C# destinadas a evitarnos pulsaciones innecesarias, y a la que seguro le daremos uso.
Publicado en: www.variablenotfound.com.
Puedes descargarla pulsando sobre la imagen:

Si quieres leer más sobre estos operadores, puedes probar también en la referencia oficial, The .Net Standard Query Operators [ING], a leer este artículo traducido por el maestro Octavio Hernández, profundizar en MSDN, o en otros de los muchos sitios con información relacionada, como la referencia de Hooked On Linq [ING].
Publicado en: http://www.variablenotfound.com/.