Duda en carga de Coleccion

21/10/2007 - 02:29 por Guillermo Peralta | Informe spam
Hola a todos;

Tengo el siguiente codigo:


//se carga en un SqlDataReader el resultado de una consulta
SqlDataReader oReader = oCmd.ExecuteReader ();

//Coleccion Generic de la clase Modulo
Modulos Modulos = new Modulos () ;

Modulo oMod = new Modulo(); // (1)

while (oReader.Read ())
{
Modulo oMod = new Modulo(); // (2)

oMod.IdModulo = (int) oReader["IdModulo"];
oMod.IdProducto = (int) oReader ["IdProducto"];
oMod.NombreModulo = oReader["NombreModulo"].ToString ();

//agrega nuevo elemento a la coleccion
Modulos.Add (oMod);
}

La duda que tengo es que si yo comento la linea marcada con (2) dentro del
bucle y solo instancio un solo objeto de la clase Modulo ( linea marcada con
(1) ) , todos los elementos de la coleccion quedan iguales al finalizar el
bucle, es decir, si la consulta me devuelve 1,2,3,4, en la coleccion yo
tengo 4,4,4,4
Si dejo la instancia del objeto dentro del bucle esto no ocurre.

No acabo de entender este comportamiento, puede alguien explicarmelo?

La otra consulta que tengo es si existe otra forma mas eficiente de cargar
una coleccion con el resultado de la consulta obtenida por SqlCommand.

Muchas gracias

Saludos
Guillermo
AG-CBA-ARG

Preguntas similare

Leer las respuestas

#1 Bela Istok
21/10/2007 - 08:02 | Informe spam
En .net las variables tienen alcance, y tu tienes 2 variables llamadas oMod
una externa (seguramente dentro de un método) y otra interna que pertenece
al while, y parece que el compilador esta tomando es la externa, puedes
probar 2 cosas primero comenta la línea marcada con (1) o segundo quita en
la línea marcada con (2) el Modulo para que quede algo así como esto: oMod =
new Modulo();

PD: La razón por la que en tu colección todos los elementos quedan con 4 es
que es una variable por referencia y tu estas añadiendo 4 veces la
referencia y los valores cambian en cada iteración del while.

PD2: hay muchas otras formas de hacerla, pero básicamente esa es la mas
usada.

Saludos,

Bela Istok
"Guillermo Peralta" wrote in message
news:%
Hola a todos;

Tengo el siguiente codigo:


//se carga en un SqlDataReader el resultado de una consulta
SqlDataReader oReader = oCmd.ExecuteReader ();

//Coleccion Generic de la clase Modulo
Modulos Modulos = new Modulos () ;

Modulo oMod = new Modulo(); // (1)

while (oReader.Read ())
{
Modulo oMod = new Modulo(); // (2)

oMod.IdModulo = (int) oReader["IdModulo"]; oMod.IdProducto = (int)
oReader ["IdProducto"];
oMod.NombreModulo = oReader["NombreModulo"].ToString ();

//agrega nuevo elemento a la coleccion
Modulos.Add (oMod);
}

La duda que tengo es que si yo comento la linea marcada con (2) dentro del
bucle y solo instancio un solo objeto de la clase Modulo ( linea marcada
con (1) ) , todos los elementos de la coleccion quedan iguales al
finalizar el bucle, es decir, si la consulta me devuelve 1,2,3,4, en la
coleccion yo tengo 4,4,4,4
Si dejo la instancia del objeto dentro del bucle esto no ocurre.

No acabo de entender este comportamiento, puede alguien explicarmelo?

La otra consulta que tengo es si existe otra forma mas eficiente de cargar
una coleccion con el resultado de la consulta obtenida por SqlCommand.

Muchas gracias

Saludos
Guillermo
AG-CBA-ARG

Respuesta Responder a este mensaje
#2 Alberto Poblacion
21/10/2007 - 09:36 | Informe spam
Me extraña que no te dé un error al compilar. Normalmente cuando decleras
una variable en un bloque externo (1) y luego la vuelves a declarar en el
interno (2), el compilador de C# te avisa de la posible ambigüedad al hacer
referencia a ella.

