sábado, 5 de abril de 2014

Constructores


Cuando se crea clase o struct, se llama al constructor. Los constructores tienen el mismo nombre que la clase o struct, e inicializan normalmente los miembros de datos del nuevo objeto.
En el ejemplo siguiente, una clase denominada Taxi se define mediante un constructor simple. Esta clase crea instancias con el operador new. El operador new invoca el constructor Taxi inmediatamente después de asignar la memoria al nuevo objeto.
C#

public class Taxi
{
    public bool isInitialized;
    public Taxi()
    {
        isInitialized = true;
    }
}

class TestTaxi
{
    static void Main()
    {
        Taxi t = new Taxi();
        Console.WriteLine(t.isInitialized);
    }
}


Un constructor que no toma ningún parámetro se denomina constructor predeterminado. Los constructores predeterminados se invocan cada vez que se crea una instancia de un objeto mediante el operador new y no se proporciona ningún argumento a new

A menos que la clase sea estática, a las clases sin constructores se les asigna un constructor público predeterminado a través del compilador de C# con el fin de habilitar la creación de instancias de clases. 
Es posible evitar que se creen instancias de una clase mediante la conversión del constructor a privado, como se muestra a continuación:
C#

class NLog
{
    // Private Constructor:
    private NLog() { }

    public static double e = Math.E;  //2.71828...
}


Los constructores para los tipos struct son similares a los constructores de clases, pero los tipos structs no pueden contener un constructor predeterminado explícito porque el compilador proporciona uno automáticamente. Este constructor inicializa cada campo del tipo struct con los valores predeterminados. 
Sin embargo, este constructor predeterminado sólo se invoca si se crean instancias del tipo struct con new. Por ejemplo, en este código se utiliza el constructor predeterminado para Int32, lo que garantiza la inicialización del tipo entero:
int i = new int();
Console.WriteLine(i);
Sin embargo, el código siguiente genera un error del compilador porque no usa new e intenta utilizar un objeto que no se ha inicializado:
int i;
Console.WriteLine(i);
Como alternativa, se pueden inicializar objetos basados en structs (incluidos todos los tipos numéricos integrados) o asignarse y, a continuación, utilizarse como en el ejemplo siguiente:
int a = 44;  // Initialize the value type...
int b;
b = 33;      // Or assign it before using it.
Console.WriteLine("{0}, {1}", a, b);
En consecuencia no se requiere llamar al constructor predeterminado para un tipo de valor.
Tanto las clases como las structs pueden definir constructores que acepten parámetros. Se debe llamar a constructores que toman parámetros a través de una instrucción new o base. Las clases y las structs también pueden definir varios constructores y no se requiere ninguno para definir un constructor predeterminado. Por ejemplo:
C#

public class Employee
{
    public int salary;

    public Employee(int annualSalary)
    {
        salary = annualSalary;
    }

    public Employee(int weeklySalary, int numberOfWeeks)
    {
        salary = weeklySalary * numberOfWeeks;
    }
}


Esta clase se puede crear mediante cualquiera de las siguientes instrucciones:
C#

Employee e1 = new Employee(30000);
Employee e2 = new Employee(500, 52);


Cualquier constructor puede utilizar la palabra clave base para llamar al constructor de una clase base. Por ejemplo:
C#

public class Manager : Employee
{
    public Manager(int annualSalary)
        : base(annualSalary)
    {
        //Add further instructions here.
    }
}


En este ejemplo, se llama al constructor de la clase base antes de ejecutar el bloque del constructor. La palabra clave base se puede utilizar con o sin parámetros. Cualquier parámetro del constructor se puede utilizar como parámetro de base o como parte de una expresión.  En una clase derivada, si no se llama explícitamente al constructor de la clase base mediante la palabra clave base, se llamará implícitamente al constructor predeterminado, si existe alguno. Esto significa que las siguientes declaraciones del constructor son efectivamente las mismas:
C#

public Manager(int initialdata)
{
    //Add further instructions here.
}


C#

public Manager(int initialdata)
    : base()
{
    //Add further instructions here.
}


Si una clase base no proporciona un constructor predeterminado, la clase derivada debe realizar una llamada explícita a un constructor base mediante base.
Un constructor puede invocar a otro constructor en el mismo objeto mediante la palabra clave this. Al igual quebasethis se puede utilizar con o sin parámetros y cualquier parámetro en el constructor está disponible como parámetro para this o como parte de una expresión. Por ejemplo, el segundo constructor del ejemplo anterior se puede rescribir con this:
C#

