martes, 23 de abril de 2013

Cargar y Guardar imagenes en MySql

Primero que todo, hago este post como respuesta a la pregunta del Ask :)
Si bien no comparto la idea de guardar imagenes en MySql, parece ser un problema algo frecuente, asi que hagamoslo!

Lo primero y mas obvio que haremos, es crear una nueva base de datos en MySql.
La mia se llama "test"
Creamos una tabla, en mi caso la llamare "imagenes"
 y tiene 2 columnas, "Nombre" para obtener la imagen asociada a su nombre, e "Image" que mantendra la imagen
"Nombre" lo guardo como "TinyText"
"Image" lo guardo como "MediumBlob"

como en la imagen


Ahora dividiremos el Codigo en partes para hacerlo mas entendible


const string MySqlConnecionString = "Server=localhost; Database=test; Username=root; Password=XXXX;";


Ahora creamos un metodo, el cual nos regresara una conexion a MySql ya abierta.


        static MySqlConnection GetNewConnection()
        {
            var conn = new MySqlConnection(MySqlConnecionString);
            conn.Open();
            return conn;
        }


Teniendo ya todo listo en cuanto a conexion MySql, vamos con lo importante
El metodo que use para guardar y cargar las images es a travez de arrays de bytes (byte[]), ya que pueden ser manipulados facilmente por las clases que heredan "Stream" y ademas porque las clases de Imagenes soportan el cambio de stream a image y vice-versa.
No comentare el codigo porque no es nada del otro mundo, gracias a que C# tambien es muy intuitivo

Guardar una imagen:

        static void GuardarImagen(Image imagen, string Nombre)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                imagen.Save(ms, ImageFormat.Gif);
                byte[] imgArr = ms.ToArray();
                using (MySqlConnection conn = GetNewConnection())
                {
                    using (MySqlCommand cmd = new MySqlCommand())
                    {
                        cmd.Connection = conn;
                        cmd.CommandText = "INSERT INTO imagenes(Nombre, Image) VALUES (@Nombre, @imgArr)";
                        cmd.Parameters.AddWithValue("@Nombre", Nombre);
                        cmd.Parameters.AddWithValue("@imgArr", imgArr);
                        cmd.ExecuteNonQuery();
                    }
                }
            }
        }


lo unico que hicimos fue crear una conexion a MySql, crear un MemoryStream, usar Image.Save(Stream, Formato), convertir el stream a byte[] y guardarlo en MySql.
El formato lo pueden cambiar de gif al que quieran, yo simplemente lo use porque
hasta donde se, ocupan menor espacio, pero no lo he comprobado en este tipo de 
casos.

Ahora vamos con el como cargar una Imagen:

        static Image CargarImagen(string Nombre)
        {
            using (MySqlConnection conn = GetNewConnection())
            {
                using (MySqlCommand cmd = new MySqlCommand())
                {
                    cmd.Connection = conn;
                    cmd.CommandText = "SELECT Image FROM imagenes WHERE Nombre = @nombre";
                    cmd.Parameters.AddWithValue("@nombre", Nombre);
                    byte[] imgArr = (byte[])cmd.ExecuteScalar();
                    imgArr = (byte[])cmd.ExecuteScalar();
                    using (var stream = new MemoryStream(imgArr))
                    {
                        Image img = Image.FromStream(stream);
                        return img;
                    }
                }
            }
        }

Aqui lo que hicimo, fue crear una conexion, hacer EXACTAMENTE EL MISMO COMANDO
QUE PARA CUALQUIER SITUACION, solo que usamos ExecuteScalar() que nos devuelve
el objeto en ese lugar en vez de un MySqlDataReader, y convertirlo a byte[] 
explicitamente, luego creamos un stream envolviendo el byte[], y usamos 
Image.FromStream(stream);


El codigo que nos queda es bastante portable.
ejemplo si quieres cargar una imagen de MySql a un pictureBox, usamos

nombrePictureBox.Image = CargarImagen("prueba");



Como dije al comienzo, no me gusta esta manera, MySql tiene una mejor escalabilidad,
pero es un poco mas lento que un archivo, por lo que en mi opinion personal, digo
que seria conveniente guardar la imagen en un archivo comun y corriente, y en la 
base de datos, en vez de guardar el archivo en si, guardar la ubicacion de la imagen.

Suerte con sus proyectos! :)



lunes, 22 de abril de 2013

class vs struct

Una de las dudas mas comunes, y que de hecho me costo bastante entender, es cuando usar struct o class, todos casi como si fuera una ley usamos unicamente class... pero, cuando son utiles los structs?
Primero que todo, debemos marcar 2 diferencia cruciales
1.-Herencia: Un struct no puede ser heredado por otro struct class, aunque si puede heredar interfaces, class como sabran, si lo permite.
2.-Bien aqui es cuando hago notar que no soy alguien que lea todo el tiempo libros, si no que aprendo de la practica y algunos articulos. las class, son en si referencias a un punto en la memoria, los structs si bien lo son, actuan de una manera diferente frente a algunas situaciones, la mas importante es el ser parametro de algun metodo, mientras class lo que hace es pasar una referencia a su ubicacion en la memoria, un struct es copiado completamente
quiere decir que si tenemos lo siguiente

