I have a lot of methods that are doing the exact same if checks. Is it possible to wrap these methods in some way so I don't have to repeat the check?
For example, I have lots of methods like these:
public void Method1(int i)
{
if (isThisTrue())
{
SomeMethod(i, 2, 3); // returns void
}
else
{
SomeMethod2(i, "TestString"); // returns void
}
}
public string Method2()
{
if (isThisTrue())
{
return OtherMethod(1, true);
}
else
{
return OtherMethod2(1, "RandomString", 2);
}
}
Because the body of the if else else clauses is different, a simple cache aspect does not work. I thought about creating an Action or a Func for this, but the methods (SomeMethod, SomeMethod2, OtherMethod, and OtherMethod2) signatures are different. Having a whole bunch of them for every possible method signatures doesn't seem sustainable.
Is there a simple way to abstract this out?
The fact that you want to return void in some instances makes it a bit awkward as void doesn't work with generics. You could do something like this though:
public void Method1(int i)
{
this.PredicateMethod(
NullFunc(() => SomeMethod(i, 1, 2)),
NullFunc(() => SomeMethod2(1, "RandomString")));
}
public string Method2()
{
return this.PredicateMethod(
() => OtherMethod(1, true),
() => OtherMethod2(1, "RandomString", 2));
}
private Func<object> NullFunc(Action a)
{
return new Func<object>(() =>
{
a();
return null;
});
}
private T PredicateMethod<T>(Func<T> trueMethod, Func<T> falseMethod)
{
return IsThisTrue() ? trueMethod() : falseMethod();
}
Or implement a base class to capture the logic:
public abstract class PredicateBase
{
private readonly Func<bool> _predicate;
protected PredicateBase(Func<bool> predicate)
{
_predicate = predicate;
}
protected T PredicateMethod<T>(Func<T> trueMethod, Func<T> falseMethod)
{
return _predicate() ? trueMethod() : falseMethod();
}
protected void PredicateMethod(Action trueMethod, Action falseMethod)
{
if (_predicate())
trueMethod();
else
falseMethod();
}
}
You can use optional parameters is much better than spaghetti code!
public object Method(int i = -999)
{
if(i != -999){//Method #1
if (isThisTrue())
{
SomeMethod(i, 2, 3); // returns void
}
else
{
SomeMethod2(i, "TestString"); // returns void
}
}else{//Method #2
if (isThisTrue())
{
return OtherMethod(1, true);
}
else
{
return OtherMethod2(1, "RandomString", 2);
}
}
}
Related
Take this pseudo example code:
static System.Runtime.InteropServices.ComTypes.IEnumString GetUnmanagedObject() => null;
static IEnumerable<string> ProduceStrings()
{
System.Runtime.InteropServices.ComTypes.IEnumString obj = GetUnmanagedObject();
var result = new string[1];
var pFetched = Marshal.AllocHGlobal(sizeof(int));
while(obj.Next(1, result, pFetched) == 0)
{
yield return result[0];
}
Marshal.ReleaseComObject(obj);
}
static void Consumer()
{
foreach (var item in ProduceStrings())
{
if (item.StartsWith("foo"))
return;
}
}
Question is if i decide to not enumerate all values, how can i inform producer to do cleanup?
Even if you are after a solution using yield return, it might be useful to see how this can be accomplished with an explicit IEnumerator<string> implementation.
IEnumerator<T> derives from IDisposable and the Dispose() method will be called when foreach is left (at least since .NET 1.2, see here)
static IEnumerable<string> ProduceStrings()
{
return new ProduceStringsImpl();
}
This is the class implementing IEnumerable<string>
class ProduceStringsImpl : IEnumerable<string>
{
public IEnumerator<string> GetEnumerator()
{
return new EnumProduceStrings();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
And here we have the core of the solution, the IEnumerator<string> implementation:
class EnumProduceStrings : IEnumerator<string>
{
private System.Runtime.InteropServices.ComTypes.IEnumString _obj;
private string[] _result;
private IntPtr _pFetched;
public EnumProduceStrings()
{
_obj = GetUnmanagedObject();
_result = new string[1];
_pFetched = Marshal.AllocHGlobal(sizeof(int));
}
public bool MoveNext()
{
return _obj.Next(1, _result, _pFetched) == 0;
}
public string Current => _result[0];
void IEnumerator.Reset() => throw new NotImplementedException();
object IEnumerator.Current => Current;
public void Dispose()
{
Marshal.ReleaseComObject(_obj);
Marshal.FreeHGlobal(_pFetched);
}
}
I knew i can! Despite guard, Cancel is called only one time in all circumtances.
You can instead encapsulate logic with a type like IterationResult<T> and provide Cleanup method on it but its essentially same idea.
public class IterationCanceller
{
Action m_OnCancel;
public bool Cancelled { get; private set; }
public IterationCanceller(Action onCancel)
{
m_OnCancel = onCancel;
}
public void Cancel()
{
if (!Cancelled)
{
Cancelled = true;
m_OnCancel();
}
}
}
static IEnumerable<(string Result, IterationCanceller Canceller)> ProduceStrings()
{
var pUnmanaged = Marshal.AllocHGlobal(sizeof(int));
IterationCanceller canceller = new IterationCanceller(() =>
{
Marshal.FreeHGlobal(pUnmanaged);
});
for (int i = 0; i < 2; i++) // also try i < 0, 1
{
yield return (i.ToString(), canceller);
}
canceller.Cancel();
}
static void Consumer()
{
foreach (var (item, canceller) in ProduceStrings())
{
if(item.StartsWith("1")) // also try consuming all values
{
canceller.Cancel();
break;
}
}
}
Let's imagine that I have the following overloaded function:
void DoSomething(int x) { ... }
void DoSomething(float x) { ... }
void DoSomething(decimal x) { ... }
In the following method, I need to call the correct overload. This is how a simple implementation would look like:
void HaveToDoSomething(object data)
{
if (data is int) DoSomething((int)data);
else if (data is float) DoSomething((float)data);
else if (data is decimal) DoSomething((decimal)data);
}
This is tedious when there are ~20 types to check. Is there a better way of doing all this casting automatically?
Something I forgot to mention: DoSomething wouldn't work with generics, as each type needs to be handled differently, and I only know the type at runtime.
One possible approach would be to use dynamic:
void HaveToDoSomething(dynamic data)
{
DoSomething(data);
}
You can use Reflection but it can have a performance impact:
public class Example
{
void DoSomething(int i)
{
}
void DoSomething(float i)
{
}
}
public static class ExampleExtensions
{
public static void DoSomethingGeneric(this Example example, object objectParam)
{
var t = objectParam.GetType();
var methods = typeof(example).GetMethods().Where(_ => _.Name == "DoSomething");
var methodInfo = methods.Single(_ => _.GetParameters().First().ParameterType == t);
methodInfo.Invoke(example, new[] { objectParam });
}
}
The given function returns a KPI value, first it checks its cache, then it performs its logic, caches the result and returns a value, handling a failure condition.
How am I best to re-use the caching, error handling logic. What I essentially want to create is a function that just performs the necessary logic with boiler plate code abstracted away and re-used across multiple similar functions.
public static int CurrentEmployees()
{
if (HttpRuntime.Cache["CurrentEmployees"] == null)
{
try
{
int CurrentEmployees = Employee.Load().Count(x => x.DateFinished == null && !x.Contractor && x.DateStarted < DateTime.Now);
HttpRuntime.Cache.Insert("CurrentEmployees", CurrentEmployees, null, DateTime.Now.AddMinutes(20), new TimeSpan(0, 10, 0));
return CurrentEmployees;
}
catch(Exception e)
{
//TODO: Report this
return -1;
}
}
else
return (int)HttpRuntime.Cache["CurrentEmployees"];
}
As the boilerplate code is wrapped around the logic it is difficult for me to simply push these into other function calls.
Here's how you could create a generic method to cache whatever you want and reuse this logic.
public static T Cache<T>(string key, Func<T> loadFunction, Func<T> errorHandler)
{
if (HttpRuntime.Cache[key] == null)
{
try
{
T value = loadFunction();
HttpRuntime.Cache.Insert(key, value , null, DateTime.Now.AddMinutes(20), new TimeSpan(0, 10, 0));
return value;
}
catch(Exception e)
{
//TODO: Report this
return errorHandler();
}
}
else
return (T)HttpRuntime.Cache[key];
}
Usage:
public static int CurrentEmployees()
{
return Cache<int>("CurrentEmployees",
() => Employee.Load().Count(x => x.DateFinished == null && !x.Contractor && x.DateStarted < DateTime.Now),
() => -1);
}
Agree with answer from #DLeh but I would write it like this:
public static class HelperFunctions
{
public static Func<T> Cache<T>(this Func<T> inner, string cacheName)
{
return () =>
{
if (HttpRuntime.Cache[cacheName] == null)
{
var result = inner();
HttpRuntime.Cache.Insert(cacheName, inner(), null, DateTime.Now.AddMinutes(20), new TimeSpan(0, 10, 0));
return result;
}
return (T)HttpRuntime.Cache[cacheName];
};
}
public static Func<T> OnError<T>(this Func<T> inner, Func<Exception, T> onError)
{
return () =>
{
try
{
return inner();
}
catch (Exception e)
{
return onError(e);
}
};
}
}
Usage:
public static class Employees
{
public static int CurrentEmployees()
{
return (new Func<int>(() => Employee.Load().Count(x => x.DateFinished == null && !x.Contractor && x.DateStarted < DateTime.Now)))
.Cache("CurrentEmployees")
.OnError(e => -1)
();//TODO: log?
}
}
This way we separate caching logic from error handling (following single responsibility principle) and are able to reuse/compose each separately. So when you add another function like this you won't have to change Caching function.
This question already has answers here:
Is there a better alternative than this to 'switch on type'?
(31 answers)
Is it possible to use the instanceof operator in a switch statement?
(26 answers)
Closed 7 years ago.
I am trying to refactor a switch statement that is like this:
private void Validate(DataTypeEnum dataType, string value, ...)
{
switch(dataType)
{
case DataTypeEnum.Number:
var typedValue = int.Parse(value);
//Validation of typedValue
break;
case DataTypeEnum.Decimal:
var typedValue = Decimal.Parse(value);
//Validation of typedValue
break;
case DataTypeEnum.DateTime:
var typedValue = DateTime.Parse(value);
//Validation of typedValue
break;
}
}
I would like to get rid of the switch statement and somehow replace it with a more object oriented construct. Any suggestions?
My ideal would be something like this:
private void Validate(DataTypeEnum dataType, string value, ...)
{
Validate(value);
}
private void (Decimal value)
{
//Validate
}
private void (DateTime value)
{
//Validate
}
Is there any elegant way to fix this?
Use polymorphism.
Example:
public class DataType
{
public virtual void Validate()
{
Console.WriteLine("Performing base class validation tasks");
}
}
class Foo : DataType
{
public override void Validate()
{
// Code to validate a foo...
Console.WriteLine("Validating a foo");
}
}
class Bar : DataType
{
public override void Validate()
{
// Code to validate a bar...
Console.WriteLine("Validating a bar");
}
}
List<DataType> datatypes = new List<DataType>();
datatypes.Add(new Foo());
datatypes.Add(new Barr());
foreach (DataType s in datatypes)
{
s.Validate();
}
To add to this, while some might consider this not OOP at all, you can use dynamic overloads to handle this:
public bool ValidateAny(dynamic val)
{
return Validate(val);
}
private bool Validate(string val) { ... }
private bool Validate(int val) { ... }
private bool Validate(decimal val) { ... }
private bool Validate(object val) { ... } // This is the fallback
Basically, this works the same as usual overload resolution, but it's performed at runtime, depending on the runtime type of the val in ValidateAny.
For example:
ValidateAny(3); // Uses the int overload
ValidateAny((object)3); // Uses the int overload as well - dynamic handles the unboxing
ValidateAny(3M); // Uses the decimal overload
ValidateAny(3.ToString()); // Uses the string overload
ValidateAny(3f); // Uses the object overload, since there's no better match
This is incredibly powerful, as long as you only ever need to have different validations for different types. If you also have other considerations, this must at some level go back to if/switch. Even then it can save you a lot of time, though.
First of all I'd start with implementing simple interface for validation:
public interface IValidator
{
bool Validate(object value);
}
Then number validator may look like this:
public class NumberValidator : IValidator
{
public bool Validate(object value)
{
return (int) value > 0;
}
}
And final step replacing your switch with dictionary:
var _validators = new Dictionary<DataTypeEnum, IValidator> // injected via DI
{
{ DataTypeEnum.Number, new NumberValidator() },
{ DataTypeEnum.DateTime, new DateTimeValidator() },
{ DataTypeEnum.String, new StringValidator() }
};
......
private bool Validate(DataTypeEnum dataType, object value, ...)
{
if (_validators.ContainsKey(dataType))
{
return _validators[dataType].Validate(value);
}
return false;
}
public interface IValidator
{
void Validate(object value);
}
public class NumberValidator : IValidator
{
public void Validate(object value)
{
//implementation
}
}
public class DecimalValidator : IValidator
{
public void Validate(object value)
{
//implementation
}
}
public class DatetimeValidator : IValidator
{
public void Validate(object value)
{
//implementation
}
}
private void Validate(IValidator validator, object value)
{
validator.Validate(value);
}
Create a Dictionary that has DataTypeEnum as Key and Action as Value. Then Get the Value from Dictionary by Key and Invoke The action.
private readonly Dictionary<DataTypeEnum , Action > Validator = new Dictionary<DataTypeEnum , Action >
{
{ DataTypeEnum.Number, () => Validate(Convert.ToDouble((string)value)) },
{ DataTypeEnum.Decimal, () => Validate(Convert.ToDecimal((string)value)) },
{ DataTypeEnum.DateTime, () => Validate(Convert.ToDateTime((string)value)) },
// ...
}
private void Validate(DataTypeEnum dataType, object value, ...)
{
Validator[dataType](); // Gets the Action and Invokes it
}
private void Validate (Decimal value)
{
//Validate
}
private void Validate (DateTime value)
{
//Validate
}
//...
Here the Action is Void delegate that takes no parameters. It will convert value to suitable format and calls Validate Method.
private void Validate<T>(T value) where T : IComparable
{
if(value is Number)
{
}
if(value is Decimal)
{
}
if(value is DateTime)
{
}
}
How about something like this:
private void Validate(object value, ...)
{
if(Reference.Equals(null, value)
return;
if(value is Number)
{
}
else if(value is Decimal)
{
}
else if (value is DateTime)
{
}
else return;
}
If the value passed in is either Number, Decimal or DateTime it will run the appropriate method, other wise it will simply return.
For example the main method I want to call is this:
public static void MasterMethod(string Input){
/*Do some big operation*/
}
Usually, I would do something like this this:
public static void StringSelection(int a)
{
if(a == 1)
{
return "if";
}
else
{
return "else";
}
}
MasterMethod(StringSelection(2));
But I want to do something like this:
MasterMethod( a = 2
{
if(a == 1)
{
return "if";
}
else
{
return "else";
}
});
Where 2 is somehow passed into the operation as an input.
Is this possible? Does this have a name?
EDIT:: Please note, the MasterMethod is an API call. I cannot change the parameters for it. I accidentally made a typo on this.
You can do this via delegates in C#:
public static string MasterMethod(int param, Func<int,string> function)
{
return function(param);
}
// Call via:
string result = MasterMethod(2, a =>
{
if(a == 1)
{
return "if";
}
else
{
return "else";
}
});
You can do this with anon delegates:
delegate string CreateString();
public static void MasterMethod(CreateString fn)
{
string something = fn();
/*Do some big operation*/
}
public static void StringSelection(int a)
{
if(a == 1)
{
return "if";
}
else
{
return "else";
}
}
MasterMethod(delegate() { return StringSelection(2); });
anonymous methods
Yes, use a delegate. Which include Lambda Expressions and anonymous methods
I think you're looking for a delegate.