public Employee(int weeklySalary, int numberOfWeeks)
    : this(weeklySalary * numberOfWeeks)
{
}

El uso de la palabra clave this en el ejemplo anterior hace que se llame a este constructor:
C#

public Employee(int annualSalary)
{
    salary = annualSalary;
}


Los constructores se pueden marcar: 

como publicprivateprotectedinternal o protectedinternal
Estos modificadores de acceso definen cómo los usuarios de la clase pueden construir la clase. 
 Un constructor se puede declarar como estático mediante la palabra clave staticSe llama automáticamente a los constructores estáticos de forma inmediata antes de que se tenga acceso a cualquier campo estático, y, generalmente, se utilizan para inicializar los miembros de clase estáticos. 

Como definir propiedades

 Las propiedades combinan aspectos de los campos y de los métodos. Para el usuario de un objeto, una propiedad es similar a un campo, el acceso a la propiedad requiere la misma sintaxis. Para el implementador de una clase, una propiedad es uno o dos bloques de código que representan un descriptor de acceso get y un descriptor de accesoset. El bloque de código para el descriptor de acceso get se ejecuta cuando se lee la propiedad; el bloque de código para el descriptor de acceso set se ejecuta cuando se asigna un nuevo valor a la propiedad. Una propiedad sin un descriptor de acceso set se considera de sólo lectura. Una propiedad sin un descriptor de acceso get se considera de sólo escritura. Una propiedad con ambos descriptores de acceso es de lectura y escritura.
A diferencia de los campos, las propiedades no están clasificadas como variables. Por lo tanto, no se puede pasar una propiedad como un parámetro ref (Referencia de C#) o out (Referencia de C#).
Las propiedades tienen muchos usos:

Validan datos antes de permitir un cambio; exponen datos de forma transparente en una clase donde se recuperan realmente los datos de otro origen, como una base de datos; realizan una acción cuando se modifican datos, por ejemplo, provocar un evento, o cambian el valor de otros campos.
Las propiedades se declaran en el bloque de clase especificando el nivel de acceso del campo, seguido por el tipo de la propiedad, por el nombre de la propiedad y por un bloque de código que declara un descriptor de accesoget y/o un descriptor de acceso set. Por ejemplo:
C#

public class Date
{
    private int month = 7;  // Backing store

    public int Month
    {
        get
        {
            return month;
        }
        set
        {
            if ((value > 0) && (value < 13))
            {
                month = value;
            }
        }
    }
}


En este ejemplo, Month se declara como una propiedad para que el descriptor de acceso set pueda asegurarse de que Month se establezca en un valor comprendido entre 1 y 12. La propiedad Month utiliza un campo privado para realizar el seguimiento del valor real. La ubicación real de los datos de una propiedad suele conocerse como "memoria auxiliar" de la propiedad. Es normal que las propiedades utilicen campos privados como memoria auxiliar. El campo se marca como privado para asegurarse de que sólo puede cambiarse llamando a la propiedad.
Las propiedades autoimplementadas ofrecen una sintaxis simplificada para las declaraciones de propiedades simples. 


El cuerpo del descriptor de acceso get se parece al de un método. Debe devolver el valor del tipo de la propiedad. La ejecución del descriptor de acceso get equivale a leer el valor del campo. Por ejemplo, cuando se devuelve la variable privada del descriptor de acceso get y las optimizaciones están habilitadas, el compilador pone la llamada al método del descriptor de acceso get entre líneas para que no se produzca una sobrecarga de método-llamada. Sin embargo, un método de descriptor de acceso get virtual no se puede poner entre líneas, porque el compilador no sabe en tiempo de compilación qué método puede llamarse en tiempo de ejecución. A continuación, se muestra un descriptor de acceso get que devuelve el valor de un campo privado name:
C#

class Person
{
    private string name;  // the name field
    public string Name    // the Name property
    {
        get
        {
            return name;
        }
    }
}


Cuando se haga referencia a la propiedad, se llamará al descriptor de acceso get para leer el valor de la misma, salvo en el caso de que la referencia se haga como el destino de una asignación. Por ejemplo:
C#

Person person = new Person();
//...

System.Console.Write(person.Name);  // the get accessor is invoked here


El descriptor de acceso get debe terminar en una instrucción return o throw, y el control no puede salir del cuerpo del descriptor de acceso.
Cambiar el estado de un objeto mediante el descriptor de acceso get es una técnica de programación poco recomendable. Por ejemplo, el siguiente descriptor de acceso cambia, como efecto secundario, el estado del objeto cada vez que se obtiene acceso al campo number.
C#

private int number;
public int Number
{
    get
    {
        return number++;   // Don't do this
    }
}


Se puede utilizar el descriptor de acceso get para devolver el valor de un campo o para calcularlo y devolverlo.Por ejemplo:
C#

class Employee
{
    private string name;
    public string Name
    {
        get
        {
            return name != null ? name : "NA";
        }
    }
}


El segmento de código anterior devolverá el valor NA si no se asigna ningún valor a la propiedad Name.


El descriptor de acceso set es similar a un método cuyo tipo de valor devuelto es void. Utiliza un parámetro implícito denominado value, que tiene el mismo tipo que la propiedad. En el siguiente ejemplo se agrega un descriptor de acceso set a la propiedad Name:
C#

class Person
{
    private string name;  // the name field
    public string Name    // the Name property
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }
}