class MiClase
{
    public int X;
}
struct MiStruct
{
   public int X
}

supongamos creamos una instancia de la clase llamada "classInst" y del struct "structInst", ambos con valor de "X" = 1000

teniendo los siguientes metodos

void TestClass(MiClase clase)
{
    clase.X = 2000;
}
void TestStruct(MiStruct estructura)
{
     estructura.X = 2000;
}

que pasa con classInst luego de
TestClass(classInst);  ?

y con el struct?

al imprimir en la consola tenemos el siguiente resultado
classInst.X = 2000;
structInst.X = 1000;

como dijimos arriba, se debe a que al pasar un struct como parametro, se crea una copia del struct, la clase por su lado es la misma, solo pasa una referencia.

En conclusion:

Struct se debe usar practicamente nunca! ^^ pero es buena practica usarlo en combinacion de los casos que:

-La tamaño de la informacion contenida bordea los 20 bytes.
-El paso del struct como parametros es casi nulo
-Las variables dentro son de preferencia readonly, o cambia pocas veces.

Dudas sobre esto.. Ask ;) link a la derecha

Dictionary con dos keys

Hace un tiempo, mientras desarrollaba mi antiguo servidor privado para un juego, llego un momento en que se convirtio en una idea bastante util pensar en una manera de tener un valor a asociado a 2 llaves distintas.
el problema fue el siguiente.

Por motivos de como estaba estructurados los paquetes de datos, cada persona conectada, tenia una ID, y obviamente, un personaje asociado, pero... que pasaba cuando necesitaba a alguien con determinado nombre? necesitaba comparar los nombres en un ciclo.

Esta clase la llame "selector", son 3 dictionary thread-safe dispuestos de la siguiente manera
<llave1, valor>
<llave1, llave2>
<llave2, llave1>

dos consultas en un caso suena mejor que sobre 50 comparaciones de strings, o no? :)

Los metodos de obtencion y actualizacion que implemente son los "seguros" por asi decirlo
TryGet....(...., out ....); 

y la obtencion de un ICollection para poder aplicar ciclos al selector :)


    public class Selector<TKey1, TKey2, TValue>
    {
        ConcurrentDictionary<TKey1, TValue> Key1ToValue;
        ConcurrentDictionary<TKey2, TKey1> Key2ToKey1;
        ConcurrentDictionary<TKey1, TKey2> Key1ToKey2;

        public Selector()
        {
            Key1ToValue = new ConcurrentDictionary<TKey1, TValue>();
            Key2ToKey1 = new ConcurrentDictionary<TKey2, TKey1>();
            Key1ToKey2 = new ConcurrentDictionary<TKey1, TKey2>();
        }

        public bool TryGetValue(TKey1 key, out TValue value)
        {
            return Key1ToValue.TryGetValue(key, out value);
        }

        public bool TryGetValue(TKey2 key2, out TValue value)
        {
            TKey1 key1;
            if (Key2ToKey1.TryGetValue(key2, out key1))
                return Key1ToValue.TryGetValue(key1, out value);
            value = default(TValue);
            return false;
        }

        public bool TryGetKey1(TKey2 key2, out TKey1 value)
        {
            return Key2ToKey1.TryGetValue(key2, out value);
        }

        public bool TryGetKey2(TKey1 key1, out TKey2 value)
        {
            return Key1ToKey2.TryGetValue(key1, out value);
        }

        public bool TryAdd(TKey1 key1, TKey2 key2, TValue value)
        {
            return (Key1ToKey2.TryAdd(key1, key2) &&
                    Key1ToValue.TryAdd(key1, value) &&
                    Key2ToKey1.TryAdd(key2, key1));
        }

        public bool TryRemove(TKey1 key1)
        {
            TValue deletedval;
            TKey1 deleted1;
            TKey2 key2;

            if (Key1ToKey2.TryRemove(key1, out key2))
                return (Key2ToKey1.TryRemove(key2, out deleted1) &&
                       Key1ToValue.TryRemove(key1, out deletedval));
            return false;



        }

        public bool ContainsKey1(TKey1 value)
        {
            return Key1ToValue.ContainsKey(value);
        }

        public bool ContainsKey2(TKey2 value)
        {
            return Key2ToKey1.ContainsKey(value);
        }

        public bool ContainsValue(TValue value)
        {
            return Key1ToValue.Values.Contains(value);
        }

        public ICollection<TKey1> Keys1
        {
            get { return Key1ToKey2.Keys; }
        }

        public ICollection<TKey2> Keys2
        {
            get { return Key2ToKey1.Keys; }
        }

        public ICollection<TValue> Values
        {
            get { return Key1ToValue.Values; }
        }
    }

