AndorraDotNet

Comunitat d'usuaris .NET del pais dels pirineus
¿No perteneces a AndorraDotNet? ¡Regístrate y sé un miembro!
Iniciar sesión | REGÍSTRATE AQUÍ | Ayuda
en Buscar

400 Bad Request

Dímelo con flores ;-)
  • Cumpleaños + Nacimiento = Día inolvidable

    :-)
    Menuda ecuación, verdad?

    Pues esto es lo que ha sucedido hoy: Cumplo 37 'tacos' y ha nacido MARA, mi segunda hija. Casi nada...

    La verdad es que ha sido el mejor regalo de cumpleaños que he tenido jamás, y los he tenido muy buenos ;-), pero ninguno comparable a este (*). Además no ha sido 'pactado' con el médico ni nada, simplemente han sido casualidades de la vida. Aunque si te lo paras a pensar, una entre 365 no es nada comparado con las probabilidades de que te toque la lotería, jejeje... Que demonios! soy un tipo afortunado.

    El parto ha ido muy bien, y aunque ahora acabo de poner a mi otra niña a dormir y estoy un poco hecho polvo, ha sido de esos días de los que sabes que te vas a acordar toda tu vida. La niña está bien y es requeteguapa (que voy a decir yo, no?), y la mamá también, y se encuentra bastante bien para lo que ha tenido que pasar :-P

    En fin, os dejo con algunas fotos, que yo tengo que ir a prepararme un examen para mañana, y si todo va bien ya os contaré... que eso da para otra historia.

    DSC02373 DSC02379

    DSC02380 DSC02382

     DSC02384 DSC02385

    DSC02386 DSC02389

     DSC02390 DSC02392

    1º Foto: El día anterior, última foto antes de salir.
    2º Foto: Justo antes de empezar la juerga
    3º Foto: Más que un tío a punto de entrar en quirófano parezco al ché guevara :-)
    4º Foto: Me han tenido esperando más de 20 minutos en un vestuario, y sólo había un par de armarios y esta señal (un tío colgado, está claro no?)
    5º Foto: Lo que puede llegar a hacer uno para olvidar los nervios :-P
    6º Foto: Demostrado: El tiempo es relativo. Cuánta razón llevaba Albert...
    7º Foto: Por fin está aquí! Primera foto de MARA.
    8º Foto: Subiendo a la habitación
    9º Foto: Ya estamos listas para la foto oficial
    10º Foto: En casa, con mi otra peque soplando las velitas.

    Saludos desde Andorra,

    (*) Al Pani y al Marc los voy a marear para que me aconsejen con mi juguetito nuevo.

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
  • Application Architecture Guide 2.0

    Veo en el Blog de Somasegar que esta semana se ha liberado una beta de Application Architecture Guide 2.0. Esta guía es un compendio de principios, patrones y buenas prácticas para el diseño de arquitecturas de software, y su propósito es el de ayudar a los arquitectos y desarrolladores a diseñar y construir mejores aplicaciones sobre la plataforma .NET.

    AppGuidance

    Os dejo el link al artículo original, y algunos recursos asociados:

    Application Architecture Guide 2.0, Knowledge Base, Project News and Announcements.

    Saludos,

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
  • DXHelmet: El futuro de la interacción hombre - máquina

    Ver para creer… si hace unos años me dicen que esto sería posible no me lo hubiese creído.

    Como dicen ellos mismos:
    […] The future of software development is here - the way in which you interact with the computer will never be the same again...

    Helmet1 Helmet2

    No os digo más, darle un vistazo que vale la pena:
    http://devexpress.com/helmet

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
  • Series: Resumen de los enlaces

    Últimamente estoy recibiendo bastantes correos preguntándome cosas acerca de las series de posts que publiqué hace un tiempo. Os dejo aquí un resumen de los enlaces y el código fuente disponible en ellas. Ya estaba todo publicado pero de forma dispersa, así que aquí lo teneis todo juntito.

    Aviso: Todas las series son ejemplos reales que muestran cómo realizar algunas de las tareas cotidianas (o no tanto) mediante C#. En ningún caso pretenden ser aplicaciones reales, de modo que deben tomarse como lo que realmente son: Meros ejemplos didácticos.


    Internet2

    Acceder a la caché de Internet Explorer

    Resumen:

    Ejemplo de cómo crear un servicio de Windows que monitoriza la caché de archivos temporales de Internet Explorer y exporta un fichero log a una ubicación remota (por si el usuario decide vaciar la caché). Contiene ejemplos de cómo usar las API de acceso a la caché, cómo serializar objetos, realizar impersonation, y cómo crear y distribuir un servicio de Windows.

    Artículos:

    Acceder a la caché de Internet Explorer (I)
    Acceder a la caché de Internet Explorer (II)
    Acceder a la caché de Internet Explorer (III)
    Acceder a la caché de Internet Explorer (IV)
    Acceder a la caché de Internet Explorer (V)

    Código de ejemplo:


    ldap1

    Accediendo al directorio activo de la organización desde .NET

    Resumen:

    Ejemplo de cómo crear una aplicación Windows que accede al directorio activo de la organización. Contiene ejemplos de cómo validar unas credenciales (usuario y password) en un dominio, cómo realizar impersonation para ejecutar nuestra aplicación con los credenciales de otro usuario, recuperar los nombres de las propiedades del objeto user del AD, y cómo obtener información y los grupos a los que pertenece el usuario actual.

    Artículos:

    Accediendo al directorio activo de la organización desde .NET (I)
    Accediendo al directorio activo de la organización desde .NET (II)
    Accediendo al directorio activo de la organización desde .NET (III)
    Accediendo al directorio activo de la organización desde .NET (IV)

    Artículos relacionados:

    Corrección función getUserLDAPProperties
    HowTo: LDAP, obtener propiedades de la clase user

    Código de ejemplo:

    Saludos desde Andorra,

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
  • ADO.NET Data Services – Entrevista en Channel 9

    En este vídeo, Beth Massi entrevista a Saaid Kahn (Program Manager de Visual Studio Pro Tools team) y nos muestra cómo crear aplicaciones de n capas usando ADO.NET Data Services (Astoria) y el Entity Data Model.


    ADO.NET Data Services (Astoria) in Visual Studio 2008 SP1

    Absolutamente recomendable darle una ojeada. Dura poco más de un cuarto de hora y vale la pena.

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
  • El Guille community Tour 2008 pasó por Andorra…

    …y no he podido escribir nada hasta ahora… aisssss!

    LogoAndorraDotNetsmall

    La verdad es que he estado missing durante unos dias debido a que tengo una punta de trabajo terrible. Espero volver a dar un poco más la vara tanto aquí como el los foros online, de los que también he estado un poco desconectado.

    Pero a lo que iba: El pasado lunes 13 en AndorraDotNet tuvimos la suerte de poder contar con dos ponentes de lujo: El Guille y David Salgado de Microsoft. Guille nos habló de las novedades de VB 9.0 como no podía ser de otra manera, y hubieron muchos ‘piques’ entre los defensores de VB y de C#, con lo que nos reímos mucho.. David nos regaló una fantástica demo de cómo construir una aplicación Web mediante ASP.NET, en la que empezamos con una solución en blanco y fue creando poco a poco los diversos elementos del proyecto. Por cierto, que sepas que ya me la han pedido!!!

    DSC_3830 DSC_3833

    Al final de la sesión tuvimos el típico sorteo de regalos, en el que algunos afortunados se fueron con un regalo entre las manos.

    DSC_3852 DSC_3853

    DSC_3855 DSC_3857

    La audiencia estuvo sobre las casi 60 personas con perfiles muy diferentes, y aunque me hubiese gustado ver más gente de empresa (ya os tiraré de las orejas a los que no pudísteis asistir) no estuvo nada mal. Por nuestra parte seguiremos trabajando intentando cambiar la situación del país, ya que sigue siendo muy difícil hacer ver a los empresarios que la formación es un recurso vital para la buena marcha de un negocio (si, parece mentira pero hay mucha gente que todavía no lo tiene claro). Si queremos avanzar no hay que escatimar en formación y en I+D. Es por el bien del país!

    DSC_3845 DSC_3848

    Un agradecimiento especial al colega Jan Arbona de TSCP por su colaboración en el evento, y por habernos tirado un cable en los momentos de estrés.
    Gracias a todos y os espero en el próximo evento que ya estamos preparando!

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
  • MVP Open Day 2008 - Game over

    Otra vez en el tren de vuelta a casa. No puedo dejar de experimentar una sensación de deja vu, como cada vez que viajo a Madrid en busca de aquellos que son como yo. Entenderme, no me considero un bicho raro ni mucho menos, lo que sucede es que vivo en un país de apenas 60.000 habitantes, un número que apenas llenaría la mitad de un estadio de fútbol moderno, y que la mayoría de pueblos grandes o ciudades pequeñas de España sobrepasan de largo. Joer, si Cuenca (con todo el respeto) tiene más habitantes :-)

    Y claro, los números salen solos: De toda esta población hay poca gente del mundo de desarrollo de software, y menos todavía que tenga la misma pasión por el desarrollo que puedo tener yo. Sólo un pequeño pueblo de irreductibles galos resiste ahora y siempre al invasor. Bueno, no es exactamente así, pero seguro que me entendéis :-P. Me estoy refiriendo a que gracias a la gente del grupo de usuarios de andorradotnet, que comparte mi misma pasión por la plataforma .NET se me hace más llevadero el estar tan desconectado (físicamente, que no realmente) de otros profesionales del tema.

    DSC02226 DSC02229 DSC02231

    De este modo cuando voy a Madrid un par de veces al año, a uno de estos eventos en los que hay un nivelazo técnico importante, me hace disfrutar cada momento como un enano. Te pones a charlar con cualquiera sobre sobre arquitectura, características de nuestros lenguajes favoritos, favoritismos y manías que todos tenemos en nuestro trabajo, etc. Y como encima lo puedes hacer todo delante de una cerveza, hace que te sientas en el paraíso... Porque de eso se trata, somos tan freaks que cuando nos vamos de fiesta a tomar unas copas terminamos hablando de ciertas cosas que hacen que las mesas de al lado te miren con cara de "de dónde se han caído estos tíos". Eso si, lo pasamos como enanos, jejeje...

    Pero no me quiero ir por las ramas, que esto de estar en el tren sin wifi, y con dos horas por delante puede hacer que se me valla la olla un rato. De hecho este post es para comentar lo requetebien que lo he pasado en el MVP Open Day de este año.

    DSC02239 DSC02240 DSC02243

    Hemos tenido de todo: Sesiones técnicas de las buenas, contacto directo con profesionales de todas las áreas de Microsoft (siempre tienes alguna pregunta para un experto en SQL Server, de Server System, etc.), te encuentras con viejos amigos y haces de nuevos, conoces gente nueva interesante. También saludas a la gente de la casa que ya conoces desde hace años, sales a tomar algo, acabas en la barra de un bar con dos (o tres) copas de más discutiendo de buen rollo con un colega acerca de si en este caso es mejor aplicar herencia o implementar interfaces, y vuelves al hotel con unas risas y habiendo aprendido un par de cosas.

    Espero tener tiempo para ir desgranando algunas de las cosas que hemos visto en esta jornada, de momento os dejo con algunos de los momentos más interesantes de este evento. Ahora voy a seguir preparando los últimos detalles del próximo evento de andorradotnet dentro de 10 días.

    DSC02259 DSC02256 DSC02260

    Compañeros: Espero no tener que esperar otro año para veros de nuevo. Así que os amenazo con montar algún otro evento en andorradotnet para que subáis a verme o a dar alguna charla. Estáis avisados...

    Ahora voy a dedicar 10 minutos a ver el paisaje a más de 300 Km/h y dejar volar la imaginación... nos vemos.

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
  • Otro año más dando la vara

    mvp_hor

    Alguien de Microsoft se ha equivocado o le ha dado al botón que no era. Acabo de recibir un correo de mvpaward de dice así:

    Enhorabuena. Nos complace presentarle el programa de nombramiento MVP de Microsoft® de 2009. Este nombramiento se concede a los líderes excepcionales de la comunidad técnica que comparten de forma activa su experiencia de alta calidad y de la vida real con otras personas.

    Reconocido por MVP por 6º año consecutivo… WOW! No se si me lo acabo de creer… :-)

    La verdad es que desde tuve la suerte de entrar en el programa (hace 6 pero parece que haga un siglo, por tal y cómo ha cambiado mi vida desde entonces :-P), he tenido la gran suerte de poder conocer un montón de gente fantástica, tanto dentro como fuera de Microsoft. Y a decir verdad está resultando una gran experiencia a nivel personal y profesional, ya que me ha permitido conocer profesionales como la copa de un pino, y además hacer amigos de los que duran toda una vida.

    Además, mañana salgo para Madrid para participar en el MVP Open Day de este año, y tengo unas ganas tremendas de rencontrarme con todos los demás. En estos eventos las sesiones técnicas son impresionantes, pero es que además lo pasamos de miedo en las cenas, bautizos, etc.

    Para muestra un botón:

    Bautizo de un MVP:
    http://es.youtube.com/watch?v=KNwA7QlvKvk

    Fotos de varios eventos:
    MVP Summit 2005 (27/09/2005 - 01/10/2005)
    MVP Open day (19/05/2005 - 20/05/2005)
    MVP Open day (11/11/2004 - 12/11/2004)
    MVP Open Day (27/05/2004 - 28/05/2004)

    Nos vemos en las comunidades online!
    Saludos desde Andorra,

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
    Enviado Oct 01 2008, 05:24 PM por lfranco con no comments
    Archivado en: ,,
  • Silverlight 2 RC Disponible

    silverlight

    Leo en el blog de ScottGu, que esta madrugada se ha liberado la primera RC pública de Silverlight 2.

    Se han corregiso algunos bugs, se ha actualizado el API desde la versión anterior y han aparecido algunos elementos nuevos en el núcleo, como los controles ComboBox, ProgressBar, y PasswordBox (dejando el tamaño igualmente en 4.6MB).

    silverlight_controls

    También me ha llamado la atención la incorporación del MessageBox.Show(), que permite mostrar cuadros de mensaje como en una aplicación de escritorio:

    silverlight_msgbox

    Nuevos skins de controles, que han cambiado respecto a la Beta 1 y 2:

    silverlight_skins

    Una de las capacidades más potentes de Silverlight es la posibilidad para los diseñadores y desarrolladores de personalizar completamente el aspecto de cualquier control. Esto permite ir más allá de estilos simples de colores y fuentes. De hecho, literalmente podemos cambiar el interfaz de usuario visual de este control, así como personalizar su comportamiento (por ejemplo agregando animaciones) sin agregar ninguna línead de código.

    Cuando estamos editando la plantilla de un control, podemos manipular cualquier sub-elemento del control (por ejemplo, el contenido interno de un CheckBox), ásí cómo personalizar sus ‘estados’ (observar el panel de estados señalados en rojo). Esto permite a los diseñadores personalizar el aspecto del control en cada estado (seleccionado, no seleccionado, al pasar el mouse por encima, etc.).

    silverlight_states

    En fin, esto se anima ya que el lanzamiento final de Silverlight está cada vez más cerca!!!
    A disfrutarlo,

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
    Enviado Sep 26 2008, 10:04 AM por lfranco con no comments
    Archivado en: ,
  • Guille Community Tour 2008 – 13 Octubre 2008 en Andorra

    Guille Community Tour 2008 - Vista previaComo muchos ya sabréis, entre varios grupos de usuarios de España y parte del extranjero :-P, hemos organizado una gira con el ‘aguelo’ de todos los MVPs: Guillermo ‘el Guille’ Som. Nota: Que conste que si le llamo ‘aguelo’ es sólo por que es el MVP más antiguo, ya que ha sido nominado desde 1997 de forma ininterrumpida, y no a su edad (que como todos sabemos está hecho un chaval).

    Esta gira llegará a tierras Andorranas el 13 de Octubre, de modo que si estás cerca de aquí ya lo sabes ¡no puedes perdértelo!

    En ella Guille nos hablará de las novedades de VB2008, así que si eres desarrollador de software no te lo puedes perder, ya que Guillermo es una de las personas que más sabe de esto en España, y además es un ponente internacional que ha escrito multitud de libros al respecto.

    Y más todavía cuando también contaremos con la presencia de David ‘supermán’ Salgado, que nos ofrecerá una de sus estupendas sesiones sobre ‘Opciones para el desarrollo de un sitio web .NET’. La verdad es que tiene una pinta estupenda, ya que David es un crack dentro de los cracks.

    Para cerrar la reunión responderemos a las preguntas que se hayan planteado en el foro de AndorraDotNet que hemos habilitado para tal efecto:
    http://andorradotnet.com/forums/t/277.aspx

    Y como siempre, realizaremos sorteos de regalos entre los asistentes, aunque aquí me gustaría hacer una aclaración:

    Esta es una gira solidaria, ya que gracias al Guille y su corazón de oso hemos conseguido que varias empresas importantes nos cedan licencias de software (desde un Visual Studio 2008 Profesional o dos suscripcions MSDN premium hasta diez licencias de ReSharper y dotTrace), y de éste modo las podamos sortear para recaudar fondos para ayudar a un niño a superar una enfermedad: ¡Ayuda a Juanma a vivir!.

    Más información sobre Juanma en:
    http://www.ayudajuanma.es/
    http://geeks.ms/blogs/lfranco/archive/2008/03/03/no-t-233-cnico-ma-241-ana-cumple-a-241-os-juansa.aspx

    Agenda del evento
    09:30 a 09:45 – Entrada y registro
    09:45 a 10:00 – Bienvenida del grupo de usuarios AndorraDotNet - Lluis Franco
    10:00 a 11:45 – ‘Novedades de VB 9.0’ - El Guille
    11:45 a 12:00 – Café i descanso
    12:00 a 13:30 – ‘Opciones para el desarrollo de un sitio web .NET’ - David Salgado
    13:30 a 14:00 – ‘Ask the experts’ (resolución de preguntas)
    14:00 a 14:15 – Sorteo de regalos

    Localización
    Sala La closeta
    La Massana, Andorra
    Dentro de la Casa Comunal (dónde se hace el salón del cómic)
    Assistència gratuita

    Ya os podéis registrar para el evento de Andorra mediante este enlace a la página de eventos de Microsoft:
    Registre: http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032389730&Culture=es-ES

    Guille Community Tour 2008 – Andorra
    Id. de evento: 1032389730

    Más información del tour en la Web del Guille o en MSDN events.

    Os esperamos el próximo 13 de Octubre en la Massana!
    El equipo de AndorraDotNet :-)

    Por cierto, el cartel ha sido obra del artista Sergio Jimenez, miembro de NavarraDotNet. Gracias Sergio, te has salido!

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
  • Folder Size: Primer contacto

    Harto de buscar dónde se iba el espacio de mi disco duro, y con la sensación de que estaba malgastando un porrón de bytes (y os aseguro que no es en peliXculas), me puse a diseñar una herramienta que me mostrase lo que ocupa cada una de las carpetas de mi ordenador. De esto hace un par de días, y la verdad es que me he liado la manta a la cabeza :-P y al final el resultado es este:

    FolderSize1

    Está enteramente escrito en C# 3.0 y aunque el funcionamiento es más sencillo que el mecanismo de un botijo (al fin y al cabo sólo recorre una estructura de carpetas y va procesando archivos), el resultado me gusta. Para compensar su sencillez le he añadido una interfaz cool (al menos para mí :-P), multithreading en la búsqueda, que a su vez hace uso de llamadas al FindFirstFile y FindNextFile para mejorar la performance... Aunque seguro que mi amigo el rano, belmonte de pro, me dice que si quiero ver performance me deje de tonterías y vuelva al C++ duro. Y os juro y perjuro que ya no me acuerdo de cómo se cocinaba con punteros. Además el resultado puede imprimirse o también exportar a Excel o PDF, y también muestra una lista de posibles errores producidos durante el análisis de la(s) carpeta(s), que mayormente son de acceso a ciertos elementos de sistema (o ubicaciones de red con permisos NTFS).

    Si a alguien le apetece probarlo os lo podéis instalar desde esta ubicación:

    http://utilities.ordeeno.com/foldersize/

    El único requisito es el Framework 3.5, y si no lo tenéis instalado el programa de instalación muy amablemente lo hará por vosotros (eso si, tarda un ratito).

    FolderSizeSetup

    La licencia es beerware, lo cual quiere decir que si te gusta y lo usas... deberás invitarme al menos a una cerveza. Y si es con papas, mejor que mejor!

    Bye @ home,

    PD - Lo he probado en XP y Vista Ultimate y de momento no le he encontrado ningún bug grave, pero si vosotros lo hacéis podéis contactar conmigo aquí.

  • Quieres ver las caras del VBTeam?

    Beth Massi publica un par de fotos en el blog del VBTeam, y nos cuenta la anécdota de porque todos visten de gris.

    Saludos,

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
  • VBTeam - How Do I Videos (WPF Forms over Data)

    movie

    Beth Massi del equipo de VB, ha publicado nuevos videos en el sitio “How Do I” Videos — Visual Basic. En este caso se trata de dos videos que muestran cómo crear formularios basados en datos en Windows Presentation Foundation usando Visual Studio 2008.

    How Do I: Create a Simple Data Entry Form in WPF?

    #1 | How Do I: Create a Simple Data Entry Form in WPF?
    (24 minutes, 32 seconds)

    #2 | How Do I: Display Data in a List in WPF?
    (11 minutes, 47 seconds)

    El link en: http://msdn.microsoft.com/en-us/vbasic/bb466226.aspx#wpfdata

    Si no conoceis el sitio “How Do I” Videos darle un vistazo, que merece la pena y mucho... :-)

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
  • HowTo: LDAP, obtener propiedades de la clase user

    Hace poco publicaba una actualización del método getUserLDAProperties de la clase LDAPservices. Esta función se encarga de recuperar todas las propiedades de la clase 'user' definidas  en el esquema del AD de la organización.

    LDAPUserProperties

    La verdad es que dicha corrección no me terminaba de satisfacer. Así que después de bucear un poco por el modelo de objetos del namespace System.DirectoryServices.ActiveDirectory he encontrado un método más elegante, y que además permite acceder a más propiedades opcionales (algo que la anterior versión no permitía).

    Os dejo aquí el código y en cuando tenga un minuto actualizo el código fuente de LDAPServices en skydrive.

    public static List<string> 
        getUserLDAPProperties(string LDAPURL)
    {
        List<string> properties =new List<string>();
        ActiveDirectorySchema objADSchema = ActiveDirectorySchema.GetCurrentSchema();
        ActiveDirectorySchemaClass objADUserSchema;
        ActiveDirectorySchemaPropertyCollection objADPropertiesCollection;
        objADUserSchema = objADSchema.FindClass("user");
        objADPropertiesCollection = objADUserSchema.MandatoryProperties;
        foreach (ActiveDirectorySchemaProperty objADSchemaProperty in objADPropertiesCollection)
        {
            properties.Add(objADSchemaProperty.Name);
        }
        objADPropertiesCollection = objADUserSchema.OptionalProperties;
        foreach (ActiveDirectorySchemaProperty objADSchemaProperty in objADPropertiesCollection)
        {
            properties.Add(objADSchemaProperty.Name);
        }
        return (from p in properties orderby p select p).ToList();
    }

    Nos vemos!

    ** crossposting desde el blog de Lluís Franco en geeks.ms **
  • ¿Goodbye Dictionary?

    Corrección al artículo (16/07/2008):

    Todas las mediciones de tiempo efectuadas en las compartivas entre listas y diccionarios han sido mal efectuadas y no son válidas. Porqué? Porque a un servidor se le olvidó 'resetear' el cronómetro del StopWatch entre una medición y otra (ay, ay, ay...), de modo que los tiempos tomados para el objeto dictionary incluyen también los de la lista, y por eso son mucho mayores de lo esperado.

    Un 'pequeño' olvido pero que afecta totalmente al sentido del post, ya que la conclusión del post era que acceder a un elemento de un diccionario NO era más rápido que acceder a un elemento de una lista, cuando la realidad es que SI lo es... y mucho. Siento haber publicado lo contrario y aquí me retracto.

    De este error puedo sacar varias conclusiones:

    • Revisar: Acostumbrarme a revisar más en profundidad lo que publico. He usado infinidad de veces el objeto StopWatch y no es nuevo para mi, así que todavía me duele más haberme olvidado de reiniciar el crono... Muchas gracias por el comentario Steven.
    • No hacer tantas cosas al mismo tiempo: La verdad es que cuando escribí el post estaba haciendo varias cosas al mismo tiempo, entre las cuales me encontraba realizando unas pruebas para una aplicación, y al medir los tiempos me quedé muy sorprendido y empecé a escribir el post sin detectar el error en mi código.
    • Todos nos equivocamos: Eso es evidente, y cualquiera puede cometer un error como este. Lo malo es que en lugar de escribir el post rápidamente y publicarlo, debería haberlo dejado para revisarlo hoy... pero lo hecho hecho está.
    • Hay que aprender de los errores: Prefiero hacer algo y equivocarme a no hacer nada y no equivocarme. Con todo, espero aprender algo de todo esto, porque todos seguimos aprendiendo día a día (y malo del día que no lo hagamos).

    Pero vamos con la corrección. Los nuevos tiempos si agregamos un watch.Reset(); antes de empezar a tomar los tiempos del diccionario son los siguientes:

    Compare load 100000 items in List vs. Dict. (ms.)
    List: 678,4068
    Dict: 759,5071

    Compare get one item by key in List vs. Dict. (ms.)
    List: 0,3645
    Dict: 0,0058

    Compare verify one item by key in List vs. Dict. (ms.)
    List: 0,2748
    Dict: 0,0058

    La conclusión es que cargar datos en un diccionario es sólamente un poco más lento que cargarlos en una lista. mientras que es mucho más rápido acceder a los elementos que contiene (del orden 50 veces más rápido aproximadamente). Evidentemente esto justifica sobradamente el uso de diccionarios.

    Bueno... Tal vez el título del artículo ahora debería quedar como "¿Goodbye Dictionary? ¡Hola melón!" :-P

    Saludos desde Andorra,

    Fin de la corrección al artículo

    El artículo original (15/07/2008):

    Generics

    La aparición del framework 2.0 nos trajo una grata sorpresa: La aparición de Generics, que nos proveía por fin de un conjunto de colecciones fuertemente tipadas, que mejoraban mucho el rendimiento al evitar el uso de boxing y unboxing, y permitían un código mucho más legible, elegante, así como detectar y prevenir muchos errores en tiempo de compilación.

    GenericsError1

    Desde ,entonces, de todos los distintos tipos de colecciones genéricas, en el 90% de los casos he usado estos dos: List y Dictionary. El primero de ellos es obviamente una lista de objetos <T>, algo de uso cotidiano, y el segundo es el equivalente genérico del viejo diccionario, que permite guardar una colección de elementos y una clave para acceder a ellos <TKey>, <TValue>:

    Dictionary<int, CPItem> dict = new Dictionary<int, CPItem>();

    Este tipo diccionario es ideal para almacenar una serie de objetos (por ejemplo clientes que provienen de una BD) y poder acceder a uno de ellos a través de su campo clave o identificador, sea éste del tipo que sea (por ejemplo en el caso anterior la clave es de tipo int):

    CPItem item2 = dict[24];

    De este modo, es muy sencillo acceder a un elemento de la colección a través del valor de su identificador (no confundir con su posición dentro de la lista). Sin embargo y a pesar de su innegable potencia, hay un par de cosas que no me gustan de los diccionarios:

    • Siempre es más lento cargar los objetos en un diccionario que en una lista (del orden de 2 a 1 aproximadamente)
    • Un diccionario no es serializable 'per se' (al menos sin hacer trucos), y esto SI puede ser un problema.

    Sin embargo, tiene la gran ventaja frente a la lista de que permite acceder de forma casi instantánea a un elemento de la misma, y además contiene métodos que permiten verificar si la colección contiene un elemento, ya sea por clave o por valor.

    List vs. Dictionary

    Veamos un ejemplo rápido, declaramos una clase con algunos miembros de diversos tipos de datos (para tener de todo un poco) y usamos esta clase para cargar varios objetos en una lista y un diccionario respectivamente:

    class CPItem
    {
        const int max = 1000000;
     
        public int propInt { get; set; }
        public string propString { get; set; }
        public DateTime propDateTime { get; set; }
        public bool propBool { get; set; }
        public double propDouble { get; set; }
     
        public CPItem(int propint)
        {
            Random r = new Random(max);
            propInt = propint;
            propString = string.Format("Item {0}", propint.ToString("000000"));
            propDateTime.AddDays(propint);
            propBool = propint <= 0.5 ? false : true;
            propDouble = r.NextDouble() * max;
        }
    }

    Declaramos los dos objetos genéricos:

    List<CPItem> list = new List<CPItem>();
    Dictionary<int, CPItem> dict = new Dictionary<int, CPItem>();

    Y a continuación usamos un StopWatch para medir los tiempos de carga de 100.000 elementos... y podremos observar una gran diferencia:

    private void LoadListDict()
    {
        const int max = 100000;
        Stopwatch watch = new Stopwatch();
     
        list.Clear();
        watch.Start();
        for (int i = 1; i <= max; i++)
        {
            list.Add(new CPItem(i));
        }
        watch.Stop();
        TimeSpan ts1 = watch.Elapsed;
     
        dict.Clear();
        watch.Start();
        for (int i = 1; i <= max; i++)
        {
            dict.Add(i, new CPItem(i));
        }
        watch.Stop();
        TimeSpan ts2 = watch.Elapsed;
     
        this.ResultsTextBox.Text = string.Format(
            "Compare load {0} items in List vs. Dict. (ms.)\r\nList: {1}\r\nDict: {2}",
            max.ToString(),
            ts1.TotalMilliseconds.ToString(),
            ts2.TotalMilliseconds.ToString());
    }

    En mi estación estos son los tiempos promedio de carga después de ejecutar 5 veces:

    Compare load 100000 items in List vs. Dict. (ms.)
    List: 737,1392
    Dict: 1479,4486

    Bien, está claro que si hay que elegir entre ambos hay que tener un buen motivo para escoger el diccionario... ¡ya que la lista es el doble de rápida!

    LINQ to objects

    Con la aparición de VS2008 y del framework 3.5, aparecen las expresiones de consulta. Éstas nos permiten manipular colecciones de objetos en memoria, para filtrarlos, ordenarlos y agruparlos según nuestras necesidades.

    Así que es posible que nos preguntemos ¿es necesario el uso de diccionarios, si ahora disponemos de LINQ para manejar listas? Es decir, si puedo cargar los datos en una lista genérica y acceder mediante LINQ to objects a un elemento, o a un subconjunto de éstos... ¿qué sentido tiene usar un dictionary?

    Uhm... Pues supongo que el rendimiento podría ser un factor, ya que según la documentación de este objeto: Retrieving a value by using its key is very fast, close to O(1), because the Dictionary<(Of <(TKey, TValue>)>) class is implemented as a hash table. O dicho de otro modo: Recuperar un valor utilizando su clave es muy rápido, porque la clase Dictionary se implementa como una tabla hash.

    Ya sabía yo que había un buen motivo para usar un diccionario: Debe ser más mucho más rápido al acceder a un objeto a través de su clave que extraerlo de una lista mediante LINQ... seguro! .... ¿o tal vez no?

    Hagamos un par de pruebas:

    A) Cuanto tardamos en recuperar a un elemento a través de su clave:

    private void GetOneItemByKey(int keyvalue)
    {
        if (list.Count == 0 || dict.Count == 0) LoadListDict();
        Stopwatch watch = new Stopwatch();
        watch.Start();
        CPItem item1 = (from l in list where l.propInt == keyvalue select l).Single();
        watch.Stop();
        TimeSpan ts1 = watch.Elapsed;
     
        watch.Start();
        CPItem item2 = dict[keyvalue];
        watch.Stop();           
        TimeSpan ts2 = watch.Elapsed;
     
        this.ResultsTextBox.Text = string.Format(
            "Compare get one item by key in List vs. Dict. (ms.)\r\nList: {0}\r\nDict: {1}",
            ts1.TotalMilliseconds.ToString(),
            ts2.TotalMilliseconds.ToString());
    }

    En mi estación estos son los tiempos promedio de carga después de ejecutar 5 veces:

    Compare get one item by key in List vs. Dict. (ms.)
    List: 3,8518
    Dict: 3,8566

    Pues parece que ambos tiempos son iguales. Es más, acceder a la colección a través de LINQ ¡es incluso un poquito más rápido! Uhm, vaya... bueno, veamos el segundo ejemplo antes de sacar conclusiones:

    B) Cuanto tardamos en verificar si existe un elemento a través de su clave:

    private void VerifyOneItemByKey(int keyvalue)
    {
        if (list.Count == 0 || dict.Count == 0) LoadListDict();
        Stopwatch watch = new Stopwatch();
        watch.Start();
        var items = from l in list where l.propInt == keyvalue select l;
        bool v1 = (items.Count() == 0);
        watch.Stop();
        TimeSpan ts1 = watch.Elapsed;
     
        watch.Start();
        bool v2 = dict.ContainsKey(keyvalue);
        watch.Stop();