Cuando se asigne un valor a la propiedad, se llamará al descriptor de acceso set utilizando un argumento que proporcione el nuevo valor. Por ejemplo:
C#

Person person = new Person();
person.Name = "Joe"// the set accessor is invoked here               

System.Console.Write(person.Name);  // the get accessor is invoked here


No es correcto utilizar el nombre de parámetro implícito, value, para una declaración de variable local en un descriptor de acceso set.

Colección de LIST

Representa una lista de objetos fuertemente tipados a la que se puede obtener acceso por índice. Proporciona métodos para buscar, ordenar y manipular listas.
Inicializa una nueva instancia de la clase List<T>.
Este miembro está sobrecargado. Para obtener información completa sobre este miembro, incluida la sintaxis, el uso y algunos ejemplos, haga clic en un nombre de la lista de sobrecarga.



Nombre
Descripción
Descripción: Método público
Inicializa una nueva instancia de la clase List<T> que está vacía y tiene la capacidad inicial predeterminada.
Descripción: Método público
Inicializa una nueva instancia de la clase List<T> que contiene elementos copiados de la colección especificada y tiene una capacidad suficiente para aceptar el número de elementos copiados.
Descripción: Método público
Inicializa una nueva instancia de la clase List<T> que está vacía y tiene la capacidad inicial especificada.

Inicializa una nueva instancia de la clase List<T> 

Que está vacía y tiene la capacidad inicial predeterminada.List<T> (Constructor)

public List()
El ejemplo agrega, inserta, y quita los elementos, mostrando cómo cambia la capacidad como estos métodos se utilizan.
C#

using System;
using System.Collections.Generic;

public class Example
{
    public static void Main()
    {
        List<string> dinosaurs = new List<string>();

        Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);

        dinosaurs.Add("Tyrannosaurus");
        dinosaurs.Add("Amargasaurus");
        dinosaurs.Add("Mamenchisaurus");
        dinosaurs.Add("Deinonychus");
        dinosaurs.Add("Compsognathus");

        Console.WriteLine();
        foreach(string dinosaur in dinosaurs)
        {
            Console.WriteLine(dinosaur);
        }

        Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);
        Console.WriteLine("Count: {0}", dinosaurs.Count);

        Console.WriteLine("\nContains(\"Deinonychus\"): {0}",
            dinosaurs.Contains("Deinonychus"));

        Console.WriteLine("\nInsert(2, \"Compsognathus\")");
        dinosaurs.Insert(2, "Compsognathus");

        Console.WriteLine();
        foreach(string dinosaur in dinosaurs)
        {
            Console.WriteLine(dinosaur);
        }

        Console.WriteLine("\ndinosaurs[3]: {0}", dinosaurs[3]);

        Console.WriteLine("\nRemove(\"Compsognathus\")");
        dinosaurs.Remove("Compsognathus");

        Console.WriteLine();
        foreach(string dinosaur in dinosaurs)
        {
            Console.WriteLine(dinosaur);
        }

        dinosaurs.TrimExcess();
        Console.WriteLine("\nTrimExcess()");
        Console.WriteLine("Capacity: {0}", dinosaurs.Capacity);
        Console.WriteLine("Count: {0}", dinosaurs.Count);

        dinosaurs.Clear();
        Console.WriteLine("\nClear()");
        Console.WriteLine("Capacity: {0}", dinosaurs.Capacity);
        Console.WriteLine("Count: {0}", dinosaurs.Count);
    }
}

