Herramientas de usuario

Herramientas del sitio


highlevel:csharp

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
highlevel:csharp [2008/12/24 19:00]
alfred
highlevel:csharp [2020/05/09 09:25] (actual)
Línea 27: Línea 27:
 VariableChar = (char)VariableInt;​ VariableChar = (char)VariableInt;​
 </​code>​ </​code>​
 +
 +
 ==== Trabajar con strings ==== ==== Trabajar con strings ====
 Si en medio de una cadena ponemos estos carácteres de escape.... Si en medio de una cadena ponemos estos carácteres de escape....
Línea 55: Línea 57:
 string b = System.String.Format("​La variable a, es: {0}", a.ToString());​ string b = System.String.Format("​La variable a, es: {0}", a.ToString());​
 </​code>​ </​code>​
 +
 +Otros Métodos:
 +  * ''​Replace''​ Éste método recibe como parámetros dos strings, y devuelve uno. Lo que hace es coger el string con el que se ha llamado este método y se le pasa una cadena que es la que sustituirá por la segunda en todo el string y el nuevo estring ya sustituido es el que devuelve.
 +  * ''​Split''​ Se le pasa un char o un vector de chars (por lo tanto irá entre comillas simples, no dobles), ​ y devuelve un vector de strings. Lo que hace es coger el string donde se ha invocado a este método y corta (hacia la derecha) y el resultado lo guarda en un array de strings que será lo que devuelva.
 +
 +
  
  
Línea 106: Línea 114:
 Si un archivo fuese arrastrado con el mouse, desde windows al ejecutable habrá un argumento, éste será la ruta completa del archivo arrastrado. 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 ​=====+ 
 +===== Programación Orientada a Objetos ​===== 
 ==== Variables y métodos estáticos y constantes ==== ==== 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. \\ 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. \\
Línea 277: Línea 287:
  
 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() { ... }''​ 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 ==== ==== Ámbito de una variable según su declaración ====
Línea 283: Línea 294:
   * **protected**:​ Visibles en la clase donde se definen y en las derivadas.   * **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.   * **internal**:​ Sólo visibles dentro del archivo binario (compilado) donde se han declarado.
-  * **protected internal**: +  * **protected internal**: Una clase pública podrá verse desde otro archivo, si no lo es no.
-Una clase pública podrá verse desde otro archivo, si no lo es no.+
  
 ==== Object en .NET ==== ==== Object en .NET ====
Línea 318: Línea 328:
 } }
 </​code>​ </​code>​
 +
  
 ==== Control de excepciones ==== ==== Control de excepciones ====
Línea 331: Línea 342:
 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: 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...   * OutOfMemoryException,​ StackOverflowException,​ IndexOutOfRangeException...
-También puede declarar sus propias excepciones o lanzar excepciones simples, de la aplicación,​ haciendo un ''​new ApplicationException''​.+También puede declarar sus propias excepciones o lanzar excepciones simples, de la aplicación,​ haciendo un ''​new ApplicationException''​. ​\\  
 +Para lanzar una excepción:​ 
 +<code csharp>​ 
 +throw new ApplicationException();​ 
 +</​code>​ 
 + 
 + 
  
 ==== Espacios de nombre (namespaces) ==== ==== Espacios de nombre (namespaces) ====
Línea 355: Línea 373:
 } }
 </​code>​ </​code>​
 +=== Otros usos de using ===
 +Podemos declarar un termino que englobe namespaces:
 +<code csharp>
 +using Terminal = System.Console;​
 +...
 +Terminal.WriteLine("​Hola!"​);​
 +</​code>​
 +=== using como instrucción ===
 +Podemos usar el comando using para crear una variable por un corto perido de tiempo. Cuando hacemos:
 +<code csharp>
 +using (Form frm = new Form()) {
 +...
 +}
 +</​code>​
 +Dentro podemos usar frm como una variable normal. Al salir de este se le llamará al método ''​IDisposable''​.
  
 ==== Enumeraciones ==== ==== Enumeraciones ====
