2010-07-30 7 views
7

Lo que (si lo hay) es la alza oa la baja (rendimiento, buena práctica de codificación, recogida de basura, etc.) de la invocación de un método no estático de una clase en la forma a continuación:Invocación de métodos no estáticos de una clase

new ClassA().MethodA(param1, param2); 

como en contra de la forma más "tradicional" de

ClassA classA = new ClassA(); 
classA.MethodA(param1, param2); 

Cualquier pensamiento sería muy apreciada.

+0

¿Crea ClassA algún recurso no administrado o implementa IDisposable? – SwDevMan81

Respuesta

10

Codificación
cuanto a codificación de la práctica, la segunda opción es mejor, en el que el objeto se almacena en una variable primero. La razón que lo hace mejor es que puede nombrar el objeto de acuerdo con el contexto donde se usa. Por ejemplo:

var pendingUserForRegistration = new User(); 

Rendimiento
En cuanto a rendimiento, la primera opción podría ser un poco mejor, ya que utiliza el objeto directamente de la pila y se salta el almacenamiento del objeto en una variable local .Se puede observar a partir de la IL de los métodos:

IL de primera:

.maxstack 8 
L_0000: nop 
L_0001: newobj instance void NS.ClassA::.ctor() 
L_0006: call instance void MS.ClassA::M() 
L_000b: nop 
L_000c: ret 

IL de segundos:

.maxstack 1 
.locals init (
    [0] class NS.ClassA c) 
L_0000: nop 
L_0001: newobj instance void NS.ClassA::.ctor() 
L_0006: stloc.0 
L_0007: ldloc.0 
L_0008: callvirt instance void NS.ClassA::M() 
L_000d: nop 
L_000e: ret 

Esto es por lo general una pequeña sobrecarga de rendimiento, es Es difícil encontrar un caso donde resolverá un problema de rendimiento real.


En pocas palabras
Dado que la capacidad de mantenimiento de la ganancia de código aquí es mayor que la ganancia de rendimiento que es preferible almacenar el objeto en una variable con el nombre significativo.

+1

Gracias Elisha. Excelente respuesta detallada. Exactamente lo que necesitaba. –

+0

Además, se insinuó en el comentario de @SwDevMan81 sobre la pregunta: si el objeto que está utilizando es desechable, querrá ponerlo en una variable para que luego pueda deshacerse de él limpiamente; hacerlo de la primera forma deja la limpieza del finalizador del objeto, lo que puede (por ejemplo) dejar las conexiones abiertas. – JohnLBevan

3

No haría ninguna diferencia en absoluto. Es solo que en esta situación un método estático probablemente sería más apropiado.

+0

Estoy de acuerdo, desafortunadamente mi influencia no se extiende a modificar esa clase :). También se vuelve un poco difícil de manejar multi-threading –

0

En general, utilizo métodos estáticos cuando no necesito que la clase "sepa" algo; Utilizo métodos de instancia cuando la clase necesita estar consciente de sí misma y de su propio estado.

Más o menos.

1

Si no va a utilizar ClassA para nada más, entonces new ClassA().MethodA(param1, param2); está bien. De lo contrario, debería ir con la instanciación más tradicional ClassA classA = new ClassA();

+0

Tiene sentido. Muchas gracias por la pronta respuesta. –

0

Me pregunto por qué querría hacer esto en el sitio de la llamada. Si no puede evitarlo, podría ser mejor ajustar el new ClassA().MethodA(a,b) en un método estático para evitar el ruido del código en el sitio de la llamada.

+0

Hmmm ... luego se vuelve complicado administrar multi-threading –

0

Son idénticos. El primer enfoque significa menos líneas de código. El segundo enfoque es ligeramente mejor si alguien necesita modificar el código para comenzar a llamar al MethodB.

+0

Tiene sentido en el segundo punto. Probablemente el compilador resuelva ambos de la misma manera de todos modos. Gracias por su pronta respuesta –

1

No veo ninguna diferencia entre ellos. Sin embargo, si ClassA implementa IDisposable ambos son una mala idea.

+0

Gracias por la respuesta rápida. Si ClassA implementa IDisposable, ¿cuáles son las repurcussions? –

+0

Si 'ClassA' implementa' IDisposable' debe invocar el método 'Dispose' cuando la instancia ya no se necesita, ya sea manualmente o mediante una instrucción' using'. Si no lo hace, puede provocar que el código pierda recursos no administrados (según lo que haga 'ClassA'). –

+0

Muchas gracias, Fredrik. Aprecio la aclaración. –

2

No hay diferencia en el back-end. En el CIL, creará un objeto ClassA y luego llamará al método. Ambas piezas de código se traducen en el mismo CIL, por lo que no hay ninguna diferencia de rendimiento.

+0

Muchas gracias Scott, eso es lo que me preguntaba. –

1

Los dos son idénticos. De hecho, hay muchas posibilidades de que el compilador genere IL idéntica para cada uno.

El método tradicional es una ventaja en la depuración, si está seguro de si hay un problema en el controlador o en MethodA; o si MethodA altera el objeto, y necesita inspeccionarlo.

+0

La depuración es un gran punto. Gracias James –

0

Su primer enfoque necesita instanciar una instancia de ClassA (además de cargar la definición de clase en la memoria si la clase nunca se usó hasta ahora). El segundo enfoque evita esta instanciación de objetos adicionales y la siguiente recolección de basura de la clase.

Si esto sucede de vez en cuando y no millones de veces, no me molestaría. Sin embargo, sería un diseño más limpio implementar el método estático si no necesita acceder a ningún método o propiedad de instancia de clase.

A veces se usa un enfoque ligeramente diferente: supongamos que ClassA necesita un argumento en su constructor que podría inicializar un campo privado o una propiedad que a su vez sería utilizada por su método. En este caso, el primer enfoque es una necesidad:

new ClassA(param0).MethodA(param1, param2); 

Pero - incluso entonces, el método simplemente podría redefinirse para tomar parámetros adicionales.

Cuestiones relacionadas