
3 7, 2008
Cuando creamos un objeto mediante “ Caja c= new Caja();” , lo introducimos en memoria, en el heap, puesto que C es un tipo referenciado.
Cuando creamos objetos también lo llamamos crear una instancia de una clase.
-Datos miembro. {campos,constantes}
-Funciones miembro se componen {metodos,propiedades,constructores,destructores,operadores,indizadores}
Modificadores de las Funciones Miembro
[modificador] tipo identificador ()
Modificadores de acceso pueden ser “public,private,protected, internal, protected internal” y otros como “ abstract,const,event, extern, override(sobrescribir un método), new(),readonly,sealed,static,unsafe,virtual,volatile”
Estructuras (Types de Visual Basic Clásico, o registros de pascal)
Una estructura es un tipo valor; va a la pila de procesamiento.
Struct nombre
{
Public const int a=5;
Public long l=;
Void metodo(){
}
}
En los métodos por defecto, los tipos por valor se pasan por valor, y los tipos referencia se pasan pasan también por valor.(pero realmente pasamos una referencia por valor) porque mandamos una copia de la dirección de memoria.
Si queremos pasar algo por referencia real, ponemos el modificador “ref” delante de la variable.
Si queremos que un metodo devuelva más de un valor y no queremos utilizar variables por referencia podemos utilizar el modificador “out”
Void m (out int i, out int j)
{
i=7;
}
Declaramos los arrays entre corchetes. Primero el tipo.
Los arrays en C # empiezan en 0.
Int [] a;
a= new int [5];
string s = new string [2];/// string[]= {“uno”,”dos”}
s.length
También existen varias clases en el Framework, como la llamada “Array” y tiene varios método como el estático llamado “Sort”.
Array.Sort(a);dónde “a” es el array a ordenar.
Arrasy multidimensionales
Int [,] a ={1,2},{2,3},{3,5}; // Int [][] a = new int [3][3]
También podemos crear arrays irregulares ( puedo introducir en un array otro array):
Por ejemplo:
Int [][] a= new int [2][];:
a[0]=new int [2];
a[1]=new int [3];
La propiedad GetLength nos devuelve el número de elementos de un array.
Operadores lógicos
&,|,^,!, &&, ||
El && sirve para que siga comparando la otra comparación, por lo que en el ejemplo siguiente comprobaría también la segunda comparación.
If (a==7 && 6==8)
Operadores de incremento, preinceremento
i++,++i—i,i—
Operadores desplazamiento de bits
<<,>>. Es para hacer una división o multiplicación por 2 a toda velocidad
Operadores de comparación
==, ¡=,
Operadores de asignación
=,+=,-=,/=,%=,&=,etcç
Operadores de acceso a miembros
El punto ( .)
Los corchetes []
Conversión con los paréntesis ()
Operador ternario condiciona que es la interrogación.
Checked, unchecked
Byte 6 = 255;
checked{
6++;
}
Console.writeln(6); Esto no daría error al sobrepasarte de rango porque lo controlo con checked
Operador “is” es para preguntar si esta variable es del tipo tal.
Por ejemplo: If (i is object)
Implícitas.Son automáticas
int i=5;
long l = i;
Aquí tenemos el valor de i que es entero, cuado se lo asignamos a l , pasa a ser entero largo.
Explicitas (también llamadas “casting”). Son manuales.
Long l= 7;
Inti = (int)l;
Todas las conversiones que tengamos que hacer de tipos más grandes a más pequeños hay que hacerlas explicitas, igual que cuando hacemos conversiones de valores con signo
Boxin, unboxing
Para convertir un tipo primitivo en objeto y al revés
Int i=2;
Object o=i; //enmarcar(boxing)
———————
Int i= 2;
Object o=I;
Int i=(int) o; //desmarcar
Sólo se puede desmarcar si hemos enmarcado
Public enum tiempo {
Mañana=0;
Tarde=1;
Noche=2;
{
Imaginemos que tenemos un método al que le pasamos:
Llamada del método:Metodo(tiempo.mañana);
Método: void Metodo( Tiempo t)
El valor t nos daría como resultado 0.
Los espacios de nombres se pueden anidar.
Namespace pepe{
//Aquí pondríamos todas las clases
Namespace ventas{
Class c1 {
}
}
Class c2{
}
}
Si yo quisiera usar la clase c1 desde otro archivo pondría para poder importarla:
Using pepe.ventas;
Si existe en el mismo espacio de nombres dos clases con el mismo nombre habría que hacer referencia a ellos mediante la ruta completa. Por ejemplo:
Pepe.ventas.c1 c1= new Pepe.ventas.c1();
Si queremos ahorrar tiempo escribiendo, podemos crearnos un alias:
p=Pepe.ventas;
p.C1.talycual;
int
Public static void main ()
{
}
Tecleamos en la linea de comandos el nombre de la clase y le pasamos los argumentos que queramos.
c:>> c 1 2 3
Class c
{
Public static void main (string [] args)
Recogemos array de los argumentos pasados desde la línea de comandos.
Arg [0];
Arg[1];
Arg[2];
{
}
Int i=2, j=3;
Console.WriteLine(“valor de i:” ! + I+ “pesetas”);
Para no tener que escribir las comillas podríamos poner lo siguiente:
Console.writeline(“{0} mas {1}={3}”,i,j,i+j)
Formateo para poner tabulación
Para escribir esto por pantalla:
987
+1
567
Console.writeLine(“{0,4}\n +{1,4}\n - - - — \n{2,4}”,i,j,i+j)
También se pueden crear máscaras:
Console.writeLine(0:#00}
// Una línea
/*Varias líneas
*/
///Para sacar la documentación
Sacar documentación
Visual Studio >> Herramientas>>Generar documentación de paginas web
Orientación a Objetos
En .Net, la herencia es simple, sólo puede tener un padre.
Class C1
{
Int p;
Void metodo()
{}
Void metodo(int i)
{
}
}
Class c2:c1 // Hacemos que c2 herede de c1.
{
Int J;
Void metodo2();
{
//Puedo llamar a las propiedades del la Clase C1 porque los estoy heredando. Si los métodos son privados no se heredan.
Console.writeLine(p);//La propiedad p es de C1.
}
Medoto();//estamos llamando al primero de los métododos de la clase c1
Metodo(7); //estamos llamando al segund de los métododos de la clase c1 porque le estoy pasando un parametro
}
Cuando dos métodos se llaman igual, pero que tienes parámetros diferentes.
Redefinición y ocultamiento de Métodos
Sobrescribir un método:
Class c1{
Virtual Void metodo1(){
//Con Virtual, estamos haciendo que se pueda sobrescribir el método
}
}
Class c2 : c1{
Override Void metodo1(){
//Con override hacemos que sobreescriba
}
}
//cuando sobrescribimos poedemos cambiarlo totalmente o ampliarlo. Por ejemplo
Class c2 : c1{
Override Void metodo1(){
Base.metodo1()
//ConBase le decimos que queremos ampliar el método
}
}
//Si lo que queremos es ocultar el método de la clase de la que heredo en lugar de sobrescribirlo debería poner New
Class c2 : c1{
New Void metodo1(){
//Es decir con esto conseguimos que al llamar a metodo1() cree uno nuevo pasando de el del padre
}
}
Una clase abstracta puede tener métodos abastractos y no abstractos
Abstract Class vehiculo{
//Ponemos también abstract a la clase, para que no me cree una isntancia de la clase vehiculo porque no tiene código
Abstract Void frenar(); //Ponemos Abstract, porque el método frenar no tiene sentido crear código en la clase vehiculo, por lo que también se lo pongo a la clase. Y luego en la clase coche sobrescribo el metodo frenar con el código de coche..
}
Class coche: vehiculo{
Override Void frenar(){
}
}
Para que no se puedan heredar las clases o sobreescribir los métodos .
Class coche:
{
Sealed Void frenar(){//Para que no se pueda modificar este método
}
}
//para que no se pueda heredar la clase pondriamos el “sealed” a la clase.
Sealed Class coche:
{
Sealed Void frenar(){//Para que no se pueda modificar este método
}
}
Class Caja
{
Private int ALTO; //Esto es un campo
Public int alto { //esto es una propiedad de la clase
Get{
Retunr alto;
}
Set{
alto=value;//value sería el valor que le pasamos
}
}
Para comparar contenidos de valores referencia utilizamos “Equal”
If (c1.equal,(c2)) ……………..
Sobrescribir el “equal”
Class Caja
{
int alto,fondo; //Esto es un campo
overrride bool Equal(object o)
{//Comparamos objetos
If (this.alto==o.alto && this.ancho=o.ancho)
Return true
Else
Return false
}
Caja c1 = new caja();
Caja c2 = new caja();
If ( c1.Equal(c2))…………
Un método tiene el mismo nombre en diferentes clases
Para el polimorfismo tenemos que tener herencia.
Se puede hacer casting entre clases que etán interconectadas.
Figura f;
Rectangulo r = new Rectangulo();
F=r;//Padre=hijo
Es como una clase abstracta pero a lo bestia. Los métodos no tienen cuerpo,
Sólo hay declaraciones de propiedades,metodos,eventos, indicadores.
No puede haber campos.
No se puede instanciar.
Para las interfaces, la connotación suele ser una I mayúscula seguida del nombre.
Con los interfaces se puede hacer herencia múltiple de varias interfaces. Se pondrían entre comas las diferentes interfaces de las que heredo.
También una interface puede heredar de una clase y una interface conjuntamente, pero
Primero se tiene que poner la clase y después la interface seguido de coma.
Por ejemplo: IMiInterface.
Public interface Imia
{
//Como vemos no tienen cuerpo
Public Int cont();
Public string Cadena (string c);
Decimal Balance
{
Get;
Set;
}
}
Después de declararnos la Interface nos hacemos una clase que herede de la interface y en la que terndríamos que desarrollar el cuerpo de los método, menos si se han declarado como abstract:
Public abstract class Classe1: Imia
{
Public Int cont();
}
Las interfaces se pueden heredar.
Public interface Imia2: Imia
{
//Como vemos no tienen cuerpo
Public void hola();
}
//en este caso he heredado de otra interface llamada Imia.
//En el caso que nos creasemos una clase que heredase de Imia2, tendríamos los
Mismos componentes de Imia2 e Imia, y tendríamos que desarrollar los cuerpos en la clase, menos si esa clase es abastracta
Un constructor no devuelve nada, ni siquiera Void
Se llama igual que la clase.
Automáticamente se crea el constructor si tu no lo creas.
Se utilizan para pasar parámetros.
Classe rectangulo
//constructor. Inicializamos en el constructor las propidedades
Rectangulo (int dim1, int dim2)
{
This.dim1=dim1;
This.dim2=dim2;
}
//También podemos hacer sobrecarga de cosntructor
Rectangulo ()
{
//y hacer asignación múltiple
This.dim1=this.dim2=-1;
}
Por lo que podríamos llamar a los dos constructores.
Rectangulo r = new rectangulo ( 7,8);
Rectangulo r1= new rectangulo();
También podemos llamar a las constantes de una clase sin tener que instanciar y inicializar.
Public class constantes
{
Static const string conexión=”sdf”;
Static const int timeour=20;
//Pongo en constructor privado para que nadie lo llame desde fuera
Private constantes()
{}
}
String c= constantes.conexión.
//no nos ha hecho falta instanciar, porque las propiedades static funcionan así.
//Supongamos que la clase rectangulo tiene el siguiente método:
Public static Rectangulo GetRectangulo()
{
If ………
//Si se cumple la condición que sea llamo al constructor, sino
//devuelvo null.
Return new rectangulo();
Else
Return null;
}
//También podemos llamar a un médodo de una clase sin instanciar y sin llamar al constructor, porque la llamada al constructor la hacemos en la propia clase
Rectangulo r = rectangulo.getrectangulo();
If r==null …….
Se cargan antes que el constructor normal. Se ejecuta cuando
la clase se carga en memoria, por lo que sólo se ejecutan una sóla vez,
la primera vez que se instancia.
ClassA
{
Static int i;
Static A()
{
i=10;
//Se utilizar para inicializar sólo las variables estáticas.
}
}
Nota: Desde un método estático no puedo llamar a otros no estático, pero sí al revés
Desde fuera de una clase se puede llamar a métodos estáticos sin instanciar un objeto
Desde un método estático para llamar a uno no estático tengo que crearme una instancia de la clase.
Llamadas a un constructor desde otro
ClassA
{
A()
{
}
//Con la siguiente línea hacemos que primero se ejecute el
Primer cosntrunctor.
A(int i): this()
{
}
}
A a =new A();
A a =new A(5);
También podemos llamar al constructor de la clase padre
Cuando creamos un objeto de una clase y no tiene constructor, llama al del padre automáticamente.
Class A
{
A ()
{
Console.WriteLine(“A”);
}
}
Class B: A
{
B()
{
Console.writeline(“B”)
}
}
}
B b=new B();
El orden de ejecución sería A,B
Tenemos varias maneras maneras de implemetar los destructores:
-Implementar el metodo dispose dela clase System.Idisposable
-Utilizar un destructor que tendría en mismo nombre de la clase pero con el carácter”~“delante.
- O bien utilizar los dos.
Si tenemos objetos controlados y queremos destruirlos, invocamos el método dispose. Si no lo hacemos no pasa nada, porque el recolector de basura pasará y los destruirá.
Si tenemos objetos no controlados ( ej. Un método que crea una conexión a una bbdd) entonces implementamos también el destructor.
Eso si, si no hay objetos no controlados no se introduce el destructor.
Public class Figura: Idisposable
{
Public void dispose()
{
Dispose (true);
//hacemos que no pase el recolector en la linea siguiente
Gc.SuppressFinalize(this)
}
~Figura ()
{
Dispose(false);
}
Protected virtual void dispose (bool disposing)
{
If (disposing)
{
//Liberar los objetos controlados
}
//liberar los objetos no controlados
}
}
Nosotros no podemos ejecutar el destructor ~Figura directamete desde código, porque lo hace él.
Los campos read only se inicializan en los constructores que deben ser estaticos
Con diferencia a una constante, estos se resuelven en ejecución y no en compilación
Como las constantes.
Class A
{
Public static readonly uint maxDoc;
Static A()
{
Maxdco=7;
//A partir de esta asignación, no se puede volver a asignar a esta constante (read only)
}
Class A {
Public static int I;
Void metodo (){
I=7;
}
}
A a = new A();
a.i=10;
A a1= new A ();
Console.writeLine(a1.i)
//Daría como resultado 10, porque los campos státicos se guardan en memoria para toda la clase.
Si instanciamos, sigue guardando el valor.
Estructuras (Types de Visual Basic Clásico, o registros de pascal)
Una estructura es un tipo valor; va a la pila de procesamiento.
Una estructura puede tener métodos.
No soportan la herencia.
No se puede crear un constructor sin parámetros(un error de mocosoft), por lo que el compilador inicializa las variables si no se le pasa nada.
Struct dimension
{
Public double ancho; //Se puede hacer
Public double alto; //Se puede hacer
Public double alto=2; //No Se puede hacer
Void dimension(int i){
}
}
Dimension d = new Dimension();
d.ancho=7;
d.alto=10;
————–
//pero si leemos un valor antes de haberlo asignado, daría error:
Dimenson d;
Double d1=d.ancho; ///Esto daría error
Matriz a= new Matriz ();
Matriz b= new Matriz();
Matriz c =a+b //Para sobrecargar el operador +, y que me sume las dos matrices correctamente haríamos.
Public static matriz operator + (Matriz a, Matriz b)
tipooperator *
tipooperator -
{
}
Ej. Sobrecarga el = =
Permite tratar las propiedadescomo arrays.
Public Class cuadrado
{
Public int dim1,dim2;
Public int this[int i];
{
Get{
Switch (i){
Case 0: return dim1;
Case 1:return dim2;
Default:
Trow new
IndexOutOfRangeException(“te has pasao de rango”);
//En caso de que el indice que introduzca el cliente sea mayor de 1, entonces controlo el error.
}
}
Set{
Switch (i){
Case 0: dim1=value;
Break;
Case 1 dim2=value;
Break;
Default:
Trow new //Arrojamos un error.
IndexOutOfRangeException(“te has pasado de rango”);
//En caso de que el indice que introduzca el cliente sea mayor de 1, entonces controlo el error.
}
}
}
}
Cuadrado c=new Cuadrado();
C[27]=3;
//Si llamasemos a cuadrado[0] estaríamaso llamando a la propiedad dim1, pero si llamamos a c[27] nos estaríamos pasando de rango y tendríamos que provocar un error.
Las excepciones o control de errores.
Todas las excepciones derivan de la clase Object.
Object
Exception
SystemExceptionApplication Exception
AritmeticException SnackOverFlowExceptionMiException
OverFlowException
Try{
//Aquí iria
}
Catch(ArimeticException e) //Catch es como una sentencia Switch
{
}
Catch(Exception e) //
{
}
Finally //El Finally se ejecuta siempre, tanto si da error como si no
{
}
Lo normal es que los Try se introduzcan dentro de las clases.
Try{
Int [] a = {0,7,8};
A[20]=10;
.Try {
a[27]=10;//*
int j=0;
int i=10/j;
}
Catch(AritmeticException e){
}
}
Match (argumentoutofrangeException e)
{
//** Aquí controlaría el error de rando dando en el bloque interno Try.
}
//Cuando en el bloque interno try da un error de fuera de rango(*), y no lo tenemos controlado como pasa aquí, ya lo controlará ya más tarde en el otro bloque más extreno(**) try.
Class miException
: aplicationException
{
Public Miexception(strign nombre)
:base (“Se ha producido un error” + nombre){
}
Public Miexception(strign nombre, Exception innerException)
:base (“Se ha producido un error” + nombre, innerException){
}
Public override Tostring()
{
Return(“Aquí pondría un texto”){
}
}
//Esta clase la introduciríamos en nuestra dll normal.
Ejemplo:
Void dividir()
{
If (op2==0) {
Trot new miexcetion(“division por 0”,new arithmeticException());
}
}
Un delegado pasa a un método otro método.
Los eventos y los threads utilizan los delegados.
El delegado representa al método que vas a ejecutar
Se pueden poner dentro o fuera de una clase y realmente son una clase.
Delegate string Midelegado ( string s); //Esta linea se convierte en una clase,
//por lo que podemos crear una instancia de ella.
Void metodo()
{
Int x=40;
//
MiDelegado m = new Midelegado(x.ToString)
m(); //al llamar a m se visualiza “40”
Directivas en tiempo de compilación que pueden ir en cualquier parte del código
#define DEBUG
#undef DEBUG
#ifDEBUG
#elif DEBUG2
#else
#endif
Por ejemplo:
//La instrucción que va entre estos dos bloques no estaría en el .exe final, sino que sólo lo ves tu cuando creas el código.
# if DEBUG
Console.WriteLine(i);
#endif
#warning
Para sacar un warning en nuestra ventana de errores.
#region
Para ocultar código para el programador.
Class A
{
[DLLImport (“user32.dll”)]//estamos llamando a una librería externa
Public static exterm int mesageBox(int h Parent, string Message, string Caption, int Type);
Void metodo(){
mesageBox (0,”hola”,”mensaje”,0);
}
[condicional(“DEBUG”)] //Te compilaria el método “metodo2” si tienes declarada antes DEBUG
Void metodo2{
………..
}
}
Por defecto en .net hay un solo hilo de ejecución, pero podemos insertar más hilos de ejecución.
Algunos métodos son Abort,suspend,resume,look.
Los hilos de ejecución no compartern variables locales, pero si campos