Línea 401: Línea 434:
 } }
 </​code>​ </​code>​
 +
 +
  
 ==== Interfaces ==== ==== Interfaces ====
Línea 432: Línea 467:
 Para crear una propiedad debemos definir si aceptará get o set: ''​int r { get; set; }''​ \\  Para crear una propiedad debemos definir si aceptará get o set: ''​int r { get; set; }''​ \\ 
 Una interface puede heredar de varias interfaces. Una interface puede heredar de varias interfaces.
 +==== Dispose y Destructores ====
 +
 +=== Interfaz IDispose ===
 +Al crear una clase que implemente esta interfaz se le añadirá el método "​Dispose",​ éste método es llamado cuando el recolector de basura elimina el objeto y, por lo tanto, este método debería de eliminar de memoria otros objetos que este contenga.
 +
 +=== Método Dispose ===
 +Un método Dispose ha de eliminar todos los objetos que tiene, llamando así, a su vez a sus métodos Dispose. Es importante que un método Dispose pueda ser llamado varias veces sin que provoque ningua excepción. Al llevar un parámetro bool, éste nos sirve para indicar si ha sido llamado por el sistema o por nosotros.
 +
 +=== Destructores ===
 +En .NET si quisiesemos que el recolector de basura hiciese algo justo al eliminar un objeto, deberíamos sobreescribir en este el método Finalize, excepto en C#  que tiene su propia sintaxis de destructor. El uso indebido de estos destructores puede ser perjudicial para el programa, ya que el recolector de basura va sondeando los objetos para eliminarlos y si cuando se van a eliminar aun no se ha lanzado el método finalize lo pone en una cola de objetos que lo han de llamar, por lo que el objeto estaría más tiempo rondando en memoria. \\ 
 +El método Finalize debería ser protected, no deberíamos de dar acceso a él a código de fuera de la clase donde esté, y debería usarse como última instancia, ya que es preferible. \\ 
 +En C# no podemos llamar a Finalize, pero sí crear un destructor así:
 +<code csharp>
 +~nombreClase { ... }
 +</​code>​
 +
 +===== Conceptos del lenguaje =====
 +==== Archivos ====
 +Para usar archivos debemos incluir (con using) ''​System.IO''​. ​ \\ 
 +Antes de nada necesitaremos un objeto ''​FileStream''​. Crearemos uno nuevo, los parámetros del constructor son:
 +  - String dirección del archivo.
 +  - El modo de fichero. ''​FileMode.<​modo>'',​ los modos son:
 +    * ''​Create'':​ Creará uno nuevo, si existe lo sobreescribirá.
 +    * ''​Open'':​ Abrirá el fichero, debe existir.
 +    * ''​OpenOrCreate'':​ Si no existe lo creará.
 +    * ''​Truncate'':​ El archivo debe existir, será borrado su contenido.
 +  - La forma de acceso al fichero. ''​FileAccess.<​modo>'',​ los modos son:
 +    * ''​Read'':​ Leer.
 +    * ''​ReadWrite'':​ Leer y escribir.
 +    * ''​Write'':​ Escribir.
 +Luego crearemos un ''​BinaryReader''​ o ''​BinaryWriter''​ si lo que queremos es leer o escribir, el parámetro que espera recibir es el FileStream antes creado. Una vez acabemos las operaciones que hayamos hecho deberemos cerrar tanto el BinaryReader o Writer y el FileStream con su método ''​.Close()''​.
 +<code csharp> ​
 +FileStream FS = new 
 +FileStream(Text2.Text,​ FileMode.OpenOrCreate,​ FileAccess.ReadWrite);​
 +BinaryWriter BW = new BinaryWriter(FS);​
 +BW.Write(Text1.Text);​
 +BW.Close();
 +FS.Close();
 +FileStream FS = new FileStream(Text2.Text,​ FileMode.Open,​ FileAccess.Read);​
 +BinaryReader BR = new BinaryReader(FS);​
 +Text1.Text = BR.ReadString();​
 +BR.Close();
 +FS.Close();​  ​
 +</​code>​
 +Podemos posicionarnos en cualquier lugar del archivo (o del FileStream) mediante el método Seek. Mediante vamos leyendo o escribiendo en un archivo el puntero del archivo va abanzando. ​
 +  * Si queremos ir al principio haremos: ''<​objeto filestream>​.Seek (0, SeekOrigin.Begin);''​
 +  * Ir al cuarto primer byte: ''<​objeto filestream>​.Seek (4, SeekOrigin.Begin);''​
 +  * Al penultimo byte: ''<​objeto filestream>​.Seek (-2, SeekOrigin.End);''​
 +  * Al enterior respecto a la posición del puntero donde tamos: ''<​objeto filestream>​.Seek (-1, SeekOrigin.Current);''​
 +Ya que la enumeración SeekOrigin admite estos cuatro elementos.
 +
 +
 +==== Conversiones ====
 +  * A integer: ''​variable int  = System.Convert.ToInt16 (variable);''​
 +  * A IP: ''​System.Net.IPAddress var = System.Net.IPAddress.Parse(var string);''​
 +
 +==== Operador as ====
 +Es un molde para la conversión de tipos, pero si existe un error en la conversión,​ proporciona el valor null en vez de producir una excepción. Más formalmente,​ una expresión de la forma: ''​expression as type'',​ que equivale a: ''​expression is type ? (type)expression : (type)null''​
 +
 +
 +
 +==== Delegados ====
 +Un delegado permite al programador encapsular un método dentro de un objeto delegado. Lo que significa que un delegado sería una especie de variable que contiene una “función”. El delegado se usa como si fuese un tipo de datos, y su declaración se hace de la siguiente manera: \\ 
 +''<​tipo de variable (pública, privada…)>​ delegate <lo que devuelve>​ nombre <lo que recibe>​.''​ \\ 
 +
 +Imaginemos un espacio de nombres y declaramos un delegado:
 +<code csharp>
 +public delegate void Callback (string s);
 +</​code>​
 +Este delegado no devuelve nada pero recibe un string, sólo podremos asignarlo a una función con estas mismas características. Imaginemos esta:
 +<code csharp>
 +private static void WriteResult (string s) {
 + Console.WriteLine(s);​
 +}
 +</​code>​
 +Para asignarlo se hace como si fuese un objeto con el nombre del delegado pero que se le pasa un parámetro que es el nombre de la función:
 +<code csharp>
 +Callback WR = new Callback(WriteResult);​
 +</​code>​
 +Imaginemos que el programador realiza una función que recoge todos los objetos de una lista, si estos objetos tienen un color igual al color indicado se llamará a una función que realizará la rutina correspondiente,​ el programador no tiene por qué tener ni idea de lo que hace esta rutina, sólo ha de saber que se le pasa un string y que no devuelve nada (que es una función del tipo “callback”):​
 +<code csharp>
 +public void SearchData(string SearchColor,​ Callback Proc) {
 + foreach (Objeto obj in this.Lista) {
 + if (obj.Color == SearchColor) {
 + Proc(obj.Name);​
 + }
 + }
 +}
 +</​code>​
 +Para llamar a esta última función, como vemos debemos pasarle un string y un Callback, es decir, el color y el Callback antes definido: ​
 +<code csharp>
 +D.SearchData("​Negro",​WR);​
 +</​code>​
 +También podemos sumar y restar delegados. Esto es, al sumar un delegado, que se llame una función y luego a otra, al restar, quitamos de un delegado una función sumada. \\ 
 +Por ejemplo imaginemos que tenemos dos funciones ''​Hola''​ y ''​Adios'',​ las dos no devuelven nada pero reciben un string. Lo que hacen es decir “Hola + string”, o “Adios + string”. Vamos a imaginar que tenemos un delegado para estas. \\ 
 +Declaramos cuatro delegados de los nuestros: a, b, c y d. ''​a = new Delegado (Hola), b = new Delegado (Adios), c = a + b, d = c – a.''​ \\ 
 +Luego llamamos a los delegados: a(“A”), b(“B”), c(“C”), d(“D”). \\ 
 +Esto nos devolverá:
 +<​code>​
 +El a: Hola A.
 +El b: Adios B.
 +El c: Hola C. Adios C.
 +El d: Adios D.
 +</​code>​
 +
 +
 +==== Añadir un nuevo evento a una clase ====
 +Lo primero que debemos hacer es declarar un delegado, este parece ser una platilla para los eventos. Lo hemos puesto como global dentro del espacio de nombres “Project2”:​ public delegate void <​nombre>​ ( <​parámetros>​ ). Dentro de la definición de la clase donde añadiremos este evento lo definimos como tal, public event <nombre del delegado>​ <nombre del evento>. A partir de ahora, cuando llamemos a este “evento” desde esta clase debemos hacerlo como si de una función se tratase, pero con los parámetros indicados al delegado. Aún así debemos indicar en algún lugar que función corresponde a ese evento, es decir, la que se ejecutará cuando se llame a este.
 +<code csharp>
 +namespace Project2 {
 + public delegate void EvNumPar (object Originador, int Num);
 + class Motor {
 + public event EvNumPar DarNumero;
 + public void Ejecuta() {
 + for (int i = 0; i <= 100; i++) {
 + if (DarNumero != null)
 + DarNumero(this,​ i);
 + }
 + }
 + }
 + class MainClass {
 + public static void NumPar (object Originador, int Num) {
 + if (Num % 2 == 0)
 + Console.WriteLine("​Número Par {0} ", Num);
 + }
 + public static void Main () {
 + Motor motor = new Motor();
 + motor.DarNumero += new EvNumPar(NumPar);​
 + motor.Ejecuta();​
 + Console.ReadLine();​
 + }
 + }
 +}
 +</​code>​
 +.NET Framework, en sus eventos, indica que l delegado para un evento debe aceptar dos parámetros:​ el orígen del objeto y la información adicional: (object sender, EventArgs e). Este no ha de devolver nada. \\ 
 +Podemos quitar delegados del evento con el operador -=. \\ 
 +En el siguiente código vemos una clase que hereda de la clase ArrayList, ésta tiene un evento llamado “Adding” que al añadir un objeto es llamado (mediante la función onAdding añadida en el método Add) si este evento apunta a alguna función, es decir, que no es nula.
 +<code csharp>
 +namespace Eventos {
 + using System.Collections;​
 + class Lista : ArrayList {
 + public event EventHandler Adding;
 + protected virtual void OnAdding (EventArgs e) {
 + if (Adding != null)
 + Adding(this,​ e);
 + }
 + public override int Add(object value) {
 + int i = base.Add(value);​
 + OnAdding(EventArgs.Empty);​
 + return i;
 + }
 + }
 +}
 +namespace Prueba {
 + using Eventos;
 + class MainClass {
 + static Eventos.Lista list;
 + static void Muestra () {
 + foreach (object obj in list) 
 + Console.WriteLine(obj.ToString());​
 + }
 + static void List1_Change(object sender, EventArgs e) {
 + Console.WriteLine("​\tSe ha llamado al método Change"​);​
 + }
 + public static void Main () {
 + list = new Lista();
 + list.Adding += new EventHandler(List1_Change);​
 + list.Add("​perro"​);​
 + list.Add("​gato"​);​
 + Muestra();​
 + Console.ReadLine();​
 + }
 + }
 +}
 +</​code>​
 +
 +==== Referencias y valores ====
 +Cuando se crea un objeto de una clase (''​obj = new cls()''​),​ realmente este lo que hace es crear un espacio reservado en memoria para una estructura de datos (no me refiero a una struct) que corresponda a la clase y convierte la "​variable"​ que representa ese objeto en una especie de puntero en memoria a él, por lo que cuando hacemos una igualación de objetos (''​cls obj1 = obj''​) esta es otro puntero al mismo espacio de memoria. Por lo que si varía una varía la otra. \\ 
 +Por lo que si hacemos una asignación así: B = A; y luego B = C;, B y C harían referencia a un mismo objeto y A a otro.
 +Para trabajar con tipos de valores, que si hacemos una igualación el valor se iguala pero si cambia uno no cambia el otro debemos de trabajar con estructuras. \\ 
 +Trabajar por referencias nos permite pasar, por ejemplo, un objeto en un evento para que sea manipulado y luego, al finalizar el evento, realizar las acciones adecuadas según lo que se haya tocado.
 +
 +==== Atributos ====
 +Los atributos se añaden a la declaración de una porción de código y complementan a esta, se pueden aplicar a un ensamblado, un módulo, una clase, estructura, enumeración,​ constructor,​ método, campo, bla bla bla…. Los encontramos antes de cada uno de estos elementos entre corchetes. \\ 
 +Un ejemplo sería el atributo ''​obsolete'',​ a éste se le pasa un string y un bool. El bool indicará si el compilador encontrará un waring (false) o un error (true). Y el string la explicación que dará.
 +<code csharp>
 +[Obsolete("​Este método está obsoleto",​ true)]
 +static void Antiguo () {}
 +</​code>​
 +
 +En verdad el atributo ''​Obsole''​ se llama ''​ObsoleteAttribute'',​ y el compilador de C# lo primero que hará será buscar en sus referencias un atributo llamado ‘Obsolete’,​ si no lo encontrase añadiría a Obsolete (o el atributo en cuestión) la palabra Attribute y la volvería a buscar. \\ 
 +Para crear un atributo, debemos crear una clase que herede de ''​System.Attribute'',​ a partir de ahí ya tenemos nuestro nuevo atributo llamado como la clase. \\ 
 +Para definir que código puede acceder a nuestro atributo añadiremos a este un atributo en la definición de la clase, este es ''​AttributeUsage''​ y recibe miembros de una enumeración llamada ''​AttributeTargets''​ que incluye todo el tipo de código al que es aplicable un atributo en general. Por ejemplo [''​AttributeUsage(AttributeTargets.Class)''​] haría que ese atributo sólo fuese aplicable a clases. Podemos indicar más código accesible mediante el operador OR ( | ). \\ 
 +Un código puede recibir un atributo repetidas veces, por lo que el código recibiría varios valores, por defecto esto no está permitido, pero si el atributo AttributeUsage también recibe como parámetro ''​AllowMultiple=true''​ lo permitirá. Esto…
 +<code csharp>
 +[AttributeUsage(AttributeTargets.Method,​ AllowMultiple = true)]
 +class HelpAttribute : System.Attribute
 +</​code>​
 +... permite esto….
 +<code csharp>
 +[Help("​Este me mola"​)]
 +[Help("​Este no me mola"​)]
 +static void Antiguo ()
 +</​code>​
 +Si una clase hereda de otra clase, esta última clase contendrá los atributos de su clase base?? La respuesta es sí si el parámetro Inherit de AtributeUsage es true, si es false no heredará. \\ 
 +No haremos que el atributo reciba más de un parámetro en el constructor (ya que los parámetros los indicamos en el constructor),​ sino mediante propiedades. Por ejemplo en un constructor podríamos inicializar las propiedades del atributo, pero estas (si son públicas), serán sobrescritas si el programador las define:
 +<code csharp>
 +class HelpAttribute : System.Attribute {
 + protected string Descripcion;​
 + public string Uso;
 + public HelpAttribute (string Explicacion) {
 + this.Descripcion = Explicacion;​
 + this.Uso = "​nulo";​
 + }
 +}
 +</​code>​
 +Con este atributo, si al usarlo hacemos: [Help(“mola”)] quedará Description como: “mola” y Uso como “nulo”. Pero si hiciesemos: [Help(“mola”,​ Uso=”muy útil”)] quedará Description como: “mola” y Uso como “muy útil”. \\ 
 +Antes de incluir el atributo al código podemos indicar que ese atributo es para ese código en concreto, es decir, podemos asignar un atributo al valor devuelto, pero este atributo lo incluimos sobre el método, cómo indicamos? Pues podemos poner unos “identificadores” delante del atributo, estos dirán a qué influyen: assembly, module, type, method, return, param…. Ej: [method:​Help(“mola”)].
 +
 +
 +
 +==== Punteros ====
 +El uso de punteros en C# es código no seguro, y para usar éste código debemos indicar al compilador que use una compilación específica:​ Proyecto -> Propiedades -> Generar -> Permitir bloques de código no seguro. Además deberemos incluir en la declaración de la función la palara unsafe. \\ 
 +El uso de punteros es muy parecido al de C/C++:
 +<code csharp>
 +public static unsafe void Main () {
 + int AInteger = 123;
 + int *Puntero = &​AInteger;​
 + Console.WriteLine(*Puntero);​
 + *Puntero = 150;
 + Console.WriteLine(AInteger);​
 + Console.ReadLine();​
 +}
 +</​code>​
 +Usamos ''​*<​variable puntero>''​ para declarar y acceder a un puntero, y ''&<​variable>''​ para acceder a una variable no puntero. El código anterior devolverá los valores 123 y 150. \\ 
 +
 +Para acceder a las propiedades de una estructura, ya que a un objeto no podemos hacerle punteros ( ¬_¬ …ya…), hacemos un puntero del tipo de la estructura y luego asignamos al puntero la variable de la estructura con un & delante. Ahora, para acceder a sus propiedades usaremos: guión y mayor: ''<​nowiki>​-></​nowiki>''​ \\ 
 +Para hacer un puntero a un array primero deberemos reservar espacio en memoria con stackalloc y el tipo:
 +<code csharp>
 +int[] Array = {1,​2,​3,​4,​5};​
 +int * puntero = stackalloc int [5];
 +for (int i = 0; i < 5; i++)
 + puntero[i] = Array[i];
 +</​code>​
 +Puede ser que C# mueva de la memoria alguna variable, y por tanto un puntero a esa variable se volvería inservible y hasta erroneo. Para asegurarnos de que esto no ocurre usaremos fixed:
 +<code csharp>
 +int[] Array = {1,​2,​3,​4,​5};​
 +fixed(int *puntero = Array) {
 + for (int i = 0; i < 5; i++)
 + puntero[i] = i;
 +}
 +</​code>​
 +De esta forma, aunque la variable puntero no exista, Array no será movida. \\ 
 +Podemos saber el tamaño de una variable con el operador ''​sizeof(<​tipo>​)''​.
 +
 +
 +
 +===== Notas =====
 +  * Una nueva línea al escribir texto se consigue con: ''​Environment.NewLine'' ​
 +
 +==== Tips ====
 +  * Crear un objeto de un solo uso: ''​new Thread(new ThreadStart(Thread2)).Start();''​
 +  * Asignar a un bool una expresión: ''​bool bPar = (iNum % 2 == 0);''​
 +  * Definir dos objetos del mismo tipo: ''​Image tal = image.fromfile("​asjdf"​),​ tal2 = image.fromfile("​sakfjdl"​);''​
 +
highlevel/csharp.1230145234.txt.gz · Última modificación: 2020/05/09 09:24 (editor externo)