Pregunta

Estoy trabajando en .NET 3.5. Tengo una clase "A" que tiene una propiedad y una propiedad de Getter que, cuando se llama, elimina el primer elemento en la pila y recupera la siguiente.

Después de inicializar la clase, vi que el Getter funciona sin ser llamado y elimina el elemento superior en la pila, lo que me da malos resultados. Un punto de interrupción en el Getter no mostró a nadie que lo pasara.

Cuando cambio la propiedad a una función, la pila se devuelve bien.

Sería feliz si alguien pudiera explicar por qué es eso.

Aquí está la clase simplificada:

 public class A
    {
        private Stack<string> Urls;

        public A(string title, string[] array)
        {
            Urls = new Stack<string>();
            foreach (string s in array)
            {
                Urls.Push(s);
            }
        }

        public string Url
        {
            get { return Urls.Peek(); }
        }
        public string NextUrl
        {
            get{
            if (Urls.Count > 1)
                { Urls.Pop(); } 
            return Urls.Peek(); 
            };
        }            
    }
¿Fue útil?

Solución

En primer lugar, hacer que un accesor de propiedad cambie el estado generalmente es una mala idea. Lo máximo que debe hacer es inicializar perezosamente algo, o posiblemente dar un valor volátil (como DateTime.Now lo hace).

En segundo lugar, probablemente esté viendo esto si se está ejecutando bajo el depurador: accede a las propiedades mientras avanza en el código. Eso probablemente explicaría por qué el punto de ruptura no estaba siendo golpeado también.

Otros consejos

Urls.Pop();

quiere ser

return Urls.Pop();

Como devuelve el valor y Elimina de la lista al mismo tiempo


En realidad, después de haber vuelto a leer su pregunta, parece que es porque el depurador evalúa las propiedades. Si ejecuta la aplicación sin el depurador, ¿obtiene el mismo problema?

Este es un mal diseño, creo. Un accesor GET no debe mutar el objeto de una manera que cause diferentes resultados en las llamadas posteriores.

En mi opinión, el problema aquí es tener una propiedad que tiene efectos secundarios no obvios; Este debería ser un método:

    public string GetNextUrl() { /* */ }

De lo contrario, las cosas malas suceden en todas partes (el depurador, la unión de datos, etc.). No asuma que alguien solo lee una propiedad una vez.

El único uso sensato de los efectos secundarios en las propiedades es cosas como la carga perezosa, la inicialización diferida, etc. Todavía debe informar el mismo valor cuando se llama secuencialmente sin ninguna otra llamada de mutación obvia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top