I apologize if I'm posting into the wrong community, I'm quite new here.
I have multiple methods using the same foreach loop, changing only the inner method I call:
public void CalculationMethod1()
{
foreach (Order order in ordersList)
{
foreach (Detail obj_detail in order.Details)
{
CalculateDiscount(obj_detail);
}
}
}
public void CalculationMethod2()
{
foreach (Order order in ordersList)
{
foreach (Detail obj_detail in order.Details)
{
CalculateTax(obj_detail);
}
}
}
Each inner method has different logic, database search, math calculations (not important here).
I'd like to call the methods above without repeating the foreach loop everytime, so I throught about the solution below:
public void CalculateMethod_3()
{
foreach (Order obj_order in ordersList)
{
foreach (Detail obj_detail in order.Details)
{
CalculateDiscount(obj_detail);
CalculateTax(obj_detail);
}
}
}
But I fall into a rule problem:
class Program
{
static void Main(string[] args)
{
Calculation c = new Calculation();
c.CalculateMethod_3();
c.AnotherMethod_4(); //It doesn't use objDetail
c.AnotherMethod_5(); //It doesn't use objDetail
c.CalculateMethod_6(); //Method 6 needs objDetail but respecting the order of the methods, so It must be after AnotherMethod_4 and AnotherMethod_5
}
}
How can I create a method to achieve my objective (I don't want to repeat code) respecting the rule above?
You can always pass a delegate to the method and then you can do basically whatever you want.
public void ApplyToDetails(Action<Detail> callback)
{
foreach (Order order in ordersList)
{
foreach (Detail obj_detail in order.Details)
{
callback(obj_detail);
}
}
}
Then to use you'd do something like this
ApplyToDetails(detail => CalculateTax(detail));
ApplyToDetails(detail =>
{
CalculateDiscount(detail);
CalculateTax(detail);
});
Delegates come in very handy in many cases and definitely in such a case. I know this has already been answered and rightly so, but here is an alternative for comparison. I have provided a link to give you some insight.
public class CalculationMethods
{
public delegate void CalculationDelegate(Detail method);
private Dictionary<string, CalculationDelegate> _methods;
public CalculationMethods
{
this._methods = new Dictionary<string, CalculationDelegate>()
{
{ "Discount", CalculateDiscount },
{ "Tax", CalculateTax }
};
}
public void Calculate(string method, Detail obj_detail)
{
foreach (Order order in ordersList)
{
foreach (Detail obj_detail in order.Details)
{
var m = this._methods.FirstOrDefault(item => item.Key == method).Value;
m(obj_detail);
}
}
}
}
Usage:
//Initialize
var methods = new CalculationMethods();
//Calculate Discount
methods.Calculate("Discount", obj_detail);
//Calculate Tax
methods.Calculate("Tax", obj_detail);
Side Note:
I would recommend some exception handling in case the method of calculation isn't found among the list of delegates. Example below: (Replace the calculate method with the following.)
public void Calculate(string method, Detail obj_detail)
{
foreach (Order order in ordersList)
{
foreach (Detail obj_detail in order.Details)
{
var m = this._methods.FirstOrDefault(item => item.Key == method).Value;
//Check if the method was found
if (m == null)
throw new ApplicationNullException("CalculationDelegate")
m(obj_detail);
}
}
}
Decent tutorial:
Delegates and Events
You can use delegates. (Google it - I don't have a development environment in front of me to run up a sample for you). Basically one method that takes a delegate to call:
Here is pseudo code...
public void CalculationMethod(delegate myFunction) // need to look up correct param syntax
{
foreach (Order order in ordersList)
{
foreach (Detail obj_detail in order.Details)
{
myFunction(); // Need to lookup correct calling syntax
}
}
}
I googled "c# delegate as parameter" and came up with http://msdn.microsoft.com/en-us/library/ms173172.aspx which seems to be a reasonable explanation.
As Darren Kopp says, you can use delegates. However, in the case that you are calling a method with a parameter, you can call it directly (you don't need the lambda expression).
With public void ApplyToDetails(Action<Detail> callback) { ... }:
ApplyToDetails(Method_1); // Uses objDetail
ApplyToDetails(d => Method_2()); // Doesn't use objDetail
ApplyToDetails(d => Method_3()); // Doesn't use objDetail
ApplyToDetails(Method_4); // Uses objDetail
Note that you must not place parameter braces after the methods you pass as delegate!
You could use delegates as the other answers have provided but I believe in your case doing so will lead to overly confusing code. Your code is cleaner and more readable if you redeclare the foreach loops in each method. Only if you were copy-pasting portions of the internals would I say you run the risk of code duplication.
Think about it this way: If you created a method passing in a delegate, what would the name of this method be called? It is a method that does something for each Detail in each Order you pass in and should be named something like DoSomethingForEachDetailInOrders(). What kind of class would this method exist for? You don't know what it is you're actually doing in the delegate, so the purpose of this class would have to be more framework-style code, which your app does not appear to be complex enough to warrant.
Additionally, if you were debugging this code or reading through it, instead of being able to see 2 foreach loops inside the method you are reading, you have to go scroll to the definition of the delegate, read that, and then go back to your method and resume reading.
Edit: I originally answered this question by downplaying the duplication of the foreach loops in the hopes that OP would not add additional complexity to his app attempting to make it follow "best practices." I didn't go deeper because the code requires a more intrusive refactor for maintainability. The foreach loop code smell stems from other problems as detailed in the comments below this answer. I still stand by my opinion that adding the delegate method is less desirable than the duplicated loops because the delegate method option is pretty much textbook boilerplate.
Added a code example to explain how the code should be refactored if maintainability is a concern:
public decimal CalculateDiscount(IEnumerable<Order> ordersList)
{
return ordersList.SelectMany(order => order.Details).Sum(detail => detail.Discount);
}
public decimal CalculateTax(IEnumerable<Order> ordersList)
{
return ordersList.SelectMany(order => order.Details).Sum(detail => detail.Total) * taxRate;
}
If you ABSOLUTELY MUST HAVE a custom function for getting all details for orders (could be refactored to an extension method):
public IEnumerable<Detail> GetDetailsForOrders(IEnumerable<Orders> orderList)
{
foreach(var order in orderList)
{
foreach (var detail in order.Details)
{
yield return detail;
}
}
}
public decimal CalculateDiscount(IEnumerable<Order> ordersList)
{
return GetDetailsForOrders(ordersList).Sum(detail => detail.Discount);
}
public decimal CalculateTax(IEnumerable<Order> ordersList)
{
return GetDetailsForOrders(ordersList).Sum(detail => detail.Total) * taxRate;
}
Related
In C#, How can I simplify GetData1() and GetData2() to one line function only?
Please see comments in GetData1 and GetData2, originally I have two write 3 lines in each function, but would like to use GetDataCore to simplify it.
public IEnumerable<int> GetDataCore(function passInFunction)
{
// many other steps
foreach (var sensor in sensors)
{
yield return sensor.passInFunction();
}
}
public IEnumerable<int> GetData1()
{
// many other steps
// TODO: use something like
// return GetDataCore(GetData1);
foreach (var sensor in sensors)
{
yield return sensor.GetData1();
}
}
public IEnumerable<int> GetData2()
{
// many other steps
// TODO: use something like
// return GetDataCore(GetData1);
foreach (var sensor in sensors)
{
yield return sensor.GetData2();
}
}
There's no need to write your own method to project all of the items in a sequence using a selector passed as a delegate. LINQ created such a method for you, called Select:
public IEnumerable<int> GetData1() {
return sensors.Select(sensor => sensor.GetData1());
}
But, to answer your question anyway, if function was a Func<Sensor, int>, then you could pass in a method that takes a sensor and transforms it into an integer, which you could do in each of your GetDataX methods, most likely using a lambada, as shown above.
I have a piece of code like this.
I write this because I love extension methods and lambda expression:
public static class TuneingRules
{
public static Func<HtmlNode, bool> IsNodeHavingClearNone = (node) =>
{
if (node.HasAttributes)
{
// HtmlAttribute atr = item.Attributes.Where(at => at.Name == "id" && at.Value == "hello").FirstOrDefault();
HtmlAttribute atr = node.Attributes.Where(at => at.Name == "style").FirstOrDefault();
if (atr != null)
{
return Regex.Match(atr.Value, "clear\\s*:\\s*none;").Success;
}
}
return true;
};
}
and extension method like this.
public static class ExtensionMethods
{
#region Ignoring Rules
public static bool Ignore(this HtmlNode Node, Func<HtmlNode,bool> func) {
return func(Node);
}
#endregion
}
now I have two approaches to use this piece of code..
1 case
if (!htmlNode.Ignore(TuneingRules.IsNodeHavingClearNone)){
//then do somethings
}
// here i am open to write lambda expression like this.
if (!htmlNode.Ignore( node => node.innerText =="" ){
//then do somethings
}
2 case
if (!TuneingRules.IsNodeHavingClearNone(htmlNode)) {
//then do something
}
I'm afraid that there are any performance issues if TuneingRules
has many static Func<HtmlNode,bool> objects. Do i need to refactor my code?
In the first case there is an extra call going through ignore function...
but in the second case i can call the function object directly.
Or is there another way to write this code in order to stick with lambda as well as extension methods?
No, there is no performance issue.
There will be a small performance hit the first time that you use the TuneingRules class, as the static constructor will be called and initialise all the static variables. That should however be quite small compared to the actual work that the function does.
Likewise, doing one extra method call is negligible compared to the work that the function does. It's even possible that the extension method call will be inlined by the JIT compiler, so that the executed code will actually do the same thing as in your second case.
I have just familiarized myself a little bit with C# delegates. One can subscribe multiple delegate instances to a delegate by the "+=" operator. But is it also possible to have a controller class that has delegates for all the methods in second class, and have the methods being added automatically, i.e. without having to add (or even know) each method individually to the corrsponding delegate ?
In simplified code (omitting access modifiers etc.):
class Car
{
void Start();
void Drive();
}
// I would like to have the following class generated automatically
// without needing to repeat all the methods of Car, i.e.
// without declaring a delegate instance for each of them
class CarController
{
delegate void DoSomething();
DoSomething StartAll;
DoSomething DriveAll;
void Subscribe(Car anotherCar)
{
StartAll += anotherCar.Start;
DriveAll += anotherCar.Drive;
}
}
EDIT:
Rawling's solution is the one that I like best. It's simple and clear. As a little tweak I have tried how the thing would work with dynamically typed objects, and it works indeed: complete decoupling between Controller and controlled objects. Of course such usage of "dynamic" is not of everyone's taste...
public class CallAller2 : HashSet<dynamic>
{
public void CallAll(Action<dynamic> action)
{
foreach (dynamic t in this)
{
try {action(t);} catch (RuntimeBinderException) {};
}
}
}
class Bike
{
void Drive();
}
CallAller2 ca = new CallAller2();
ca.Add(new Car());
ca.Add(new Bike());
ca.CallAll(c => c.Start()); // is ignored by Bike which does not implement it
ca.CallAll(c => c.Drive());
Now I realise this is just essentially recreating the much-maligned List<T>.ForEach. Why not just use that, since it's there?
Although it doesn't give you the ability to just call .StartAll or .DriveAll, you could do something as simple as
class CallAller<T> : HashSet<T>
{
public void CallAll(Action<T> action)
{
foreach (T t in this)
{
action(t);
}
}
}
var ca = new CallAller<Car>();
ca.Add(myFirstCar);
ca.Add(mySecondCar);
// Call a simple function
ca.CallAll(c => c.Start());
// Call a function taking parameters
ca.CallAll(c => c.SetRadio(88.1, RadioType.FM));
// Get return values... if you really need to.
Dictionary<Car, int> returnValues = new Dictionary<Car, int>();
ca.CallAll(c => returnValues.Add(c, c.GetNumberOfTyres()));
If you want something with actual methods to call and Intellisense, you'll need to look into code generation - it's possible, but I doubt it'd be worth the hassle.
I think this should work:
//Edit: Don't simplify the MethodInfo mi1 = mi, otherwise you get a problem called Access to modified closure
static IList<Action> getDelegatesFromObject(Object obj)
{
Type type = obj.GetType();
List<Action> Actions = new List<Action>();
foreach (MethodInfo mi in type.GetMethods())
{
MethodInfo mi1 = mi;
Actions.Add(
() => mi1.Invoke(obj, new object[] {})
);
}
return Actions;
}
I'm trying to iterate a list of items. The items are all part of a common interface. They are as described in this question. I want to use a foreach loop to go through them, but execute different actions depending on what type it is.
For simplicity's sake, let's say the actions I want to execute are as follows:
ProcessLine(MachineLine ML); //For MachineLines
ProcessLine(MachineCircle MC); //For MachineCircles
How can this iteration be accomplished to account for the multiple data types?
I would seriously consider if this is the most appropriate design in this context. Are you sure the IMachine interface shouldn't have a Process method? Each machine could implement this as appropriate, and then the loop just becomes:
foreach (IMachine machine in machines)
{
machine.Process();
}
Anyway, to answer the question as asked, here's one way to do it. The idea is to keep trying a "speculative cast" to a target-type until it succeeds or we are out of options. This is normally done with the as operator, followed by a null-test.
IList<IMachine> machines = ...
foreach (IMachine machine in machines)
{
MachineLine machineLine = machine as MachineLine;
if (machineLine != null)
ProcessLine(machineLine);
else
{
MachineCircle machineCircle = machine as MachineCircle;
if (machineCircle != null)
ProcessCircle(machineCircle);
else throw new UnknownMachineException(...);
}
}
As you can see, this pattern is ugly. For a cleaner solution, you might also want to take a look at C# - Is there a better alternative than this to 'switch on type' if there are a large number of implementers.
The best way to handle this IMHO is to have the types inherit from a common base class/interface which has a method that does the action you want. Then call the common method within the loop. In your case, I would make it a base class instead since these are is-a relationships and add the ProcessLine() method to the base class.
public abstract class MachineShape
{
public abstract void ProcessLine();
}
public class MachineLine : MachineShape
{
public override void ProcessLine()
{
// implement for MachineLine
}
public double X1;
public double Y1;
public double X2;
public double Y2;
public double Thickness;
}
public class MachineCircle : MachineShape
{
public override void ProcessLine()
{
// implement for MachineCircle
}
public double CenterX;
public double CenterY;
public double Radius;
}
MachineShape[] shapes = ...;
foreach (var shape in shapes)
{
shape.ProcessLine();
}
Let polymorphism do the work for you.
Assuming you have defined the proper overloads for ProcessLine(), you simply test the types of these objects during each iteration, and then cast accordingly and call the method. Something like this:
foreach (IMachine m in machineList) {
if (m is MachineLine) {
ProcessLine((MachineLine) m);
} else if (m is MachineCircle) {
ProcessLine((MachineCircle) m);
}
}
To improve your program design, you may wish to consider the other suggestions here (add a Process() method to your interface, etc).
List<IMachine> m = new List<IMachine>();
foreach ( IMachine machine in m) {
if (m is MachineLine) {
ProcessLine( m as MachineLine );
}
else if (m is MachineCircle) {
ProcessLine( m as MachineCircle );
}
}
foreach (var m in list){
if (m is MachineLine) ProcessLine((MachineLine) m);
else if (m is MachineCircle) ProcessLine((MachineCircle) m);
}
You should change your ProcessLine method to accept an IMachine instead, and make it call different methods depending on the type. It will make the code clearer, and you might reuse the logic somewhere else later on. Like this:
foreach (IMachine m in machineList)
ProcessLine(m);
The code in ProcessLine would look like:
void ProcessLine(IMachine machine)
{
if (machine is MachineLine)
ProcessMachineLine(MachineLine)
else if (machine is MachineCircle)
ProcessMachineCircle(MachineCircle)
}
This also sounds like a nice candidate for the Visitor design pattern...
http://en.wikipedia.org/wiki/Visitor_pattern
Jeff's solution is the first choice, alternatively, if it's too much for you to change now, you can also use function overloading as well.
foreach (IMachine m in machineList){
//sorry I can't test it since I don't have visual studio installed.
//but you get the idea
ProcessLine((m.getType())m);
}
function ProcessLine(MachineLine m)
{
...
}
function ProcessLine(MachineCircle m)
{
....
}
you can either use the keyword dynamic , if you are working in .net 4.0
foreach (dynamic m in machineList) {
if(m.GetType()==typeof(MachineLine))
{
// code goes here
}
else if(m.GetType()==typeof(MachineCircle))
{
// code goes here
}
}
I have a class that creates a List<Action<int>> and holds on to them until a later time. This class can add and remove delegates from this list. This works well as long as people don't get too fancy. To combat anonymous function (which can't be removed) I check against the target of the delegate being null. If its null I throw an exception. The problem comes in when there is an anonymous delegate that contains a function. This has a target, but is just as unremovable. The simplified code below illustrates my issues
public class MyDelegateContainer
{
List<Action<int>> m_Container = new List<Action<int>>();
public void Add(Action<int> del)
{
if (del.Target == null)
{
throw new Exception("No static handlers");
}
m_Container.Add(del);
}
public bool Remove(Action<int> del)
{
if (m_Container.Contains(del))
{
m_Container.Remove(del);
return true;
}
return false;
}
}
public class MyFakeActionClass
{
public void Test(int temp) { }
}
class Program
{
static void Main(string[] args)
{
bool removed = false;
int counter = 0;
MyDelegateContainer container = new MyDelegateContainer();
MyFakeActionClass fake = new MyFakeActionClass();
//container.Add(p => { }); //Throws, this is what I want to happen
container.Add(fake.Test); //Works, this is the use case
removed = container.Remove(fake.Test); //Works, this is the use case
Debug.Assert(removed);
container.Add(p => { fake.Test(p); counter++; }); //Works but I would like it not to
removed = container.Remove(p => { fake.Test(p); counter++; }); //doesn't work
Debug.Assert(removed);
}
}
I need some way to identify
p => { fake.Test(p); counter++; }
is an anonymous function so I can throw if someone tries it. Thanks for any help
EDIT: I should note that I could use an Action<int> variable for the anonymous function and everything would work, but the Add and Remove are never in the same scope in practice.
In your example, the caller is responsible from removing the handler. So, if the caller doesn't want to remove the handler, it won't get removed, no matter if the handler is an anonymous delegate/lambda or not.
My suggestion is to change the delegate container to something like this:
public class MyDelegateContainer
{
List<Action<int>> m_Container = new List<Action<int>>();
public Action Add(Action<int> del)
{
m_Container.Add(del);
return new Action(() =>
{
m_Container.Remove(del);
});
}
}
The caller is still responsible for removing the handler, but instead of passing the handler again to the container, it receives a "token" that it can save and use later to remove the handler.
There is no way to reliably determine whether a function is "anonymous" because all functions have names to the CLR. It's only anonymous within the language that generates it, and that's compiler-dependent. You may be able to determine the algorithm used by Microsoft's current C# compiler, only to have it stop working on C# 5 or Mono.
Since you want to prevent users of your type from writing code that uses it wrong, you just need to throw an exception at some point that will make their program crash. What I would do is throw the exception in the Remove function when the target delegate isn't found. At that point your users will still get a crash and the only way to fix it is to write the delegate in some way that it's removable.
As an added bonus, you will catch bugs where somebody tries to remove delegates twice or that were never added in the first place. The code would look like this:
public bool Remove(Action<int> del)
{
if (m_Container.Contains(del))
{
m_Container.Remove(del);
return true;
}
throw new ArgumentException("Attempt to remove nonexistent delegate");
}
I would use introspection to check the names of the methods.
Anonymous methods typically have very predictable names. (I don't remember the exact format, but run some tests, and it should be obvious).
The drawback would be that if anyone created a non-anonymous method, but decided to name it anonMethod123 (or whatever the format is...) It would be falsely rejected.
Of course you can remove an anonymous method, you just need to have a reference to the same anonymous method.
var myAnonymousMethod = p => { fake.Test(p); counter++; };
container.Add(myAnonymousMethod);
removed = container.Remove(myAnonymousMethod);
As jonnii suggested in a comment, another way you could implement it is with a dictionary:
public class MyDelegateContainer
{
Dictionary<string, Action<int>> m_Container =
new Dictionary<string, Action<int>>();
public void Add(string key, Action<int> del)
{
m_Container.Add(key, del);
}
public bool Remove(string key)
{
return m_Container.Remove(key);
}
}
Then you could easily remove a known delegate at some arbitrary point in your code just by knowing what name was used to add it:
container.Add("fake.Test", fake.Test);
removed = container.Remove("fake.Test");
Debug.Assert(removed);
container.Add("anon", p => { fake.Test(p); counter++; });
removed = container.Remove("anon"); // works!
Debug.Assert(removed);
Old question I know but I would think that this would be a current (and future) proofed way of checking if a method is anonymous:
bool isAnonymous = !System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(del.Method.Name);
The runtime name of the anonymous method would have to be invalid if used at compilation time to ensure that it didn't clash.