Professional Documents
Culture Documents
ISMA-3
INVESTIGACIONES:
➢ GET Y SET.
➢ CLASES
➢ SYSTEM
➢ CREACION DE HILOS
➢ ........
C# soporta un completo juego de operadores a nivel de bits, por lo que podemos realizar tareas al igual
que se hacen en ensamblador. Las operaciones a nivel de bits nos permiten comprobar, asignar o desplazar
los
bits reales que componen un dato de tipo entero. Los operadores son:
OPERACION / ACCION.
CLASES
En C#, una clase es un tipo de datos muy eficaz. Como las estructuras, las clases
definen los datos y el comportamiento del tipo de datos. Los programadores
pueden crear objetos que son instancias de una clase. A diferencia de las
estructuras, las clases admiten herencia, que es una parte fundamental de la
programación orientada a objetos. Para obtener más información, vea Herencia.
Declarar clases
Copiar código
public class Customer
{
//Fields, properties, methods and events go here...
}
El nivel de acceso precede a la palabra clave class. En este caso, se utiliza public,
que significa que cualquiera puede crear objetos a partir de esta clase. El nombre
de la clase sigue a la palabra clave class. El resto de la definición es el cuerpo de
clase, donde se definen el comportamiento y los datos. Los campos, propiedades,
métodos y eventos de una clase se conocen colectivamente como miembros de
clase.
Crear objetos
Copiar código
Customer object1 = new Customer();
Cuando se crea una instancia de una clase, una referencia al objeto se vuelve a
pasar al programador. En el ejemplo anterior, object1 es una referencia a un
objeto basado en Customer. Esta referencia hace referencia el nuevo objeto, pero
no contiene los datos del propio objeto. De hecho, se puede crear una referencia
a objeto sin crear un objeto:
C#
Copiar código
Customer object2;
No se recomienda la creación de referencias a objetos como ésta, que no hace
referencia a un objeto, porque al intentar el acceso a un objeto a través de esa
referencia se producirá un error en tiempo de ejecución. Sin embargo, este tipo
de referencia se puede crear para hacer referencia a un objeto, ya sea creando un
nuevo objeto o asignándola a un objeto existente, de la forma siguiente:
C#
Copiar código
Customer object3 = new Customer();
Customer object4 = object3;
Este código crea dos referencias a objeto que se refieren al mismo objeto. Por
consiguiente, los cambios realizados en el objeto a través de object3 se
reflejarán en los usos posteriores de object4. El hecho de que las clases se
conozcan como tipos de referencia se debe a que se hace referencia a los objetos
basados en clases por referencia.
Herencia de clase
La herencia se realiza a través de una derivación, lo que significa que una clase
se declara utilizando una clase base de la cual hereda los datos y el
comportamiento. Una clase base se especifica anexando dos puntos y el nombre
de la clase base a continuación del nombre de la clase derivada, del modo
siguiente:
C#
Copiar código
public class Manager : Employee
{
// Employee fields, properties, methods and events are inherited
// New Manager fields, properties, methods and events go here...
}
Cuando una clase declara una clase base, todos los miembros de clase definidos
para la clase base también pasan a formar parte de la nueva clase. Dado que una
clase base se puede heredar de otra clase, que a su vez se heredó de otra clase y
así sucesivamente, una clase puede provenir de varias clases base.
Ejemplo
En el ejemplo siguiente, se define una clase pública que contiene un campo único,
un método y un método especial denominado constructor. Para obtener más
información, vea Constructores (Guía de programación de C#). Luego se crean
instancias de la clase con la palabra clave new.
C#
Copiar código
public class Person
{
// Field
public string name;
// Constructor
public Person()
{
name = "unknown";
}
// Method
public void SetName(string newName)
{
name = newName;
}
}
class TestPerson
{
static void Main()
{
Person person1 = new Person();
System.Console.WriteLine(person1.name);
person1.SetName("John Smith");
System.Console.WriteLine(person1.name);
}
}
class Persona
{
string _Nombre; // Campo de cada objeto Persona que
almacena su
nombre.
int _Edad; // Campo de cada objeto Persona que
almacena su edad.
string _NIF; // Campo de cada objeto Persona que
almacena su NIF.
using System;
using System.IO;
using System.Threading;
for(int i=0;i<10;i++){
Console.WriteLine("Escribiendo desde ==> 1″);
Thread.Sleep(1000);
for(int i=0;i<10;i++){
Thread.Sleep(1000);
th1.Start();
th2.Start();
th1.Join();
th2.Join();
La creación de cada hilo se realiza mediante las líneas Thread th1 = new Thread(new
ThreadStart(msg.Mostrar1));. Esta línea indica que se crea una instancia de la clase Thread,
con nombre th1, a partir de un delegado de la clase ThreadStart, que apunta al método
Mostrar1 del objeto msg creado anteriormente.
Una vez creados los dos hilos hay que activarlos, para lo que se llama al método Start de
cada uno de ellos. Tras este punto cada hilo se ejecuta en paralelo entre si, y con el
programa principal, por lo que utilizamos el método Join de ambos hilos para esperar a que
terminen los hilos antes de finalizar el programa.
El delegado ThreadStart no acepta parámetros de entrada ni de salida, por lo que si
queremos crear un hilo sobre un método que los necesite, hay que utilizar algún mecanismo
auxiliar. Una posible forma de conseguir esto es crear una nueva clase con los parámetros
necesarios en la entrada y con un nuevo método sin parámetros que llame al método que
queremos hacer paralelo, enviándole estos parámetros. A partir de aquí tendríamos que crear
una instancia de dicha clase con los parámetros que queremos enviar al método original, y
hacer que el hilo se ejecutase sobre el nuevo método de la clase. En el caso de que
quisiéramos obtener el resultado de la ejecución, deberíamos crear una función que acepte
como parámetro de entrada el tipo del valor devuelto por el método original, y hacer que la
nueva clase creada disponga también de un delegado que indique la función a la que llamar
tras la ejecución.
Como esto puede parecer un poco lioso, vamos a ver otro ejemplo. En esta ocasión
disponemos de una clase de funciones matemáticas y queremos llamar de forma paralela a
una de ellas. Este método acepta un valor entero en la entrada y devuelve otro entero.
using System;
using System.Threading;
using System.IO;
Thread.Sleep(5000);
return n;
protected int n;
this.n = n;
this.callback = callback;
{
int result = EjemploMates.CalculoComplejo(n);
if(callback != null)
callback(result);
th.Start();
th.Join();
C#
class TimePeriod
{
private double _seconds;
public double Seconds
{
get { return _seconds; }
set { _seconds = value; }
}
C#
class TimePeriod2
{
public double Hours { get; set; }
}
class TimePeriod
{
private double _seconds;
public double Seconds
{
get { return _seconds; }
set { _seconds = value; }
}
}
System. Object
Ahora que sabemos lo que es la herencia es el momento apropiado para explicar que en
.NET todos los tipos que se definan heredan implícitamente de la clase System.Object
predefinida en la BCL, por lo que dispondrán de todos los miembros de ésta. Por esta razón
se dice que System.Object es la raíz de la jerarquía de objetos de .NET.
A continuación vamos a explicar cuáles son estos métodos comunes a todos los objetos:
• public virtual bool Equals(object o): Se usa para comparar el objeto sobre el que se
aplica con cualquier otro que se le pase como parámetro. Devuelve true si ambos
objetos son iguales y false en caso contrario.
La implementación que por defecto se ha dado a este método consiste en usar
igualdad por referencia para los tipos por referencia e igualdad por valor para los
tipos por valor. Es decir, si los objetos a comparar son de tipos por referencia
sólo se devuelve true si ambos objetos apuntan a la misma referencia en memoria
dinámica, y si los tipos a comparar son tipos por valor sólo se devuelve true si todos
los bits de ambos objetos son iguales, aunque se almacenen en posiciones diferentes
de memoria.
Como se ve, el método ha sido definido como virtual, lo que permite que los
programadores puedan redefinirlo para indicar cuándo ha de considerarse que son
iguales dos objetos de tipos definidos por ellos. De hecho, muchos de los tipos
incluidos en la BCL cuentan con redefiniciones de este tipo, como es el caso de
string, quien aún siendo un tipo por referencia, sus objetos se consideran iguales si
apuntan a cadenas que sean iguales carácter a carácter (aunque referencien a
distintas direcciones de memoria dinámica)
El siguiente ejemplo muestra cómo hacer una redefinición de Equals() de manera que
aunque los objetos Persona sean de tipos por referencia, se considere que dos
Personas son iguales si tienen el mismo NIF:
public override bool Equals(object o)
{
if (o==null)
return this==null;
else
return (o is Persona) && (this.NIF == ((Persona) o).NIF);
}
Hay que tener en cuenta que es conveniente que toda redefinición del método
Equals() que hagamos cumpla con una serie de propiedades que muchos de los
métodos incluidos en las distintas clases de la BCL esperan que se cumplan. Estas
propiedades son:
Reflexividad: Todo objeto ha de ser igual a sí mismo. Es decir, x.Equals(x) siempre ha de
devolver true.
Simetría: Ha de dar igual el orden en que se haga la comparación. Es decir, x.Equals(y) ha
de devolver lo mismo que y.Equals(x) .
Transitividad: Si dos objetos son iguales y uno de ellos es igual a otro, entonces el primero
también ha de ser igual a ese otro objeto. Es decir, si x.Equals(y) e y.Equals(z) entonces
x.Equals(z) .
Consistencia: Siempre que el método se aplique sobre los mismos objetos ha de devolver el
mismo resultado.
Tratamiento de objetos nulos: Si uno de los objetos comparados es nulo (null), sólo se ha
de devolver true si el otro también lo es.
Hay que recalcar que el hecho de que redefinir Equals() no implica que el operador de
igualdad (==) quede también redefinido. Ello habría que hacerlo de
independientemente como se indica en el Tema 11: Redefinición de operadores.
• public virtual int GetHashCode(): Devuelve un código de dispersión (hash) que
representa de forma numérica al objeto sobre el que el método es aplicado.
GetHashCode() suele usarse para trabajar con tablas de dispersión, y se cumple que
si dos objetos son iguales sus códigos de dispersión serán iguales, mientras que si
son distintos la probabilidad de que sean iguales es ínfima.
En tanto que la búsqueda de objetos en tablas de dispersión no se realiza únicamente
usando la igualdad de objetos (método Equals()) sino usando también la igualdad de
códigos de dispersión, suele ser conveniente redefinir GetHashCode() siempre que se
redefina Equals() De hecho, si no se hace el compilador informa de la situación con un
mensaje de aviso.
• public virtual string ToString(): Devuelve una representación en forma de cadena
del objeto sobre el que se el método es aplicado, lo que es muy útil para depurar
aplicaciones ya que permite mostrar con facilidad el estado de los objetos.