Como se imaginaran, por ser thread-safe y ser 3 dictionaies, la obtencion de un valor por medio de la llave 1   se ve un poco mas lento, aun asi, satisface las necesidades de cualquier situacion. en casos de necesitarse mas velocidad que thread-safe obviamente es recomendable cambiarlos a Dictionary, concurrentDictionary puede llegar a ser 5 veces mas lento en la obtencion de datos

Tutorial(basico y en desarrollo)


Antes que todo,  El tutorial es de mi autoria, problemas con fuentes y tamaños son debidos a que los tenia en un Word con otro formato.
Tambien quisiera que me disculparan, la calidad de varios de los tutoriales no es la mejor,
lo estuve leyendo y esta mal explicado, asi como falta informacion, sigue siendo una base
para un tutorial, pero hay que completarlo y corregir algunas cosas, esto se debe a que es
MUY VIEJO, lo escribi hace un año aproximadamente :/, las secciones que quedan dentro
de esos tutoriales que reescribire son hasta "Metodos", luego de eso seran completamente
nuevos, espero que mejor explicados, y mucho mas completos :)... luego comenzare a
reescribir las secciones ya nombradas :P

Secciones:
-Integers
-Strings
-Booleans
-Conversiones
-If-else if- else
-Ciclos
-Metodos

Integers


Las variables de tipo integer son numéricas finitas y se dividen en 2 tipos: integer y unsigned integer
Los integers están en el conjunto Z(están y no son porque no son infinitos como lo es el conjunto), el 0 es el punto medio en la recta de un integer, o sea, la cantidad de números negativos del integer será igual a la cantidad de números positivos mas el cero, los nombres de los integers son los siguientes
sbyte, short, int y long.                                                 

Los unsigned integers, como su nombre lo dice, son integers sin signo(solo números positivos contando el 0) y el nombre que llevan es el mismo que el de un integer, pero comenzando con la vocal “u” a excepción del byte, su valor máximo es igual al máximo numero permitido por su int mas el valor absoluto del mínimo valor de su int(ejemplo: integer sbyte = -128 a 127, un byte = |-128| + 127 + 1(para contar el 0) = 256, o sea un byte abarca los números desde el 0 al 255, el nombre de los Unsigned integers son los siguientes.
byte, ushort, uint y ulong.
Todos los integers pueden ser creados sin valor pero antes de usarla se debe asignarle un valor, de lo contrario tendrás un error como este y no podremos compilar.
Puedes saber el valor máximo, mínimo y sus propiedades (de cada integer) de la siguiente manera:
Click derecho en el integer.
Y ahora haz click en ir a definición, como lo muestra la imagen





OPERANDO CON INTEGERS

Usaremos en los siguientes casos la variable
byte numero = 9; // o cualquier numero que desees

Suma = +
Ejemplo
1)numero = numero + 3; //hacemos que la variable byte llamada numero se le sume 3
2)numero += 3; //hacemos que la variable byte llamada numero se le sume 3
3)numero++ //a la variable numerica llamada numero, le sumamos una unidad (1),esta funciona igual que las anteriores, solo //que siempre sumara una unidad, muy usado en el ciclo for que veremos luego

Resta = -
Ejemplo
1)numero = numero - 3; //hacemos que la variable byte llamada numero se le reste 3
2)numero -= 3; //hacemos que la variable byte llamada numero se le reste 3
3)numero-- //a la variable numerica llamada numero, le restamos una unidad (1), esta funciona igual que las anteriores, //solo que siempre restara una unidad
Multiplicación = *
Ejemplo
numero = numero * 3; //hacemos que la variable byte llamada numero se multiplique por 3
numero *= 3; //hacemos que la variable byte llamada numero se multiplique por 3

División = /
Ejemplo
numero = numero / 3; //hacemos que la variable byte llamada numero se divida por 3
numero /= 3; //hacemos que la variable byte llamada numero se divida por 3

Valor absoluto = Math.Abs (valor)
Devolverá un valor SHORT que será el valor absoluto de cierto numero, por lo tanto si quieres que el valor absoluto sea otro tipo de variable, tendrás que hacer una conversión (valor absoluto es la distancia de un numero al 0 y se escribe gráficamente |valor|, ejemplo |-8| = 8 porque de -8 a 0 hay 8 números)
Esto sirve para ahorrarte códigos con checks de cual numero es mayor, ejemplo, hace un tiempo hice algo como esto tratando de fixear el jump en mi source 5165(lo cual ahora da vergüenza :$)
           
            int X1;
            int X2;
            int Y1;
            int Y2;
            byte distancia1;
            byte distancia2;

            if (X1 >= X2)
                {
                distancia1 = (byte)(X1 - X2);
                }
            if (X1 < X2)
                {
                distancia1 = (byte)(X2 - X1);
                }
            if (Y1 >= Y2)
                {
                distancia2 = (byte)(Y1 - Y2);
                }
            if (Y1 < Y2)
                {
                distancia1 = (byte)(Y2 - Y1);
                }

Después aprendí a usar un poco mas la clase Math, y esas 16 líneas se resumen en esto

  distancia1 = (byte)Math.Abs(X1 - X2);
                         distancia2 = (byte)Math.Abs(Y1 - Y2);


Raíz Cuadrada = Math.Sqrt (este es mejor dicho un operador de doublés, pero estará aquí por organización y porque también hay casos posibles)

Esta devuelve la Raíz cuadrada de un valor DOUBLE, por lo cual si quieres tener la raíz cuadrada de un valor que no sea Double, deberás usar una conversión.
¿Alguna idea de porque tiene que ser double? Si no, te daré una pista

 byte Raiz;
            Raiz = (byte)Math.Sqrt(3);

Es imposible tener en un byte la Raíz cuadrada ya que un byte no acepta decimales, y la raíz cuadrada de 7 es un decimal
Por lo tanto cuando se use Math.Sqrt lo mejor es usar double o en algunos casos se puede usar floats(que también admiten decimales) pero simplemente usemos double

              double Raiz;
              Raiz = Math.Sqrt(7);


Elevar = Math.Pow(x, y)

Esta clase nos permie elevar numeros muy facilmente, si quieres elevar 5 a 3 (5^ 3) solo escribes

int potencia = Math.Pow(5, 3);

siendo el primer numero la base, y el segundo el exponente


Modulo= %

Devuelve un valor que es igual al resto o residuo que se obtiene de dividir un numero por otro sin alargar la división, con esto me refiero, que si divides 5/2 el resultado no será 2.5 , sino que será 2 y el resto o residuo será 1
            int i = 12 % 7;
            Console.WriteLine(i.ToString());
En este sencillo caso, la consola escribirá 5, debido a que 12 / 7 usando solo números enteros, dara como resultado 1 y resto 5.



STRINGS
Existen dos tipos de strings, char y string, esta ultima, aunque parezca, no es una variable primitiva, ya que deriva de char, por eso, un string o cadena, es una cadena de chars.

Char: se escribe entre una comilla (‘char’) y solo puede almacenar un carácter. Posee 2 metodos, ToString() y CompareTo().  ToString() lo veremos en CONVERSIONES.
              //ejemplo de un char
            char caracter = 'C';
String: se escribe entre comillas (“string”), almacena cualquier cantidad de chars
            //ejemplo de un string
            string cadena = "ejemplo de string";

Ahora aprenderemos solo algunos métodos y la concatenación de esta variable que son los mas usados y necesarios a la hora de usar C# para programar que son: Concatenación (por medio de signo mas(+) y una comparación que hice en C# con stringbuilder), ToLower(), ToUpper() , Split() y SubString()
ToLower: Este método sirve para transformar todos los caracteres de un string a minúscula, veámoslo en un ejemplo
            //en este caso, cadena1 es el string a convertir
            string cadena1 = "EjEmPLO de StRing";
            //en este caso, cadena2 es el string despues de convertido
            string cadena2 = cadena1.ToLower();
El resultado tras lo conversión, o sea cadena2, será
"ejemplo de string";

ToUpper: Este método sirve para transformar todos los caracteres de un string a mayúscula, veámoslo en un ejemplo

            //en este caso, cadena1 es el string a convertir
            string cadena1 = "EjEmPLO de StRing";
            //en este caso, cadena2 es el string despues de convertido
            string cadena2 = cadena1.ToUpper();
El resultado tras lo conversión, o sea cadena2, será
"EJEMPLO DE STRING";

Split: Sirve para separar un string cada vez que aparezca un char definido por quien lo use, genera un array de strings, cada string dentro del del array será una sección del string principal después del Split (separación en ingles). Por ejemplo:

            //Determinamos una cadena principal
            string CadenaPrincipal = "Ejemplo de split para el tutorial";
            //Llamamos el split, puede tomar cualquier nombre, en este caso cmd, y luego elegimos el char por el cual sera //separada la cadena, en este caso sera un espacio.
            string [] cmd = CadenaPrincipal.Split(' ');
            //ejemplo usando el split, escribimos en la consola la primera palabra y la tercera
            Console.WriteLine(cmd[0] + cmd[2]);

En este caso, la consola escribirá "Ejemplosplit"
En este split se puede concluir esto
    [0]        [1]    [2]      [3]    [4]     [5]
Ejemplo    de    Split    para    el    tutorial



SubString: Este método sirve para separar una cadena pero no por un char como el método anterior, sino que por una cantidad de chars definida por el coder, se usa de la siguiente manera

string cadena1 = "ejemplo de substring";
string cadena2 = cadena1.Substring(1, 4);

