2009-02-17 16 views
7

Cuando inicializo un objeto usando los nuevos inicializadores de objeto en C#, no puedo usar una de las propiedades dentro de la clase para realizar una acción adicional y no sé por qué.¿Qué estoy haciendo mal con los inicializadores de objetos C#?

Mi código de ejemplo:

Person person = new Person { Name = "David", Age = "29" }; 

Dentro de la clase de persona, x será igual a 0 (por defecto):

public Person() 
{ 
    int x = Age; // x remains 0 - edit age should be Age. This was a typo 
} 

Sin embargo person.Age es igual a 29. Estoy seguro de que esto es normal, pero me gustaría entender por qué

+0

¿Se supone que la edad de su constructor debe ser en minúscula o titular como su propiedad? Eso podría ayudar a determinar el problema –

+0

no, debería ser Edad. Lo sentimos error – dmce

Respuesta

21

Las propiedades se establecen para Nombre y Edad después de que el constructor 'public Person()' haya terminado de ejecutarse.

Person person = new Person { Name = "David", Age = "29" }; 

es equivalente a

Person tempPerson = new Person() 
tempPerson.Name = "David"; 
tempPerson.Age = "29"; 
Person person = tempPerson; 

Así, en la Edad del constructor no se han convertido en 29 todavía.

(tempPerson es un nombre de variable único que no se ve en el código que no entre en conflicto con otras instancias Person construidas de esta manera. TempPerson es necesario para evitar problemas de subprocesos múltiples; su uso asegura que el nuevo objeto no se convierta en disposición de cualquier otro hilo hasta después de que el constructor ha sido ejecutado y después de todas las propiedades se han inicializado.)


Si usted quiere ser capaz de manipular la propiedad Edad en el constructor, a continuación, Sugiero que cree un constructor que tome la edad como argumento:

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

    // Now do something with Age 
    int x = Age; 
    // ... 
} 
+0

esto es incorrecto, ver respuestas más nuevas – juan

+0

No es la primera afirmación en esta respuesta correcta aunque "Las propiedades se establecen para Nombre y Edad después de que el constructor 'public Person()' haya terminado de ejecutarse." – dmce

+0

@Juan: Estás siendo poco amable con tus comentarios de "esto está mal". Si bien esta respuesta es un poco inexacta con respecto a no hacer referencia a la variable temporal, no está mal con respecto a la pregunta que se hace. Trate de ser más educado, no sea que sea su pregunta o respuesta la próxima vez. –

3

Parece que está intentando acceder al Age en el constructor del objeto. Los valores del inicializador de objetos no se establecerán hasta después de que se haya ejecutado el constructor.

Prueba esto:

Person person = new Person { Name = "David", Age = 29 }; 
int x = person.Age; 

EDITAR en respuesta a comentar

Si necesita acceder a Age en el constructor sí, entonces tendrá que crear un constructor explícito con el parámetros requeridos, y usar eso en lugar de la sintaxis del inicializador de objetos. Por ejemplo:

public class Person 
{ 
    public string Name { get; set; } 
    public int Age { get; set; } 

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

     int x = Age; // will be 29 in this example 
    } 
} 

Person person = new Person("David", 29); 
+0

downvotes inexplicables son una plaga –

+1

votando solo hasta p.o. quien haya votado –

+0

Sí, esto funcionó para mí, pero quiero hacer algo con Age cuando todavía estaba en el constructor – dmce

6

Su línea de código es idéntico a:

Person person = new Person() { Name = "David", Age = "29" }; 

que es idéntica a:

Person person = new Person(); 
person.Name = "David"; 
person.Age = "29"; 

Como se puede ver; cuando el constructor se ejecuta, Age aún no está configurado.

+0

"Cuando el constructor se ejecuta, ¿La edad sigue siendo 29"? De Verdad? –

+0

Ooops - ya sabes lo que quiero decir ;-p –

+0

esto está mal, ver respuestas más nuevas – juan

9

Tenga en cuenta, como un importante detalle técnico, que:

Person person = new Person { Name = "David", Age = "29" }; 

es equivalente a:

Person <>0 = new Person(); // a local variable which is not visible within C# 
<>0.Name = "David"; 
<>0.Age = "29"; 
Person person = <>0; 

pero no es equivalente a:

Person person = new Person(); 
person.Name = "David"; 
person.Age = "29"; 
+0

¿Por qué es esto importante? No veo ninguna diferencia en el efecto. –

+0

+1 por darme una paliza ... eres el correcto wcoenen, no verías la diferencia ... hasta que un hilo diferente intente leer Person.Name - pero en realidad no está configurado porque <> 0.Name es ... –

+0

Sí, el multihilo es la razón por la cual este detalle técnico es importante. – yfeldblum

4

Técnicamente, este código:

Person person = new Person { Name = "David", Age = 29 }; 

es idéntico a este código:

Person tmpPerson = new Person(); 
tmpPerson.Name = "David"; 
tmpPerson.Age = 29; 
Person person = tmpPerson; 

que es ligeramente diferente de lo que otros han publicado:

Person person = new Person(); 
person.Name = "David"; 
person.Age = 29; 

Esta diferencia es crucial si la aplicación está utilizando multi-threading.

0

Bueno, como dijeron otros, el constructor sin parámetros se ejecutó primero, de ahí su dilema.

Sin embargo, tengo que preguntar si ha configurado un campo en lugar de una propiedad automática para su variable de edad.

public class Person 
{ 
    private int _age; 

    public int Age 
    { 
     get { return _age; } 
     set { _age = value; } 
    } 
} 

Usted podría utilizar en lugar de _agex si eso es suficiente, o si realmente necesita usar x:

public class Person 
{ 
    private int _age; 
    private int x; 

    public int Age 
    { 
     get { return _age; } 
     set 
     { 
      _age = value; 
      x = _age; 
     } 
    } 
} 

lo que sea más apropiado.

+0

He utilizado Public int Age {get; establecer;} - propiedades automáticas – dmce

+0

dmce - precise. Las propiedades "manuales" o "tradicionales" le facilitarán la solución de este problema. –

Cuestiones relacionadas