Al llamar Push()
y Pop()
una instancia de Stack<T>
en una sola línea consigo un comportamiento diferente de realizar el mismo código en mi humilde opinión en dos líneas.orden de operación inesperado en Pila <T> relacionados con un trazador de líneas
El siguiente fragmento de código reproduce el comportamiento:
static void Main(string[] args)
{
Stack<Element> stack = new Stack<Element>();
Element e1 = new Element { Value = "one" };
Element e2 = new Element { Value = "two" };
stack.Push(e1);
stack.Push(e2);
Expected(stack); // element on satck has value "two"
//Unexpected(stack); // element on stack has value "one"
Console.WriteLine(stack.Peek().Value);
Console.ReadLine();
}
public static void Unexpected(Stack<Element> stack)
{
stack.Peek().Value = stack.Pop().Value;
}
public static void Expected(Stack<Element> stack)
{
Element e = stack.Pop();
stack.Peek().Value = e.Value;
}
La clase de elemento es muy básico:
public class Element
{
public string Value
{
get;
set;
}
}
Con este código me sale el siguiente resultado (.NET 3.5, Win 7, totalmente parcheado):
- Calling
Expected()
(versión con dos líneas ) LEA un elemento en la pila conValue
establecido en"two"
. - Al llamar
Unexpected()
(Versión con una línea) consigo un elemento de la pila con el conjunto deValue
"one"
.
La única razón de la diferencia que podía imaginar era la precedencia del operador. Como el operador de asignación (=
) tiene el lowest precedence, no veo ninguna razón por la cual los dos métodos se comporten de manera diferente.
También tuve un vistazo a la IL genera:
.method public hidebysig static void Unexpected(class [System]System.Collections.Generic.Stack`1<class OperationOrder.Element> stack) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: callvirt instance !0 [System]System.Collections.Generic.Stack`1<class OperationOrder.Element>::Peek()
L_0006: ldarg.0
L_0007: callvirt instance !0 [System]System.Collections.Generic.Stack`1<class OperationOrder.Element>::Pop()
L_000c: callvirt instance string OperationOrder.Element::get_Value()
L_0011: callvirt instance void OperationOrder.Element::set_Value(string)
L_0016: ret
}
No soy una grieta IL, pero para mí este código todavía se ve bien ans deben salir de un elemento en la pila con el valor establecido en " dos".
¿Alguien me puede explicar el motivo por el cual el método Unexpected()
hace algo diferente de Expected()
?
¡Muchas gracias!
Lukas
Tienes razón. Debería haber pensado en eso. ¡Muchas gracias! –