En este caso, 1 es donde comienza el SubString, es mas fácil comprenderlo pensando en que el primer número es la cantidad de chars que se dejan de lado en el COMIENZO  del string principal, luego, tenemos el numero 4, este significa la cantidad de chars que tomara el substring.

                    string cadena1 = "ejemplo de substring";
  //se tiene un string principal ahora creamos el substring, dejaremos de lado el primer char del string
  //y luego tomaremos los 4 chars siguientes
            string cadena2 = cadena1.Substring(1, 4);
            Console.WriteLine(cadena2);


En este caso, la consola escribirá “jemp” porque:
Eliminando el primer char del string nos queda "jemplo de substring"
Tomando los 4 chars siguientes j-e-m-p forman el string "jemp"

También puedes crear un Substring tomando todos los chars después de dejar de lado la cantidad deseada
                    string cadena1 = "ejemplo de substring";
  //se tiene un string principal ahora creamos el substring, dejaremos de lado el primer char del string
  //y luego se tomaran todos los chars sin contar los dejados
            string cadena2 = cadena1.Substring(3);

En este caso, la consola escribirá “mplo de substring”.

Concatenación: La concatenación se usa para unir strings, la siguiente no es la única manera, pero en este caso les explicare como unir cadenas por medio del operador +.
            //tenemos dos strings
            string cadena1 = "cadena1";
            string cadena2 = "cadena2";
            //los unimos por medio del operador + con otro string mas
            Console.WriteLine(cadena1 + " unido a " + cadena2);
Como se podrán imaginar, la consola escribirá “cadena1 unido a cadena2”.

Investigación  Operador + v/s StringBuilder:

Bueno, hace un tiempo, divagando por internet, leí que el stringbuilder era lejos la mejor herramienta para unir strings, y al comprobarlo por medio de una simple aplicación, supe que era por MUY LEJOS mejor que usar string x + string y, etc.…
Les anexare una tabla que elabore con el resultado entre tiempo y cantidad de strings unidas por medio del operador + y usando StringBuilder.
Llenare la tabla con color rojo indicando un empate, verde el ganador y negro el perdedor
En caso de ser 0.0, el DateTime quizás no capto por la velocidad en que sucedió todo.

500 strings
2000 strings
5000 strings
7000 strings
50000 strings
StringBuilder
0.0
0.0
0.0
0.0
0.0156250
Operador +
0.0
0.0312500
0.2187500
0.4375000
32.6406250

          Finalmente trate de ralentizar el stringbuilder, lo hice juntar 1 millón de strings, el tiempo demorado 0.0781250
El string usado durante las pruebas fue simplemente "String ";
Se puede notar que el stringbuilder es mucho mas rápido juntando cualquier tipo de datos, así es, el stringbuilder no solo une strings, capta cualquier tipo de datos, y al final, puedes realizar la conversión .ToString() si lo deseas
Para usar el StringBuilder se hace de la siguiente manera


  int uno = 130;
            string dos = "para sb";
            byte etc = 230;
            StringBuilder sb = new StringBuilder();
            sb.Append(uno);
            sb.AppendLine(dos);
            sb.Append(etc);
            sb.AppendLine();
            sb.Append(uno);                                                                     
            Console.WriteLine(sb.ToString());

Por si no lo han notado, AppendLine solo acepta strings, si se quiere anexar una línea con otra variable hay dos opciones, usar AppendLine(); y luego Append(variable cualquiera) ya que esta ultima acepta cualquier tipo de variable o usando una conversión ToString().