List<T> (Clase)

Representa una lista de objetos fuertemente tipados a la que se puede obtener acceso por índice. Proporciona métodos para buscar, ordenar y manipular listas.
[SerializableAttribute]
public class List<T> : IList<T>, ICollection<T>, 
        IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, 
        IEnumerable

List<T> (Constructor) (IEnumerable<T>)
Inicializa una nueva instancia de la clase List<T> que contiene elementos copiados de la colección especificada y tiene una capacidad suficiente para aceptar el número de elementos copiados.
public List(
        IEnumerable<T> collection
)
El ejemplo siguiente se muestra el constructor de List<T> y los diversos métodos de la clase de List<T> que actúan en intervalos. Se crea una matriz de cadenas y se pasa al constructor, rellenando la lista con los elementos de la matriz. A continuación, se muestra la propiedad Capacity para mostrar que la capacidad inicial es exactamente la necesaria para contener los elementos de entrada.
using System;
using System.Collections.Generic;
 
public class Example
{
    public static void Main()
    {
        string[] input = { "Brachiosaurus", 
                           "Amargasaurus", 
                           "Mamenchisaurus" };
 
        List<string> dinosaurs = new List<string>(input);
 
        Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);
 
        Console.WriteLine();
        foreach( string dinosaur in dinosaurs )
        {
            Console.WriteLine(dinosaur);
        }
 
        Console.WriteLine("\nAddRange(dinosaurs)");
        dinosaurs.AddRange(dinosaurs);
 
        Console.WriteLine();
        foreach( string dinosaur in dinosaurs )
        {
            Console.WriteLine(dinosaur);
        }
 
        Console.WriteLine("\nRemoveRange(2, 2)");
        dinosaurs.RemoveRange(2, 2);
 
        Console.WriteLine();
        foreach( string dinosaur in dinosaurs )
        {
            Console.WriteLine(dinosaur);
        }
 
        input = new string[] { "Tyrannosaurus", 
                               "Deinonychus", 
                               "Velociraptor"};
 
        Console.WriteLine("\nInsertRange(3, input)");
        dinosaurs.InsertRange(3, input);
 
        Console.WriteLine();
        foreach( string dinosaur in dinosaurs )
        {
            Console.WriteLine(dinosaur);
        }
 
        Console.WriteLine("\noutput = dinosaurs.GetRange(2, 3).ToArray()");
        string[] output = dinosaurs.GetRange(2, 3).ToArray();
 
        Console.WriteLine();
        foreach( string dinosaur in output )
        {
            Console.WriteLine(dinosaur);
        }
    }
}


List<T> (Constructor) (Int32)

Inicializa una nueva instancia de la clase List<T> que está vacía y tiene la capacidad inicial especificada.
public List(
        int capacity
)
 
En el ejemplo siguiente se muestra el constructor List<T>(Int32). Se crea List<T> de cadenas con una capacidad de 4, puesto que se sabe que el tamaño final de la lista será exactamente 4. La lista se rellena con cuatro cadenas y se crea una copia de sólo lectura utilizando el método AsReadOnly.
C#

using System;
using System.Collections.Generic;

public class Example
{
    public static void Main()
    {
        List<string> dinosaurs = new List<string>(4);

        Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);

        dinosaurs.Add("Tyrannosaurus");
        dinosaurs.Add("Amargasaurus");
        dinosaurs.Add("Mamenchisaurus");
        dinosaurs.Add("Deinonychus");

        Console.WriteLine();
        foreach(string s in dinosaurs)
        {
            Console.WriteLine(s);
        }

        Console.WriteLine("\nIList<string> roDinosaurs = dinosaurs.AsReadOnly()");
        IList<string> roDinosaurs = dinosaurs.AsReadOnly();

        Console.WriteLine("\nElements in the read-only IList:");
        foreach(string dinosaur in roDinosaurs)
        {
            Console.WriteLine(dinosaur);
        }

        Console.WriteLine("\ndinosaurs[2] = \"Coelophysis\"");
        dinosaurs[2] = "Coelophysis";

        Console.WriteLine("\nElements in the read-only IList:");
        foreach(string dinosaur in roDinosaurs)
        {
            Console.WriteLine(dinosaur);
        }
    }
}

No hay comentarios:

Publicar un comentario