¿Cuál es la forma correcta de manejar una variable a través de múltiples métodos?

Di que tengo un List<Objects>. Quiero definir la lista de objetos en un método y usarlos en varios otros.

Estas son las formas que se me ocurrieron y estoy buscando más o la forma correcta de hacerlo.

  1. Tu puedes definir List<Objects> en todos los métodos que lo utilizan.
    • Ventajas: Funciona. No hay posibilidad de obtener la variable incorrecta.
    • Contras: Duplicación de código.
  2. Puedes usar un privado List<Objects> definido en la clase y actualizarlo usando (ref ListObjects)
    • Pros: solo tengo que definirlo una vez.
    • Desventajas: Siento que es una práctica desordenada y mala.
  3. Puedes pasar List<Objects> como un parámetro a los métodos que lo utilizan.
    • Pros: evita la duplicación de código
    • Contras: tengo que hacer que mis funciones de relleno devuelvan funciones y agregar parámetros a mis otros métodos. ¿Posibles conflictos con Eventos?

Así que eso es lo que se me ocurrió. Realmente no estoy seguro de cuál usar o si hay una mejor manera de hacerlo. ¿Pensamientos?

EDITAR: Incluyendo algún código según lo solicitado.

private List<MedicalPlan> medicalPlansList;

Esta es la lista. Es una lista que obtiene información de una base de datos, aquí:

private void BindMedicalList()
{
   medicalPlansList = new MedicalPlanRepository().RetrieveAll().Where(x => x.Year == year).ToList();
}

Luego se usa para encontrar objetos en esa lista, como

var result =
                    medicalPlansList.FirstOrDefault(
                        c => c.CoverageLevels.Any(p => p.Id == id));

preguntado el 27 de julio de 12 a las 18:07

Por qué lo necesitas ref? puedes pasar List<T> y mutarlo... -

@proseidon List es una clase, y como tal es un tipo de referencia. Cuando tienes una variable que es de tipo List en realidad no contiene la lista completa, contiene una referencia a esa lista. Pasando eso usando ref parámetros es el equivalente en C++ de un puntero a un puntero. No necesitas eso en este contexto. -

Para eliminar la confusión de cuándo usar ref lea el artículo de @JonSkeet sobre los parámetros de C#: yoda.arachsys.com/csharp/parameters.html -

@proseidon Bueno, es más difícil decirlo sin código, pero parece que definió una variable de lista y nunca le asignó una instancia de lista. -

@proseidon Dados los fragmentos de código proporcionados, si la lista es nula cuando llama al segundo método, significa que nunca llamó al Bind método primero (al menos no en la misma instancia de objeto). Si lo hizo, se configuró como nulo después o hubo un error al crear la lista. -

4 Respuestas

Así es, en general, cómo lo haría. Si siempre usa la misma secuencia de funciones en una lista, considere crear una función encadenada para manejar eso. También puede pasar directamente una llamada de función dentro de una de las otras llamadas de función (siempre que devuelva una lista), pero eso tiende a verse complicado.

public List<int> DoSomethingWithList(List<int> list)
{
    //do stuff
    return list;
}

public List<int> DoSomethingElseWithList(List<int> list)
{
    //do other stuff
    return list;
}

public void SomeOtherFunction(string[] args)
{
    var list = new List<int>() { 1, 2, 3, 4 }; //create list
    list = DoSomethingWithList(list); //change list
    list = DoSomethingElseWithList(list); //change list further
}

Si está trabajando con un objeto que tiene un List<T> campo, haría así:

public class MyBigClass
{
    private List<int> myList;
    public MyBigClass()
    {
        //instantiate list in constructor
        myList = new List<int>() { 1, 2, 3, 4 }; 
    }

    public void PublicListAdder(int val)
    {
        myList.Add(val);
    }

    private void PrivateListCleaner()
    {
        //remove all even numbers, just an example
        myList.RemoveAll(x => x % 2 == 0);
    }
}

Rara vez necesitas usar ref en C#, porque maneja automáticamente los punteros por usted. (Por lo general) no está pasando una estructura, está pasando una referencia de objeto (que básicamente es un puntero).

Respondido 28 Jul 12, 08:07

El único problema que encontré con esto es que quiero acceder a la lista en un evento de botón, y dado que el clic del evento de botón se llama desde la página web, mi código subyacente no pasa ningún parámetro al evento. - proseidón

Su #1 y #2 realmente no tienen sentido:

  1. Si define una lista diferente en cada método que la usa, entonces está usando una lista diferente cada vez. Esto no es compartir la lista; este no se trabaja. Si quiere decir "llame a su método que crea la lista de cada método que lo usa", entonces se aplica lo mismo: está usando una lista diferente cada vez.
  2. No necesitas usar ref ListObjects para actualizar un miembro privado; solo se accede a un miembro privado por su nombre. Esta no es una mala práctica; esta es una práctica estándar orientada a objetos.
  3. Pasando todos los datos requeridos dentro un método como parámetros hace que el método sea inherentemente más reutilizable ya que reduce el acoplamiento a la clase a la que pertenece el método.