BOOLEANS
Los booleans (abreviado bool y como se usa en C#) pueden tener dos valores distintos que son true y false.
Un ejemplo de un bool seria
bool Boolean = false;
aunque un bool abarca mucho mas, y es una de las variables mas usadas aunque muchos no lo sepan porque no se define explicitamente, por ejemplo, los if-else if- else.

CONVERSIONES
Para transformar valores numéricos de una variable a otra(ejemplo de byte a int) es simple usar esta conversión genérica: se escribe la variable A LA QUE se desea convertir la variable entre paréntesis, seguida de la variable a convertir por ejemplo (Variable Salida)valor:
 //tenemos un byte 120 y queremos convertirlo a ushort
            byte ejemplo = 120;
            ushort ejemplo2 = (ushort)ejemplo;
Aunque hay que tener cuidado porque en ciertos casos podrías tener una perdida de datos, ejemplo:
//tenemos un double 15,3231 y queremos convertirlo a byte
            double ejemplo = 15.3231;
            byte ejemplo2 = (byte)ejemplo;
¿El resultado cual crees que será? Exacto, será 15 porque la variable byte no acepta decimales, por lo que se borrara todo lo que esta después del punto(.).

Para transformar un algún valor a String se usa el método ToString()
Ejemplo:
//tenemos un byte 130 y queremos convertirlo a string
            byte ejemplo = 130;
            string ejemplo2 = ejemplo.ToString();
//queremos tener algun valor de un DateTime en un string, por ejemplo la hora(solo hora)
            string ejemplo2 = DateTime.Now.Hour.ToString();

En caso de querer revertir esto, se puede usar el método variable.Parse(string);
Ejemplo:
//Tenemos un string “12345” y queremos que sea ushort
            string ejemplo = "12345";
            ushort ejemplo2 = ushort.Parse(ejemplo);
Un ejemplo usando los casos anteriores
//hacemos que la consola nos pida un numero
            Console.WriteLine("escribe un numero: ");
//como fue escrito en la consola, el numero sera una cadena
//asi que la convertiremos a la variable int
            int numero = int.Parse(Console.ReadLine());
//convertimos el numero de la variable int a byte
            byte numero2 = (byte)numero;
//convertimos la variable byte llamada numero2 a string y la escribimos en la consola
            Console.WriteLine(numero2.ToString());

IF -ELSE IF - ELSE
Desde ahora lo llamaremos simplemente “if” Este tipo de bool, sirve para hacer una condición dentro de tu código, veamos los operadores que usaremos para luego explicarlo un poco mas detalladamente.
Los operadores que se usan en los bool, específicamente if-else if- else son:

== (si ambos valores, uno a cada lado del operador son iguales, se ejecutara el codigo)

            int X = 130;
            int Y = 270;
            if(X == Y)
                {
                //Codigo
                }

X != Y (indica no, si x NO ES IGUAL A  y, se ejecutara el código)
            int X = 130;
            int Y = 270;
            if(X != Y)
                {
                //Codigo
                }

X >= Y(si X es mayor o igual a Y, se ejecutara el código)
            int X = 130;
            int Y = 270;
            if(X >= Y)
                {
                //Codigo
                }

X <= Y(si X es menor o igual a Y, se ejecutara el código)
            int X = 130;
            int Y = 270;
            if(X <= Y)
                {
                //Codigo
                }

X > Y(si X es mayor que Y, s ejecuta el código)
              int X = 130;
            int Y = 270;
            if(X > Y)
                {
                //Codigo
                }

X < Y(si X es menor que Y, se ejecuta el código)
            int X = 130;
            int Y = 270;
            if(X < Y)
                {
                //Codigo
                }

&& (se usa como si uno hablara con “Y” ,sirve para anexar otra condición al if, y si todas las condiciones anexadas con && se cumplen, se ejecutara el código) ejemplo
  bool ejemplo1 = true;
            bool ejemplo2 = true;
            //si es que ejemplo1 Y ejemplo2 son true, se ejecutara el codigo
            if(ejemplo1 == true && ejemplo2 == true)
                {
                //Codigo
                }

|| (Se usa como si se hablara con “O”, sirve para anexar otra condición al if, y si una se cumple se puede ejecutar el código) ejemplo
  bool ejemplo1 = true;
            bool ejemplo2 = true;
            //si es que ejemplo1 O ejemplo2 son true, se ejecutara el codigo
            if(ejemplo1 == true || ejemplo2 == true)
                {
                //Codigo
                }

condición ? valor1 : valor2 (Este es un if acortado se podria decir, si la condición se cumple devuelve valor1, si no, devuelve valor2, veamoslo con un ejemplo en conquer, muchos usan la source 5375++, vayan a  al npc “eternity” y verán algo como esto(removí client.Entity obviamente), se revisa primero el paréntesis, revisemos un ejemplo para aclararlo

            int Level = 111;
            int Job = 135;
  //si Job es igual a 135, devolvera 110, si Job != a 135, devolvera 120 (135 es el job del watertaoist que   //renace al level 110) luego se revisa el if completo, si Level es mayor al valor devuelto, ejecuta el codigo
            if (Level < (Job == 135 ? 110 : 120))
                {
                //codigo
                }

El uso de del operador anterior es equivalente a esto:


            int Level = 111;
            int Job = 135;
  int LevelNecesario = 0;
            if (Job == 135)
                LevelNecesario = 110;
            else if (Job != 135)
                LevelNecesario = 120;

            if (Level > LevelNecesario)
            {
               //codigo
            }

El que solo haya usado integers y bools no quiere decir que sean las únicas variables que se pueden pasar por un if, pueden ser clases, strings, etc.…

Estructura
Un if tiene la siguiente estructura.

            if(condicion1)//OBLIGATORIO
                {
                //Codigo
                }
            else if(condicion2)//OPCIONAL
                {
                //Codigo
                }
            else//OPCIONAL, SE USA CUANDO TODAS LAS OTRAS CONDICIONES FUERON FALSE, ENTONCES SE EJECUTA EL CODIGO DEL ELSE
                {
                //Codigo
                }

Como verán, la única parte obligatoria en un if, es justamente el if, o sea estos casos son válidos(contando la estructura anterior


1)          if(condicion1)//OBLIGATORIO
                {
                //Codigo
                }


2)          if(condicion1)//OBLIGATORIO
                {
                //Codigo
                }
            else if(condicion2)//OPCIONAL
                {
                //Codigo
                }
           

3)          if(condicion1)//OBLIGATORIO
                {
                //Codigo
                }
            else//
                {
                //Codigo
                }


