Herramientas de usuario

Herramientas del sitio


highlevel:csharp

¡Esta es una revisión vieja del documento!


C#

Básico

Variables

Como asignar valores con coma flotante:

Float:		7.5f;
Double:		7.5d;
Decimal:	7.5m;

Matrices

Unidimensionales

  • Declaración: int [] Estudiantes;
  • Declaración indicando el tamaño: Estudiantes = new int [100];
  • Declaración e inicialización: int [] Estudiantes = {1,2,3,4};
  • Matriz de un objeto: SQLParametros[] Parametros; Parametros = new SQLParametros[5];

Multidimensionales

  • Declaración de dos dimensiones: int [,] Vertices;
  • Declaración de tres dimensiones int [,,] Vertices;
  • Declaración indicando el tamaño: Vertices = new int [10,24];

Conversiones (casts)

char	VariableChar;
int 	VariableInt;
VariableInt = 9;
VariableChar = (char)VariableInt;

Trabajar con strings

Si en medio de una cadena ponemos estos carácteres de escape….

\t	tabulación
\r	retorno de carro
\v	tabulación vertical
\f	la impresora pasa a la siguiente página
\n	nueva línia
\x	seguido de dos dígitos hexadecimales lo inserta
\u 	carácter unicode (seguido de cuatro dígitos)
\\	muestra la barra \, si sigue de una t, una r, v, f... provocará el efecto de estas.

Para desactivar carácteres especiales sólo habrá que poner una @ antes del string.

string MyString = @”hello \ world!;
string MyString = “c:\\carpeta\\archivo.txtstring MyString = @”c:\carpeta\archivo.txt<code>
Acceder a una posición del string
<code csharp>
string a = “Hola mundo!;
char b = a[3]; //a será igual a “a”

Si quisiesemos introducir en un string parámetros:

int a = 5;
string b = System.String.Format("La variable a, es: {0}", a.ToString());

Bucles y condicionales

while() {}
do {} while ();

foreach:
int [] Array;
Aray = new int [5]
Array[0] = 1;
Array[1] = 2;
...
foreach (int ArrayElement in Array)
	System.Console.WriteLine(ArrayElement);

break rompe el bucle. En cambio continue hace, dentro de un bucle, que pase del código que siga y vuelve a seguir con el bucle.

Parámetros especiales en las funciones

Parámetros de salida

Podemos pasar a una función una variable y esta función se encargará de cambiarle el valor, dentro de la función este valor no podrá ser leido.

void Func (out int a) {
	a=3;
}
Main () {
	int b;
	Func(out b);
}

Parámetros de referencia

Al pasar un valor en una variable, la función lo podrá leer y además escribir:

void Func (ref int a) {
	a++;
}
Main () {
	int b;
	Func(ref b);
}

Método System.Console.WriteLine

