Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

154
Views
¿Por qué puedo establecer las propiedades de una propiedad establecida de forma privada?

Tengo una clase LoginManager que tiene un campo privado currentUser y una propiedad pública CurrentUser para no permitirme cambiar accidentalmente el valor de CurrentUser desde fuera de la clase LoginManager .

CurrentUser es { get; } solo, pero aún puedo cambiar las propiedades en el currentUser subyacente que es privado.

p.ej.

 Console.WriteLine(loginManager.CurrentUser.ClockedIn.ToString()); // true loginManager.CurrentUser.ClockedIn = false; Console.WriteLine(loginManager.CurrentUser.ClockedIn.ToString()); // false loginManager.CurrentUser.ClockedIn = true; Console.WriteLine(loginManager.CurrentUser.ClockedIn.ToString()); // true

LoginManager.cs

 public class LoginManager { private User? currentUser { get; set; } private readonly ApplicationDbContext dbContext; public event EventHandler CurrentUserChanged; public User? CurrentUser { get { return currentUser; } } //... }

Usuario.cs

 public class User { public Guid Id { get; set; } public string Name { get; set; } public string Username { get; set; } public string Password { get; set; } public bool ClockedIn { get; set; } }

Lo quiero para que no pueda cambiar CurrentUser desde fuera de la clase LoginManager . ¿Alguien podría indicarme la dirección correcta?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Creo que veo el problema, las instancias privadas de CurrentUser get y set propiedades que están expuestas fuera de la clase, ya que esas variables miembro tienen un alcance public .

¿Por qué no hacer que las propiedades del User sean private ?

 public class User { private Guid Id { get; set; } private string Name { get; set; } private string Username { get; set; } private string Password { get; set; } private bool ClockedIn { get; set; } }

O si necesita get el private set marcas de propiedades:

 public class User { public Guid Id { get; private set; } public string Name { get; private set; } public string Username { get; private set; } public string Password { get; private set; } public bool ClockedIn { get; private set; } }

O hágalos explícitamente de readonly para que solo puedan inicializarse en el Constructor :

 public class User { public readonly Guid Id { get; private set; } public readonly string Name { get; private set; } public readonly string Username { get; private set; } public readonly string Password { get; private set; } public readonly bool ClockedIn { get; private set; } public User(Guid Id, string Name, string Username, string Password, bool ClockedIn) { this.Id = Id; this.Name = NameName; this.Username = Username; this.Password = Password; this.ClockedIn = ClockedIn; } }
over 4 years ago · Santiago Trujillo Report

0

Lo primero que debe comprender es que el descriptor de acceso set faltante solo le impide cambiar el valor de la propiedad CurrentUser en sí. Es decir, le impide cambiarlo a otro objeto User (o nulo). Sin embargo, estas reglas solo se aplican a la propiedad en sí, y no a nada dentro de ella. La naturaleza de solo lectura de las propiedades no es recursiva.

Si desea evitar cambiar las propiedades dentro del objeto User contenido en CurrentUser , deberá tener un objeto User inmutable de algún tipo, o debe evitar el acceso directo al objeto y proporcionar métodos auxiliares que permitan recuperar ciertos datos del usuario sin poder cambiarlo. Las dos opciones son, por lo tanto, ocultar el acceso directo o hacer que el objeto User sea de alguna manera inmutable.

La primera opción es ocultar el acceso al objeto User :

 public User? CurrentUser { get; } public string GetCurrentUserName() { return CurrentUser?.Name; } public string GetCurrentUserUsername() { return CurrentUser?.UserName; }

Lo anterior sigue la llamada Ley de Deméter, pero no veo que se use con demasiada frecuencia ya que no es ergonómico e infla las clases. Siga esta ruta solo si muchos de los detalles del usuario actual no son importantes para el código que usa LoginManager y si dicho código no necesita poder pasar el objeto User .

La segunda opción tiene algunas subopciones. Puede crear una interfaz IReadOnlyUser que solo exponga propiedades de solo lectura:

 interface IReadOnlyUser { public string Name { get; } public string Username { get; } } public class User : IReadOnlyUser { // although these have setters, they cannot be access through variables of type IReadOnlyUser (see below) public string Name { get; set; } public string Username { get; set; } } public class LoginManager { // you can use a field here instead of a property since it is private private User currentUser; // returns an read-only view of the user, so write accessors are not available public IReadOnlyUser CurrentUser { get { return currentUser; } } } // usage var lm = new LoginManager(); Console.WriteLine(lm.CurrentUser.Name); // okay because IReadOnlyUser has a read accessor for Name lm.CurrentUser.Name = "foo"; // not allowed because IImutableUser does not expose a write accessor }

Además, puede hacer lo mismo que en la otra respuesta y hacer que los campos en la clase de User sean de solo lectura, ya sea con campos de readonly o con propiedades que solo tienen accesos de get . Depende de si cree que hay casos en los que debería poder modificar las propiedades de los objetos User , pero no en el contexto de LoginManager .

Finalmente, si no controla la clase User , puede crear una clase de fachada que envuelva un objeto User pero solo exponga captadores:

 public class ReadOnlyUser { private User user; public ReadOnlyUser(User user) { this.user = user; } public string Name { get { return user.Name; } } } // in LoginManager private ReadOnlyUser currentUser; public ReadOnlyUser CurrentUser { get { return currentUser; } set { currentUser = new ImmutableUser(value); } } // usage var lm = new LoginManager(); lm.CurrentUser = userFromSomewhereElse; Console.Log(lm.CurrentUser.Name); // okay because ReadOnlyUser exposes this property from the underlying User class lm.CurrentUser.Name = "foo"; // not allowed because ReadOnlyUser doesn't have a setter for Name

En mi opinión, no hay una única respuesta correcta en particular. Depende de lo que quieras hacer.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!