Veamos porque.

If preguntara dentro del código asi  ¿Es lo que esta dentro del paréntesis cierto? Con dos respuestas probables, si y no (true y false), si no existe un if, es imposible que exista un else if o un else

Else if es como otro intento, puedes agregar todos los else if que quieras, funciona asi
si todos los if y else if anteriores fueron no ¿ lo que esta dentro de este paréntesis es cierto?, tiene las mismas respuestas probables que el if.

Else es en caso de que ninguno de los if - else if anteriores fuera cierto, funciona asi
Si todos los casos anteriores fueron no, ejecutar esta acción.
En caso de no estar esta opción en tu código, es posible que no se ejecute ningun código de tu bloque if


No necesariamente las condiciones serán entre integers, puede ser cualquier variable, DateTimes, strings, etc…



CICLOS
Un ciclo, es es un código hecho para que se repita cierta cantidad de veces, esta cantidad de repeticiones es la cantidad  veces en que la condición del ciclo sea true, y al terminar, continua ejecutando un código, los tipos de ciclo son: For, foreach, while, do-while que los explicaremos ahora excepto do-while, nunca lo he usado y mi explicación seria algo mala.
For: este ciclo tiene la siguiente estructura:
for([variable], [condición], [acción a ejecutar cada vez que se cumpla un ciclo])
                {
                //Codigo
                }

Funciona así:
Se cumple el ciclo, y entonces se aplica el tercer parametro del ciclo, y luego se usa el segundo de la siguiente manera


Ejemplo: haremos un código en consola para elevar un numero(base) a una potencia
            Console.WriteLine("Escribe la base");
            //Establecemos la base de la potencia
            int Base = int.Parse(Console.ReadLine());
            //Creamos un int igual a la base, ¿por qué?, porque la base es constante, pero el resultado a medida
            //que se aplica la potencia no
            int NuevoValor = Base;
            Console.WriteLine("Escribe a cuanto deseas elevar la base");
            //definimos a cuanto estar elevada la base
            int Potencia = int.Parse(Console.ReadLine());
            //creamos el ciclo, definimos i = 1 porque toda potencia elevada a 1 sera igual a la base
            //Creamos la condicion, cada vez que i sea menor que la potencia, se multiplicara el nuevovalor por la base
            //y sumara 1 a i
            for (int i = 1; i < Potencia; i++)
            {
                NuevoValor *= Base;
            }
            Console.WriteLine("El resultado es: " + NuevoValor.ToString());
            Console.ReadLine();

While: Este ciclo, en teoría se puede usar en la mayoría de los casos en que se puede usar el ciclo for, pero cuando pasemos el ciclo foreach, veremos una manera de usar el ciclo while en el que no se puede usar el ciclo for.
 la estrutura es la siguiente
while(condición)
                {
                //Codigo
                }

Funciona asi: Mientras la condición se cumpla, ejecutar código, si deja de cumplirse, seguir ejecutando el código, pero se debe tener cuidado con crear un ciclo infinito ya que el código siguiente al ciclo nunca se ejecutara.
                         
Ejemplo de un ciclo while
            //definimos un bool en false y un int para el ciclo
            bool ejemplo = false;
            int i = 0;
            //mientras el bool sea falso, se ejecuta el codigo dentro del ciclo
            while(ejemplo == false)
                {
                    if (i < 10)
                    {
                        i++;
                        Console.Write(i + " ");
                    }
 }
                    else
                        ejemplo = true;
                }
            Console.WriteLine();
            Console.WriteLine("Ciclo terminado");
            Console.ReadLine();

Ejemplo de un ciclo while infinito
            //definimos un bool en false y un int para el ciclo
            bool ejemplo = false;
            int i = 0;
            //mientras el bool sea falso, se ejecuta el codigo dentro del ciclo
            while(ejemplo == false)
                {
                    if (i < 10)
                    {
                        i++;
                        Console.Write(i + " ");
                    }
                }
            Console.WriteLine();
            Console.WriteLine("Ciclo terminado");
            Console.ReadLine();

¿Cual es el problema? La variable a la que hace referencia la condición jamás cambia, por lo que el ciclo se ejecutara permanentemente, prueba el último código. ¿Puedes adivinar porque no continua escribiendo los números siendo que el ciclo no para de de ejecutarse? La respuesta es porque porque esta escrito un if que revisa si es que el int es menor que 10, y si es que lo es,  le suma 1 al int.

Foreach: Este tipo de ciclo lo que hace es aplicar alguna acción a CADA UNO de los objetos que cumplan la condición, se usa especialmente para variables dentro de alguna colección (puedes leer el archivo Colecciones.doc para entenderlas mas).
Ejemplo mezclando los dos ciclos (while y foreach), el método del string Split y un StringBuilder:
Crea un archivo de texto llamado ejemplo.txt en la carpeta bin/debug del proyecto que estas usando(si no tiene carpeta, apreta click en archivo y luego en guardar todo), copia dentro lo siguiente
3 un
11 xD
5 pero
8 en
1 Pablito
7 pego
10 manito
2 clavo
6 se
9 la
4 clavito