Para escribir por pantalla variables usamos: System.Console.WriteLine (“{0}, {1}”, X, Y);
Si quisiesemos escribir una variable float o double (Z), para indicar los decimales: System.Console.WriteLine (“{0:#,##}”,Z); Si Z vale 7,3454 esto escribirá: 7,34.

Método Main

Cada aplicación debe contener sólo una función Main dentro de alguna clase. Esta es donde se inicia el programa y debe de ser unmétodo público y estático. Al programa podemos pasarle argumentos desde la línia de comandos (si estos parámetros son (string[] args)) y también podremos devolver valores.
Si un archivo fuese arrastrado con el mouse, desde windows al ejecutable habrá un argumento, éste será la ruta completa del archivo arrastrado.

Programación Orientada a Objeto

Variables y métodos estáticos y constantes

Una variable estática dentro de la aplicación es una variable de la que sólo habrá una copia. Es decir, si tenemos varios objetos de una clase y ésta una propiedad estática, esta propiedad será la misma para todos los objetos de esa clase.
Para cambiar un campo estático de una clase no podremos hacerlo desde un objeto, sino desde el nombre de la clase:

code codigo = new code();
codigo.X = 5;
code.iZ = 4;

La propiedad iZ es una propiedad estática de la clase codigo.
Con las funciones estáticas ocurre lo mismo, sólo hay una copia en memoria para la aplicación, pero estas no pueden usar elementos de la clase que no estén marcados como estáticos (ej. Intentar acceder a una función desde el main. Podemos llamar a métodos estáticos de una clase sin necesidad de que existan objetos de esta), debemos tener en cuenta que a un método estático podremos acceder desde cualquier parte del programa, pero éste sólo podrá usar clases o métodos y variables estáticas.

La sintaxis para una constante es: const <tipo de dato> <nombre> = <valor>;
En una clase lo mejor es que las constantes sean estáticas, así para cada objeto no se carga siempre esa constante y ese valor cada vez, sino sólo una vez.

Clases anidadas

En c# existe la posivilidad de crear clases anidadas dentro de otras.

class Class1 {
	private int i = 5;
	private class Class2 {}
	public class Class3
	{
		public void escribePrivado () {
			Class1 cls = new Class1();
			Console.WriteLine(cls.i.ToString());
		}
	}
}
class Class4 {
	public static void Main () {
		Class1.Class3 cls = new Class1.Class3();
	}
}

Si main estubiese en class1 podríamos acceder a class2.
En class3 podemos ver como podemos acceder a los elementos privados de class1.
Si en class4 hiciesemos otra clase que heredase de class3, ésta no podría acceder a los elementos privados de class1.

Constructores y destructores

Existe la sobrecarga de constructores.
La sintaxis para un constructor de una clase es: public <nombre de la clase> (<parámetros>) { } A los destructores no los podemos llamar mediante código, pero su sintaxis es: ~<nombre de la clase> { }

Propiedad readonly

Cuando a una variable de una clase le indicamos que es de sólo lectura (ej. public readonly int campo), sólo podremos modificar su valor en la declaración de és (si en el ejemplo incluimos algo así ‘= 123;’) o desde el constructor de la clase.

Descriptores de acceso

  • get Con get recogemos el valor de una variable.
  • set Con set asignamos el valor a una variable.
private int iX, iY;
public int X {
	set {
		iX = X;
	}
	get {
		return iX;
	}
}

Indizadores

Una clase en sí también puede devolver un valor de un array:

class Indizadores {
	public int this[int IND] {
		get{
			switch(IND) {
				case 1:
					return 3;
				case 2:
					return 4;
				default:
					return 0;
			}
		}
	}
}

Llamandola así devolverá un 3: Indizadores E = new Indizadores(); Console.Write(E[1]);
Podemos sobrecargar los indizadores mientras estos tengan diferente la lista de parámetros.

Operadores typeof y sizeof

typeof Indica que tipo es una variable dentro de las bibliotecas .NET (ej. int = Sytem.Int32).

Console.WriteLine(APP.a + " {0} y {1} ", typeof(int), typeof(short));

siceof Para usarlo hay que hacerlo con el compilador preparado para código no seguro e indicando en la función que esta es de código no seguro.

Console.WriteLine("The size of short is {0}.", sizeof(int));

Operaciones con clases

Podemos indicar lo que ocurre si sumamos dos de nuestras clases. Para ello debemos crear una función dentro de la clase con estas características:

  1. Que sea pública y estática
  2. Debemos indicar el valor que devuelve
  3. Luego la palabra clave ‘operator’ seguida del operador que usaremos
  4. Los que le pasaremos.

Los operadores son: + (suma), - (resta), ~ (bit a bit), ++ (incremento), – (decremento).
Después hay otros que deben declararse juntos y deben devolver un bool: true y false, > y <, == y !=.
Ejemplos:

class Punto {
	public int x, y, z;
	public Punto () {
		x = 1;
		y = 2;
		z = 3;
	}
}

Cambio de signo:

public static Punto operator - (Punto TmpPunto) {
	TmpPunto.x = -TmpPunto.x;
	TmpPunto.y = -TmpPunto.y;
	TmpPunto.z = -TmpPunto.z;
	return TmpPunto;
}

Llamandolo como sigue nos cambiaría a todas sus variables el signo:

Punto point = new Punto();
point = -point;

Pongamos sumando dos Puntos (que se sumen las variables del primero con las del segundo de forma correspondiente (también podríamos sobrecargar la resta)):

public static Punto operator + (Punto FstPunto, Punto ScdPunto) {
	Punto TmpPunto = new Punto();
	TmpPunto.x = FstPunto.x + ScdPunto.x;
	TmpPunto.y = FstPunto.y + ScdPunto.y;
	TmpPunto.z = FstPunto.z + ScdPunto.z;
	return TmpPunto;
}

Para el true o false debemos codificar los dos, que devuelva un bool y pensarlo del palo “sí, es cierto que es cierto o no es cierto que es cierto” o “cierto… es falso o no es falso”:

public static bool operator true (Punto TmpPunto) {
	if (TmpPunto.x < 0)
		return true;
	else
		return false;
}
public static bool operator false (Punto TmpPunto) {
	if (TmpPunto.x > 0)
		return true;
	else
		return false;
}

Podemos definir qué ocurriría al hacer una conversión:

  • Si es implícita: public static implicit operator int (Punto TmpPunto);
  • Si es explícita: public static explicit operator int (Punto TmpPunto);

Implicita es si a un double le asignamos un float, explicita es si hacemos algo así: VarFloat = (float)VarInt

Herencia

Para indicar que una clase se hereda de otra, en la declaración: class Point3d : Point2d
Si Point2d tiene por ejemplo X e Y y en 3d queremos volver a definir X deberemos hacer: new public int X;
Si tenemos en la clase Point2d un método que escribe por pantalla la X y la Y y no queremos conservar su código para Point3d pero sí el nombre de la función, deberán ser declaradas así:

  • En Point2d: public virtual void Print() {… }
  • En Point3d: public override void Print() {… }

Podremos también llamar, desde Point3d al método Print de Point2d indicando: base.Print();
Podemos definir un método abstracto de la clase, esto es sólo una definición, una indicación a las clases derivadas que han de poner código dentro de ese método, el método codificado luego será también escrito como override:

  • Dentro de una clase base polígono: public abstract int Perimetro();
  • Dentro de la clase cuadrado derivada de polígono: public override int Perimetro() { … }

Podemos indicar (como hacemos con el indicador this) que una variable viene de su clase base así: base.X. O de esta misma forma, en un método override, indicar que antes de continuar con el código se ejecute lo que se ejecuta en su clase base: int i = base.Add(obj);

Aún así la palabra base también nos serviría, en un ejemplo como en el de Point3d para el constructor, si hacemos un constructor así: public Point3d (int X, int Y, int Z) : base (X, Y) Y en el constructor de su clase base (Point2d) tenemos esta definición: public Point2d(int X, int Y). Lo que hace ese : base(X, Y) es llamar al constructor parametrizado de su clase base Point2d con los parámetros X e Y que le han pasado a Point3d.

Podemos sellar una clase para que de esta no se herede código, de esta forma: sealed class Point2d { … }

Puede ocurrir que la base clase tenga un método que nosotros queramos implementar, pero sta no esté implementada como virtual, para sustituir ese método por el nuevo sólo deberemos incluir el modificador new en la declaración de la función de la clase derivada: new public void Print() { … }

Ámbito de una variable según su declaración

  • public: Son visibles dentro de la misma clase, en clases derivadas y en el código donde se crean los objetos.
  • private: Sólo son visibles dentro de la clase donde se definen.
  • protected: Visibles en la clase donde se definen y en las derivadas.
  • internal: Sólo visibles dentro del archivo binario (compilado) donde se han declarado.
  • protected internal:

Una clase pública podrá verse desde otro archivo, si no lo es no.

Object en .NET

Todas las clases base creadas en c#, sin que nosotros hayamos indicado una clase base, se derivan de la clase base System.Object. Ésta contiene ciertos métodos que nos pueden ser útiles:

  • Equals(obj): Compara dos objetos y devuelve true si son iguales o false si no. Es virtual, por lo que se puede modificar.
  • GetType(): Proporciona información obre la clase.
  • ToString(): Pasa a cadena el cntenido del objeto.
string MyString;
MyString = 123.ToString();
  • Finalize(): Es virtual y podemos cambiarlo. No hace nada, pero siempre se le llama cuando el objeto es destruido, por lo que podemos usarlo como destructor.
  • MemberwiseClone(): Crea una copia del objeto.

Por lo que un objeto “objeto” es un tipo estándard que podemos usar en cualquier parte, y cada objeto de cualquier sitio podrá ser asignado a una variable objeto “objeto”. Para saber si una variable es de un tipo o de otro usamos el operador is.

public static void CheckType(object o) {
 if (o is string) {
  Console.WriteLine ("o is String");
  string s = (string)o;
  Console.WriteLine (s);
 }
 else if (o is Int32[]) {
  Console.WriteLine ("o is Int32 array");
  Int32[] ins=(Int32[])o;
  for(Int32 i=0;i< ins.Length;i++)
    Console.WriteLine (ins[i]);
 }
 else if (o is Myclass) {
  Console.WriteLine ("o is Myclass");
  Myclass a = (Myclass)o;
  a.doSomething();
 }
}

Control de excepciones

Para controlar los errores de código en C# usamos try y catch. Lo que hacemos es colocar dentro del try (entre corchetes) el código que puede causar una excepción, luego el catch, que será el código que se ejecute si ocurre una excepción.
También podemos usar finally con el código que vendrá después del try (o del catch) por ejemplo en el try abrimos ficheros, en catch si hay algún error que lo diga y en finally cerramos el fichero.
Para capturar la excepción, podemos coger y en el catch, entre paréntesis declarar una variable Exception y luego mostrarla llamando a su propiedad ToString():

catch (Exception exp) {
	System.Console.WriteLine(exp.ToString());
	System.Console.Read();
}

También existen excepciones ya definidas por .NET. Éstas las introducimos en los parentesis del catch (catch (StackOverflowException)) y ese será el codigo para esa excepción, estas excepciones son:

  • OutOfMemoryException, StackOverflowException, IndexOutOfRangeException…

También puede declarar sus propias excepciones o lanzar excepciones simples, de la aplicación, haciendo un new ApplicationException.

Espacios de nombre (namespaces)

Los namespaces pueden estar anidados, podemos incluir varios dentro de uno o podemos indicar que un namespace está incluido dentro del otro así: namespace numero.uno {}, uno estaría dentro de número.
Para declarar un objeto de una clase distinta a la nuestra:

namespace.clase objeto = new namespace.clase();

Podemos usar un mismo namespace en varios archivos. De esta forma el contenido de estos archivos quedará incluido dentro del namespace.
Y podemos acortar el nombre de los namespaces usando alias. Por ejemplo:

using sc = System.Console;

Y usarlo así:

sc.WriteLine(“hola”);

Podemos elegir que un using esté sólo en un espacio de nombres colocando este dentro de su contenedor:

Namespace MyCollections {
	using System.Collections;
	...
}

Enumeraciones

Una enumeración es una especie de estructura con varios elementos, estos elementos reciben una numeración (el primero 0, los que siguen 1, 2, 3…) a no ser que sea cambiada. Por defecto una numeración usa ints, a no ser que este valor también sea cambiado:

public enum Estado {
  abierto,
  cerrado
}	
public enum Estado : short {
  abierto,
  cerrado
}	   
public enum Estado {
  abierto=10,
  cerrado=50
}		 

El identidificador de la enumeración se podrá usar como una variable (en nuestro caso Estado).

class Punto2d {
	public enum Coordenadas {X, Y};
	public Coordenadas cord;
}
class Punto3d {
	static void Main () {	
		Punto2d point = new Punto2d();
		point.cord = Punto2d.Coordenadas.X;
		System.Console.WriteLine(point.cord);
		Console.ReadLine();
	}
}

Dentro de un if:

public enum Modo {Leer, Escribir};
public BinaryFlux (string path, Modo mode) {
	if (mode == Modo.Escribir)
	{ ... }

Podemos usar una enumeración en un swich:

switch (this.varEnum) {
	case enum.Opt:
		break;
}

Interfaces

Una interfaz actúa como una plantilla para una clase. Todos los métodos declarados en esta deberán ser implementados en la clase. Una clase no puede heredar de varias clases pero sí de varias interfaces. La ventaja es que luego, la interface actúa como si fuese una clase de la que podemos definir objetos:

interface a {
	void b ();
}
class Class2 : a {
	public void b() {
		System.Console.WriteLine("entra");
	}
}
class Class3 {}
class Class1 {
	[STAThread]
	static void Main(string[] args) {
		ArrayList list = new ArrayList();
		list.Add(new Class2());
		list.Add(new Class3());
		list.Add(new Class2());
		for (int i=0; i<list.Count; i++){
			a tmp = list[i] as a;
			if(tmp != null)
				tmp.b();
		}
		System.Console.ReadLine();
	}
}

Para crear una propiedad debemos definir si aceptará get o set: int r { get; set; }
Una interface puede heredar de varias interfaces.

highlevel/csharp.1230145234.txt.gz · Última modificación: 2020/05/09 09:24 (editor externo)