En resumen: #3 es una buena práctica hasta cierto punto, ya que aumenta la reutilización del código. Sin embargo, el uso de #2 es fundamentalmente la razón por la que tenemos programación orientada a objetos: para ahorrar evitar que pase repetidamente parámetros a todos sus métodos. ¡Esto es exactamente para lo que están diseñados los campos privados!

Respondido 27 Jul 12, 18:07

No estoy de acuerdo con sus comentarios sobre el n. ° 1. Asumes que necesita compartir la lista. Ese no es un requisito establecido. Si cada método solo lee datos, no importa si se comparte o no. También es posible que sea un requisito que la lista no ser compartido. No hay información suficiente para saber cuál es el comportamiento deseado. - Servir

Dice "Quiero definir la lista de objetos en un método y usarlos en varios otros". Supongo (quizás incorrectamente) que esto significa compartir la lista. Quizás el OP podría dar más detalles. - dan puzey

El problema era que no quería acceder a la base de datos para obtener una lista varias veces si solo podía acceder a ella una vez y usar la lista una y otra vez. No hubo ningún problema con la lista que se leyó varias veces porque la base de datos no cambió, pero no fue eficiente: proseidón

@proseidon Eso es correcto. Dado que su lista se genera al acceder a una base de datos, querrá evitar generarla siempre que sea posible y, en su lugar, reutilizarla. Hasta que agregó ediciones posteriores, eso no era evidente. - Servir

En la mayoría de los casos, probablemente elegiría la respuesta de Anders. Dependiendo de su situación, otra forma que vale la pena considerar es escribir métodos de extensión para Lista.

namespace ExtensionMethods
{
    public static class MyExtensions
    {
        public static object DoSomething(this List<T> list)
        {
            //do the something with list
        }
    }   
}

Y luego puedes usarlo así:

var list = new List<int>();
list.DoSomething();

En ese ejemplo, list se pasa como parámetro al método de extensión.

Respondido 27 Jul 12, 19:07

El problema parece ser cómo pasar un List alrededor para que se pueda acceder desde múltiples ámbitos. (Y si esto debemos hacerse o no.) Esto no parece relevante para eso en absoluto. - Servir

@Servy Es relevante porque es otra forma de trabajar con una lista en varias llamadas a métodos. Es posible que no necesite pasar la lista a diferentes métodos si puede escribir extensiones en su lugar. No es la forma más sencilla, pero sin duda tiene su utilidad. - Jeff

Puede ser apropiado tener métodos que tomen un List como un parámetro (para el cual califica un método de extensión). Ese es ciertamente un posible aspecto de una respuesta a esta pregunta, pero ciertamente no es una respuesta en sí misma, y ​​ser un método de extensión no tiene nada que ver con nada; la única razón por la que esto es levemente relevante es que es cualquier método antiguo que toma un List como uno de sus parámetros. - Servir

@Servy No estoy convencido de que sepa qué son los métodos de extensión. O eso o eres un troll. - Jeff

Un método de extensión es azúcar sintáctico que permite llamar a un método estático usando una sintaxis que lo hace parecer un método de instancia del tipo que es el primer parámetro de ese método estático. Usando su método, se transformará internamente (o hará el equivalente de transformar) list.DoSomething() dentro MyExtensions.DoSomething(list). - Servir

Por lo general un List<T> no debe pertenecer al estado de una instancia y estar expuesto, ya que es mutable y puede cambiar el estado desde el exterior, a menos que su getter esté diseñado para devolver una lista de solo lectura. A menos que su diseño permita claramente tal posibilidad cuando pueda ocurrir. Mi respuesta realmente no responde a su pregunta, es solo una sugerencia de un buen diseño orientado a objetos. Como alguien ya sugirió mucho mejor que yo, puede pasar una Lista de un lado a otro de cada método y modificarlo directamente.

Respondido 27 Jul 12, 19:07

Las listas pueden ser variables de instancia de clases. Esto es bastante común. Sí, puede hacerlo de manera insegura si expone demasiado la lista, pero eso no significa que no se deban usar (o que no se usen todo el tiempo). - Servir

¡¡por supuesto!! ¡pero expliqué por qué en este contexto! increíble. de todos modos está bien... tu explicación es tan brillante que tengo que votar a favor (sarcasmo) - diego de vita

"Por lo general, una lista no debería pertenecer al estado de una instancia" No veo cómo esto se refiere al ejemplo de este usuario específico, ya que no ha incluido nada específico a esta pregunta en su respuesta. La declaración citada es bastante amplia y parece aplicarse a... todo. - Servir

ok, corregiré la declaración de acuerdo con mi opinión y su resaltado. Gracias - diego de vita

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.