Objetos (Guía de programación de C#)

Actualización: noviembre 2007

Una definición de clase o estructura es como un plano que especifica qué puede hacer el tipo. Un objeto es básicamente un bloque de memoria que se ha asignado y configurado en función del plano. Un programa puede crear muchos objetos de la misma clase. Los objetos también se denominan instancias y se pueden almacenar en una variable con nombre o en una matriz o colección. El código cliente es el código que utiliza estas variables para llamar a los métodos y obtener acceso a las propiedades públicas del objeto. En un lenguaje orientado a objetos como C#, un programa típico se compone de varios objetos que interactúan dinámicamente.

Nota:

Los tipos estáticos se comportan de manera diferente a la que se describe aquí. Para obtener más información, vea Clases estáticas y sus miembros (Guía de programación de C#).

Instancias de estructura frente a instancias de clase

Dado que las clases son tipos de referencia, una variable de un objeto de clase contiene una referencia a la dirección del objeto en el montón administrado. Si un segundo objeto del mismo tipo se asigna al primer objeto, ambas variables hacen referencia al objeto en esa dirección. Este punto se analiza con más detalle más adelante, en este mismo tema.

Las instancias de clases se crean utilizando el operador new. En el ejemplo siguiente, Person es el tipo y person1 y person 2 son instancias, u objetos, de ese tipo.

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
    //Other properties, methods, events...
}

class Program
{
    static void Main()
    {
        Person person1 = new Person("Leopold", 6);
        Console.WriteLine("person1 Name = {0} Age = {1}", person1.Name, person1.Age);

        // Declare a new person, assign person1 to it.
        Person person2 = person1;

        //Change the name of person2, and person1 also changes.
        person2.Name = "Molly";
        person2.Age = 16;

        Console.WriteLine("person2 Name = {0} Age = {1}", person2.Name, person2.Age);
        Console.WriteLine("person1 Name = {0} Age = {1}", person2.Name, person2.Age);

        // Keep the console open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();        

    }
}
/*
    Output:
    person1 Name = Leopold Age = 6
    person2 Name = Molly Age = 16
    person1 Name = Molly Age = 16
*/

Dado que las estructuras son tipos de valor, una variable de un objeto de estructura contiene una copia de todo el objeto. También se pueden crear instancias de estructuras utilizando el operador new, pero no es obligatorio, como se muestra en el ejemplo siguiente:

public struct Person
{
    public string Name;
    public int Age;
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

public class Application
{
    static void Main()
    {
        // Create a struct instance and initialize by using "new".
        // Memory is allocated on thread stack.
        Person p1 = new Person("Alex", 9);
        Console.WriteLine("p1 Name = {0} Age = {1}", p1.Name, p1.Age);

        // Create a new struct object. Note that a struct can be initialized
        // without using "new".
        Person p2 = p1;

        // Assign values to p2 members.
        p2.Name = "Spencer";
        p2.Age = 7;
        Console.WriteLine("p2 Name = {0} Age = {1}", p2.Name, p2.Age);

        // p1 values remain unchanged because p2 is a copy.
        Console.WriteLine("p1 Name = {0} Age = {1}", p1.Name, p1.Age);

        // Keep the console open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey(); 
    }
}
/*
  Output:
    p1 Name = Alex Age = 9
    p2 Name = Spencer Age = 7
    p1 Name = Alex Age = 9
*/

La memoria para p1 y p2 se asigna en la pila de subprocesos. Esta memoria se reclama junto con el tipo o método en el que se declara. Ésta es una razón por la que las estructuras se copian en la asignación. Por el contrario, Common Language Runtime reclama automáticamente (mediante la recolección de elementos no utilizados) la memoria asignada a una instancia de clase cuando todas las referencias al objeto han quedado fuera del ámbito. No es posible destruir de manera determinista un objeto de clase como se hace en C++. Para obtener más información sobre la recolección de elementos no utilizados en .NET Framework, vea Recolección de elementos no utilizados.

Nota:

La asignación y desasignación de memoria en el montón administrado están muy optimizadas en Common Language Runtime. En la mayoría de los casos no existe una diferencia significativa de costo de rendimiento entre asignar una instancia de clase en el montón frente a asignar una instancia de estructura en la pila.

Identidad de objetos frente a igualdad de valor

Al comparar dos objetos para comprobar si son iguales, primero debe diferenciar si desea conocer si las dos variables representan al mismo objeto en memoria o si los valores de uno o más de sus campos son equivalentes. Si desea comparar valores, debe considerar si los objetos son instancias de tipos de valor (estructuras) o tipos de referencia (clases, delegados, matrices).

  • Para determinar si dos instancias de clase hacen referencia a la misma ubicación en memoria (lo que significa que tienen la misma identidad), utilice el método estático Equals. (System.Object es la clase base implícita para todos los tipos de valor y de referencia, incluyendo las clases y estructuras definidas por el usuario.)

  • Para determinar si los campos de instancia de dos instancias de estructura tienen los mismos valores, utilice el método ValueType.Equals. Dado que todas las estructuras heredan implícitamente de System.ValueType, se llama al método directamente en el objeto como se muestra en el ejemplo siguiente:

Person p1 = new Person("Wallace", 75);
Person p2;
p2.Name = "Wallace";
p2.Age = 75;

if (p2.Equals(p1))
    Console.WriteLine("p2 and p1 have the same values.");

// Output: p2 and p1 have the same values.

La implementación System.ValueType de Equals utiliza la reflexión porque debe ser capaz de determinar qué son los campos en cualquier estructura. Al crear sus propias estructuras, invalide el método Equals para proporcionar un algoritmo de igualdad eficaz específico de su tipo.

Secciones relacionadas

Para obtener más información:

Vea también

Conceptos

Guía de programación de C#

Tipos de valor en el sistema de tipos común

Clases del sistema de tipos común

Referencia

object (Referencia de C#)

Herencia (Guía de programación de C#)

class (Referencia de C#)

struct (Referencia de C#)

new (Operador, Referencia de C#)