c# - personalizar - merge nombre mailchimp
Condicional de C#usando la instrucción de bloque (10)
Tengo el código de seguimiento pero es incómodo. ¿Cómo podría mejor estructurarlo? ¿Tengo que hacer que mi clase consumidora implemente IDisponible y condicionalmente construya la clase de acceso a la red y la deseche cuando haya terminado?
protected void ValidateExportDirectoryExists()
{
if (useNetworkAccess)
{
using (new Core.NetworkAccess(username, password, domain))
{
CheckExportDirectoryExists();
}
}
else
{
CheckExportDirectoryExists();
}
}
Al hacer que su clase implemente IDisposable, el método de disposición se llama solo cuando se usa la instrucción "utilizando". De lo contrario tienes que llamar explícitamente a disposición.
Normalmente, los objetos que administran el consumo de memoria fuera del recolector de basura implementan IDisposable (como, por ejemplo, el uso de código no administrado). Proporciona una manera de limpiar cualquier memoria consumida.
Siempre que su clase de NetworkAccess implemente IDisposable, se llamará al método dispose tan pronto como se complete el alcance de la declaración de uso. Si es un código administrado, entonces no hay necesidad de desecharlo. Solo deja que el recolector de basura haga su trabajo.
La declaración de uso es un atajo para evitar los bloques "finalmente" y solo debe usarse cuando hace que el código sea más fácil de seguir. En tu caso escribiría el siguiente código. Puede que no sea tan breve como algunas de las otras versiones, pero es mucho más sencillo.
protected void ValidateExportDirectoryExists()
{
Core.NetworkAccess access = useNetworkAccess ? new Core.NetworkAccess(username, password, domain) : null;
try
{
CheckExportDirectoryExists()
}
finally
{
if (access != null)
{
access.Dispose();
}
}
}
Lo que esté incluido dentro de la declaración de uso tendrá su IDispoable.Dispose
llamado según lo dictado por la interfaz IDisposable
. Como se ve en MSDN para using
...
Proporciona una sintaxis conveniente que asegura el uso correcto de los objetos IDisponibles.
Por lo tanto, si coloca un tipo personalizado dentro de la declaración de using
, debe limpiar sus recursos de manera adecuada a través de la interfaz IDisposable
.
No sé si es "mejor", pero podría usar el patrón de objeto nulo y tener un objeto de acceso de red desechable "nulo". Algo como esto:
protected void ValidateExportDirectoryExists()
{
using (GetNetworkAccess(username, password, domain))
{
CheckExportDirectoryExists();
}
}
protected IDisposable GetNetworkAccess(string username, string password, string domain)
{
return useNetworkAccess ? new Core.NetworkAccess(username, password, domain) : new NullNetworkAccess(username, password, domain);
}
internal class NullNetworkAccess : IDisposable
{
internal NullNetworkAccess(string username, string password, string domain)
{
}
public void Dispose()
{
}
}
Esto es probablemente demasiado lindo por su propio bien.
[EDITAR] Acabo de ver en la respuesta de Jon que null se puede usar en una instrucción using. ¡No tenía ni idea!
Si repite este patrón en muchos métodos puede romper el patrón
protected void OptionalNetworkCall(Action action)
{
if (useNetworkAccess)
{
using (new Core.NetworkAccess(username, password, domain))
{
action();
}
}
else
{
action();
}
}
protected void ValidateExportDirectoryExists()
{
OptionalNetworkCall(CheckExportDirectoryExists);
}
Supongo que eso es realmente una cuestión de cosméticos si el código es tan simple como eso.
Puedo imaginar cómo podría verse a la inversa, y mi voto será para esta versión que tiene ahora.
Una opción, que es algo desagradable pero funcionaría, en función del hecho de que el compilador de C # llama a Dispose
solo si el recurso no es nulo:
protected void ValidateExportDirectoryExists()
{
using (useNetworkAccess
? new Core.NetworkAccess(username, password, domain)
: null)
{
CheckExportDirectoryExists();
}
}
Otra alternativa sería escribir un método estático que devolviera un valor nulo o un NetworkAccess:
private Core.NetworkAccess CreateNetworkAccessIfNecessary()
{
return useNetworkAccess
? new Core.NetworkAccess(username, password, domain)) : null;
}
Entonces:
protected void ValidateExportDirectoryExists()
{
using (CreateNetworkAccessIfNecessary())
{
CheckExportDirectoryExists();
}
}
Una vez más, todavía no estoy seguro de no preferir el original ... realmente depende de la frecuencia con la que necesite este patrón.
Use su propio bloque try / finally, que realiza una lógica similar a la de "usar", pero solo se elimina si se establece useNetworkAccess. Tenga en cuenta que si useNetworkAccess podría verse afectado por otros subprocesos, debe copiar su valor y usar esa copia tanto para crear el recurso como para desecharlo.
el uso del ámbito solo dispondrá de un objeto si la clase implementa una interfaz IDisposible, de modo que sí necesita implementar el método de disposición.
protected void ValidateExportDirectoryExists()
{
var access = useNetworkAccess
? new Core.NetworkAccess(username, password, domain)
: null;
using (access)
{
CheckExportDirectoryExists();
}
}