2012-10-09 38 views
11

¿por qué en C# mis dos variables apuntan a diferentes objetos DateTime?C# DateTime siempre crea un objeto nuevo?

DateTime a1 = DateTime.Now; 
DateTime a2 = a1; 

a1 = a1 + TimeSpan.FromMinutes(15); 
a2 = a2 - TimeSpan.FromMinutes(16); 

Me di cuenta de que a2 en realidad apunta a un nuevo objeto que es diferente de a1.

Pero en otro caso. Digamos que tengo una Persona de clase, y edad = 1;

Person a1 = new Person(); 
a2 = a1; 
a2 = Person.Age = 2; 

En Person Case, a1 y a2 apuntan al mismo objeto. Estoy realmente confundido aquí, ¿alguien puede explicar?

+2

DateTime es un tipo de valor, no un tipo de referencia –

+1

Comprobar esta respuesta http://stackoverflow.com/a/4265417/1511796 –

Respuesta

23

DateTime es un tipo de valor - una estructura.

Con los tipos de valor, cuando se hace algo así como:

DateTime a2 = a1; 

a2 para crear una copia de los valores de a1. No es la misma referencia a la misma ubicación de memoria, sino una copia completa y separada.

Por otro lado, Person es un tipo de referencia - una clase.

Al hacer:

Person p2 = p1; 

Con un tipo de referencia, la referencia que apunta a p2 es el mismo que p1 puntos a. Entonces los cambios en uno son cambios a ambos.

Consulte Value Types and Reference Types en MSDN.

+0

DateTime es inmutable si no estoy equivocado. En realidad estoy en una confusión. Cadena inmutable también, pero ese es el tipo de referencia. Quiero preguntar ¿no es efecto para una Inmutabilidad qué tipo es realmente? Apreciaré su respuesta gracias. –

+1

@NomiAli - ¿por qué no publicar una pregunta, entonces? Los tipos de valores normalmente se crean como inmutables (y se ajusta bastante bien a su semántica). 'cadena' fue creado como inmutable por muchos motivos diferentes (la optimización es uno). Puede crear valores inmutables o tipos de referencia. – Oded

3

La diferencia aquí es que DateTime es un tipo de valor, y asumo que Person es un tipo de referencia (clase).

En el caso de una asignación variable de un tipo de valor, en realidad está copiando el contenido de la memoria de una ubicación a otra.

Sin embargo, en el caso de un tipo de referencia, todavía está apuntando a la misma pieza de memoria.

3

Aquí hay dos conceptos por separado. La primera es que DateTime es un tipo de valor (a.k.a. una estructura) mientras que Person es [presumiblemente] un tipo de referencia (una clase). Debido a esto, cuando lo hace:

DateTime date1 = DateTime.Now; 
DateTime date2 = date1; 

date2 dará lugar a copiar el valor, por lo que las dos variables no va a hacer referencia al mismo objeto.

Con las clases, cuando lo hace:

Person p1 = new Person(); 
Person p2 = p1; 

p1 no contiene realmente un Person, que sólo contiene una referencia a una persona . Esa referencia luego se copia (por valor) a p2. El efecto de copiar esa referencia es que ambas variables ahora están "apuntando a" o "haciendo referencia" al mismo objeto.

A continuación está la cuestión de la mutabilidad.Person, en este caso, es un tipo mutable. Eso significa que puede ser cambiado. Por otro lado, un tipo inmutable no se puede cambiar una vez construido.

La línea:

p2.Age = 2; 

es en realidad cambiar el objeto que p2 referencias, y desde p2 y p1 tanto referencia al mismo objeto, p1.Age sería 2 después de esa línea de código.

Ahora, con fines de demostración, vamos a hacer un inmutable clase Person:

public class Person 
{ 
    private int _age; 
    public Person(int someAge) 
    { 
     _age = someAge; 
    } 

    public int Age 
    { 
     get { return _age; } 
    } 

    public Person Grow() 
    { 
     return new Person(_age + 1); 
    } 
} 

Si hacemos algo como esto:

Person p1 = new Person(1); 
Person p2 = p1; 
p2 = p2.Grow(); 

la segunda línea está haciendo precisamente lo que era antes, asegurando que ambos apuntan al mismo objeto, pero la tercera línea es diferente. En lugar de cambiar (o mutar) a esa persona para que sea un año más antiguo, nuestro método Growdevuelve un nuevo objeto Person que representa a alguien un año mayor. Después de hacer esto, p2 y p1 ya no estarán haciendo referencia al mismo objeto; Acabo de cambiar el objeto p2 referencias a uno nuevo que acaba de crear el método Grow.

Este segundo ejemplo es bastante similar a lo que está sucediendo con DateTime. No puede mutar un objeto DateTime; es inmutable Llamar a sus métodos (en este caso, los operadores más y menos) devuelve un objeto completamente nuevo. Por convención, los tipos de valor no deben ser mutables sin una razón convincente, ya que a menudo puede ser complicado lidiar con ellos. Los tipos de referencia pueden ser inmutables o mutables; ninguno tiene problemas significativos (en el caso general).

4

Como otros ya han señalado DateTime es una estructura, no una clase y, por lo tanto, un tipo de valor. Puede ver esto en el editor de Visual Studio, si cambia el color de texto utilizado para mostrar las estructuras. Abrir el cuadro de diálogo en el menú Tools>Options y vaya a Environment>Fonts and Colors

enter image description here

Es útil para cambiar el color de los delegados, enumeraciones, interfaces y estructuras (tipos de valor).

Cuestiones relacionadas