I have several methods that execute the same setup code and then some cleanup code. The stuff in between changes. I could do it like this:
void method1()
{
var x = DoSetupStuff();
// Method 1 specific code that uses x
DoCleanupStuff(x);
}
void method2()
{
var x = DoSetupStuff();
// Method 2 specif开发者_运维问答ic code that uses x
DoCleanupStuff(x);
}
But I'd rather do something where I don't have to call both setup and cleanup methods every time. Maybe like one call where the method specific stuff can be passed in?
void SetupAndCleanup( method-specific-code )
{
// Setup code here
int x = 1;
// method-specific code injected here.
// note that it uses x.
// cleanup code here
x = 0;
}
The method1, method2 approach works perfectly well, I'm just wandering if there is a way to improve it or make it more elegant.
If "x" is always an int you can just pass in an Action:
void SetupAndCleanup( Action<int> methodCode )
{
// Setup code here
int x = 1;
try
{
methodCode(x);
}
finally
{
// cleanup code here
x = 0;
}
}
You can use a delegate:
void SetupAndCleanup(Action action) {
// setup
action();
// cleanup
}
void Method1() {
SetupAndCleanup(() => {
// do my stuff here
});
}
// or...
private void Method2Impl() {
// do my stuff here
}
void Method2() {
SetupAndCleanup(Method2Impl);
}
or an IDisposable:
private sealed class SetupClass : IDisposable {
public SetupClass() {
// setup
}
public void Dispose() {
// cleanup
}
}
void Method1() {
using (SetupClass setup = new SetupClass() {
// do stuff here
}
}
void Method2() {
using (SetupClass setup = new SetupClass() {
// do stuff here
}
}
If you can place the Method1 & Method2 specific code into their own functions, and each could share the same method signature, then create a delegate type of the signature, and write Method1 & Method2 to conform to the signature and pass it to SetupAndCleanup. A lambda will work if you can do everything you need to using the lambda. To use the lambda just remember that the lambda follows the signature of the delegate.
Sounds like you might want to use a class:
public abstract class DoStuff
{
protected abstract void DoStuffImpl(var x);
private var DoSetupStuff()
{
} // eo DoSetupStuff
private void DoCleanupStuff(var x)
{
} // eo DoCleanupStuff
public DoStuff()
{
} // eo ctor
public void DoMethod()
{
var x = DoSetupStuff();
DoStuffImpl(x);
DoCleanupStuff(x);
} // eo DoMethod
} // eo class DoStuff
Then provide specializations:
public class Special1 : DoStuff
{
protected override DoStuffImpl(var x)
{
// work with x here
}
} // eo class Special1
public class Special2 : DoStuff
{
protected override DoStuffImpl(var x)
{
// work with x here, but in a different way
}
} // eo class Special2
// work with them
Special1 s1; s1.DoMethod();
Special2 s2; s2.DoMethod();
I'd use a method such as this:
void ExecuteMethodWithSetupAndCleanup(Action<int> method)
{
// do the setup stuff
var x = DoSetupStuff();
// run the provided code
method(x);
// do the cleanup stuff
DoCleanupStuff(x);
}
And then use it like this:
void method1()
{
ExecuteMethodWithSetupAndCleanup(x =>
{
// here is the method1 specific code using x
}
}
void method2()
{
ExecuteMethodWithSetupAndCleanup(x =>
{
// here is the method2 specific code using x
}
}
Alternatively, if you already have method1()
and method2()
and you want to keep them separate, and only remove the setup/cleanup from them, you can do something like this:
void method1(int x)
{
// here is the method1 specific code using x
}
void method2(int x)
{
// here is the method2 specific code using x
}
void ExecuteMethod1AndMethod2()
{
ExecuteMethodWithSetupAndCleanup(method1);
ExecuteMethodWithSetupAndCleanup(method2);
}
How about something like:
protected Action DoSetupStuff()
{
//... setup code
Action cleanup = () =>
{
//... prepare cleanup code for later
};
return cleanup;
}
void DoSomethingUseful()
{
var cleanup = DoSetupStuff();
// do something useful
cleanup();
}
This way, your setup method prepares its own cleanup code, and your primary DoSomethingUseful method never has to know about it.
精彩评论