Ahora lo que haremos será ordenar la frase que esta con números al comienzo, usaremos un stringbuilder para comenzar a usar un código distinto al Console.Write(); para ponerlo más en práctica, aun así eres libre de cambiarlo.
En cada comentario, si al final esta escrito ”…” es porque continua un poco mas abajo a medida que avanza el código

            StringBuilder sb = new StringBuilder();
            //Creamos un array de strings, en que cada string dentro del array es una linea del archivo "ejemplo.txt"
            string[] lineas = File.ReadAllLines("ejemplo.txt");
            int i = 1;
            //mientras i sea menor a la cantidad de strings en el array...
            while (i <= lineas.Length)
                {
                //Para cada linea palabra en el array...
                    foreach (string linea in lineas)
                    {
                        string[] split = linea.Split(' ');
                        //si la primera palabra de la la linea es igual al int i ejecuta el codigo...
                        if(split[0] == i.ToString())
                        {
                            sb.Append(split[1] + " ");
                            //indicamos que una palabra fue agregada
                            i++;
                        }
                    }
                }
            //Termina el ciclo y escribimos la frase ordenada en la consola
            Console.WriteLine(sb.ToString());
            Console.ReadLine();


METODOS
Mas de una vez seguramente te topaste con uno de estos, los métodos sirven para hacer mas rápida de escribir una acción que debes usar varias veces, como también sirve para hacer mas organizado tu código fuente, para usarlos se llaman de la siguiente manera
 ClaseEnDondeRadica.NombreMetodo(parámetros necesarios). La estructura es la siguiente
[tipo][nombre](parámetros)
  {     
   Codigo
  }

Se debe mencionar, que un método NO PUEDE estar dentro de otro método, solo se pueden llamar otros métodos.
El nombre puede ser cualquiera, siempre y cuando no comience con un numero.
Parámetros, son las variables o clase NECESARIOS para ejecutar el código (si no es necesario ninguno, no hay porque agregar alguno). Es como si el método te pidiera algo.
Por ejemlo si tienes en parámetros algo como (string ejemplo), el método te esta pidiendo un string, y como ya aprendimos, el string puede ser algo entre comillas, “texto” o algún string que hallamos definido previamente.
Código, no necesita una gran explicación, es lo mismo que hubieses puesto en caso de que no fuera un método o lo que quieres que pase al llamar el método
Tipo,aprenderemos las mas usadas y básicas, que son void, o una variable
void : no retorna ningún valor, solo ejecutara alguna acción.
Ejemplo de un void:
Public static void Write(string texto)
{     
    Console.WriteLine(texto);
}
   
Como verán, no devuelve ningún valor pero ejecuta una acción y es escribir en la consola lo que uno escriba dentro de los paréntesis de parámetros cuando alguien llame al void.
Ejemplo:
Write(“ejemplo”);
//desde ahora será igual a
Console.WriteLine(“ejemplo“);
Ahora veremos el otro tipo de métodos que aprenderemos, que a diferencia del void, si devuelve un valor. Se usan de la siguiente manera
[Variable] [Nombre](Parámetros)
  {     
   Codigo
   Return valoraretornar;
  }

Por ejemplo:
Arriba de
static void Main(string[] args)
Copia este método

        private static int multiplicar (int multiplo1, int multiplo2)
            {
                return multiplo1 * multiplo2;
            }
Ahora en el void Main, agrega esto
            Console.WriteLine("escribe el primer multiplo");
            int m1 = int.Parse(Console.ReadLine());
            Console.WriteLine("escribe el segundo multiplo");
            int m2 = int.Parse(Console.ReadLine());
            Console.WriteLine("el resultado es " + multiplicar(m1, m2));
            Console.ReadLine();
Y genera, ahora:
Prueba removiendo el return y podras saber el error que da mientras no escribas return en los métodos que si retornan un valor.
Ensaya un poco, escribe un método que retorne el numero(base) elevada a una potencia. No sigas hasta que hayas tratado algunas veces


























         //double para que se puedan elevar valores decimales
        public static double elevado(double Base, double potencia)
        {
            double nuevovalor = Base;
            for(int i = 1; i < potencia; i++)
                {
                    nuevovalor *= Base;
                }
            return nuevovalor;
        }
        public static void elevar()
            {
                Console.WriteLine("escribe el numero base que deseas elevar");
                double numero = double.Parse(Console.ReadLine());
                Console.WriteLine("escribe el numero al cual deseas elevar la base");
                double Potencia = double.Parse(Console.ReadLine());
                Console.WriteLine("el resultado es: " + elevado(numero, Potencia));
                Console.ReadLine();
                Console.Clear();
                elevar();
            }

Y en el void Main, agrega
elevar();