En cualquier caso, lo que no tiene mucho sentido es declararla e
inicializarla (new) en los dos sitios. Puedes declararla fuera e
inicializarla dentro:

Modulo oMod;
while (oReader.Read ())
{
oMod = new Modulo();
...

O bien declararla e inicializarla dentro, es decir, dejar únicamente (2) y
suprimir (1). Esta opción es preferible en este caso concreto en que "oMod"
no se necesita fuera del bucle, en atención al criterio de definir las
variables con el mínimo alcance posible.


"Guillermo Peralta" wrote in message
news:%
//se carga en un SqlDataReader el resultado de una consulta
SqlDataReader oReader = oCmd.ExecuteReader ();

//Coleccion Generic de la clase Modulo
Modulos Modulos = new Modulos () ;

Modulo oMod = new Modulo(); // (1)

while (oReader.Read ())
{
Modulo oMod = new Modulo(); // (2)

oMod.IdModulo = (int) oReader["IdModulo"];
oMod.IdProducto = (int) oReader ["IdProducto"];
oMod.NombreModulo = oReader["NombreModulo"].ToString ();

//agrega nuevo elemento a la coleccion
Modulos.Add (oMod);
}
Respuesta Responder a este mensaje
#3 Guillermo Peralta
21/10/2007 - 15:29 | Informe spam
Hola Alberto y Bela, ante todo gracias por contestar;

En realidad no fui claro, las lineas (1) y (2) las deje en el ejemplo pero
yo para probar dejaba (1) y comentaba la (2), luego comentaba (1) y dejaba
(2) dentro del bucle. Digamos que nunca deje las dos al mismo tiempo por eso
que el compilador no me de ningun error.

Me parece que la respuesta a mi duda esta en el PD del mensaje de Bela
Istok, sucede que yo pensaba que:

oReader.Read();

oMod.IdModulo = (int) oReader["IdModulo"];

oMod.IdProducto = (int) oReader ["IdProducto"];

oMod.NombreModulo = oReader["NombreModulo"].ToString ();

Modulos.Add (oMod); //en la primera vuelta cargaba los valores en la
coleccion

oReader.Read(); //busca proximos datos

oMod.IdModulo = (int)oReader["IdModulo"];

oMod.IdProducto = (int)oReader["IdProducto"];

oMod.NombreModulo = oReader["NombreModulo"].ToString();

Modulos.Add(oMod); //en la segunda vuelta cargaba los nuevos datos

// pero manteniendo los que ya estaban en la coleccion

//aca es donde no entendia el comportamiento ya que siempre en la coleccion
tenia los ultimos valores cargados

//no pense que fuera necesario instanciar un nuevo objeto de la clase Modulo

Saludos
Guillermo
AG-CBA-ARG



"Alberto Poblacion"
escribió en el mensaje news:
Me extraña que no te dé un error al compilar. Normalmente cuando decleras
una variable en un bloque externo (1) y luego la vuelves a declarar en el
interno (2), el compilador de C# te avisa de la posible ambigüedad al
hacer referencia a ella.

En cualquier caso, lo que no tiene mucho sentido es declararla e
inicializarla (new) en los dos sitios. Puedes declararla fuera e
inicializarla dentro:

Modulo oMod;
while (oReader.Read ())
{
oMod = new Modulo();
...

O bien declararla e inicializarla dentro, es decir, dejar únicamente (2) y
suprimir (1). Esta opción es preferible en este caso concreto en que
"oMod" no se necesita fuera del bucle, en atención al criterio de definir
las variables con el mínimo alcance posible.


"Guillermo Peralta" wrote in
message news:%
//se carga en un SqlDataReader el resultado de una consulta
SqlDataReader oReader = oCmd.ExecuteReader ();

//Coleccion Generic de la clase Modulo
Modulos Modulos = new Modulos () ;

Modulo oMod = new Modulo(); // (1)

while (oReader.Read ())
{
Modulo oMod = new Modulo(); // (2)

oMod.IdModulo = (int) oReader["IdModulo"];
oMod.IdProducto = (int) oReader ["IdProducto"];
oMod.NombreModulo = oReader["NombreModulo"].ToString ();

//agrega nuevo elemento a la coleccion
Modulos.Add (oMod);
}



email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida