Good evening,
I was wondering if I could do something like:
while(true)
{
MyEnum currentValue = GetMyEnumValueFromDB();
if(currentValue == MyEnum.BreakIfYouGetThis)
break;
else if(currentValue == MyEnum.AlsoBreakIfYouGetThis)
break;
else
//Do some computing
}
But instead of having a while(true) loop, I'd want to encapsulate the conditional logic in a Func and execute it like this:
while(new Func<bool>(/* what goes here? */))
{
//Do some computing
}
In my case at least, it would look much cleaner, but i'm not sure how to do it (kinda new at Func/Action..).
EDIT hope this clarifies:
It could also be done like this:
while(GetMyEnumValueFromDB() != MyEnum.BreakIfYouGetThis &&
GetMyEnumValueFromDB() != MyEnum.AlsoBreakIfYouGetThis)
{
//Do some computing
}
But that's 2 call to the database...
Thanks =)
Well you could have:
Func<bool> condition = ...;
while (condition())
{
}
Is that what you're thinking of? It's not really clear...
EDIT: In the example you've given, I'd use something like:
private static readonly MyEnum[] BreakEnumValues = {
MyEnum.BreakIfYouGetThis,
MyEnum.AlsoBreakIfYouGetThis
};
...
while (!BreakEnumValues.Contains(GetMyEnumValueFromDB()))
{
...
}
Or:
private static bool ShouldBreak(MyEnum enumFromDatabase)
{
return enumFromDatabase == MyEnum.BreakIfYouGetThis ||
enumFromDatabase == MyEnum.AlsoBreakIfYouGetThis;
}
...
while (!ShouldBreak(GetMyEnumValueFromDB))
{
...
}
EDIT: To counter KeithS's answer, this is entirely valid:
while (new Func<bool>(() => {
Console.WriteLine("Evaluating...");
return true;
})()) {
Console.WriteLine("In loop");
count++;
if (count == 5)
{
break;
}
}
It's horrible, but it's valid. (It can be made slightly less horrid by explicitly calling Invoke, but it's still not nice.)
You could do that, but if you don't have a compelling reason to do so (like you're passing the condition function in as a parameter), I'd just wrap your logic in a function and call it directly:
while(KeepGoing())
{
//Do stuff
}
bool KeepGoing()
{
// Check conditions for continuing
var value = GetMyEnumValueFromDB();
return value != MyEnum.BreakIfYouGetThis && value != MyEnum.AlsoBreakIfYouGetThis;
}
First off, a database call in a while loop is a bad idea. Query what you'll need beforehand and loop accordingly.
It appears that polymorphism can be your friend here. If you need to keep the same flow, you can do something like this:
interface IWhileLoopContinuable
{
bool KeepGoing {get;}
void DoWork();
}
Then you can use TakeWhile on this enumerable:
foreach(var item in queriedAsIWhileLoopContinuable.TakeWhile(c => c.KeepGoing))
{
item.DoWork();
}
All that being said, you could just query for what you want and work on that.
Well, first off you cannot "new" a Func, just like you can't new up any delegate type. You must instead assign an existing named method or function literal (aka anonymous delegate, lambda, etc) to initialize a Func variable.
//these won't compile; Func has no constructor
Func<bool> condition = new Func<bool>();
//As Jon Skeet notes, these will compile because of language-provided syntax,
//even though Funcs have no constructor with a delegate parameter.
Func<bool> condition = new Func<bool>(SomeNamedMethodReturnsBool);
Func<bool> condition = new Func<bool>(()=>true);
//and these will compile because you're directly assigning the delegate
Func<bool> condition = SomeNamedMethodReturnsBool;
Func<bool> condition = ()=>true;
You actually cannot do what you want in C#; an anonymous delegate must be assigned to a variable or parameter in order to be used. It cannot be used in-place as a "function literal" in the abstract sense.
Even if you could, the utility of such a statement escapes me. The delegate would not be re-instantiated every time (the compiler turns anonymous delegates into named private functions of the containing class, with mashup names), but you're adding a layer onto the call stack just to evaluate a constant expression that could be placed directly into the parenthesis of the while() statement. The main utility of an anonymous delegate would be that you could swap out lambdas at runtime, and in order to do that you MUST have a variable.
Related
Is there a design pattern that can be applied where I can build sophisticated workflows without having to write multiple conditional and nested conditional statements - I think the answer may lie somewhere in employing something like the Specification Pattern but am unsure how it comes together in C#?
static void Main()
{
// I have some predicates
bool transientError = true;
bool fatalError = true;
bool maxRetriesReached = true;
// I have some actions
Action SendToDeadletter = () => { };
Action Retry = () => { };
Action Complete = () => { };
// Is there a way of building the following without using conditional statements
// something like Specification Pattern?
// maxRetriesReached || fatalError => SendToDeadletter()
// transientError && !maxRetriesReached => Retry()
// !transientError && !fatalError => Complete()
}
You can define your conditions as an enum (or a struct have more expandability):
[Flags]
public enum WorkflowFlags
{
SendToDeadletter,
Retry,
Continue
}
And then define workflow items with a method, say ShouldExecute that takes in the flags and returns true/false if the item should be ran.
public class MyWorkflowItem : IWorkflowItem
{
public bool ShouldExecute(WorkflowFlags flags)
{
return (flags & WorkflowFlags.Retry) != 0;
}
}
You could probably use the Specification Pattern to code your logic
There is a c# example on how to do this here
https://en.wikipedia.org/wiki/Specification_pattern
You probably found plenty of example online.
With your explanations I fail to understand the why you would use the Specification Pattern to code you logic.
At a point you are forced to use a conditional statement.
It seems like you may want something like that however.
public static void Reaction(this Func<bool> condition, Action conditionMet,Action conditionUnmet)
{
condition() ? conditionMet() : conditionUnmet();
}
Using it the following way
Func<bool> CanDoAction = ()=> false;
Action behaviorAction = ()=> DoStuff;
Action behaviorUnableToDoAction = ()=> DoOtherStuff;
CanDoAction.Reaction(behaviorAction ,behaviorUnableToDoAction );
Honestly, I think you're barking up the wrong tree. You can combine conditionals into a single specification to encapsulate them, or you can create different specs for different conditionals to name them, but I think other patterns are more appropriate - If I am inferring your need correctly.
You want to implement "sophisticated workflows". To me, this is saying you want to implement business use cases that have lots of branching points. For those, some form of the Strategy pattern is the best place to start.
How can I go about doing this so if the "if" statement is true, to skip the code below the foreach loop and to go on with the rest of the program
void()
{
foreach()
{
if()
{
}
}
//code I want to skip if "if" statement is true
}
There's no way to directly do what you want (without "goto" labels -- perish the thought!), but you can use the "break" keyword, and set a variable you can refer to later.
void()
{
var testWasTrue = false;
foreach()
{
if()
{
testWasTrue = true;
break; // break out of the "foreach"
}
}
if( !testWasTrue ) {
//code I want to skip if "if" statement is true
}
}
I know this was already answered, but I figured I'd throw in my 2 cents since nobody considered abstracting the check to a separate method:
void()
{
if (ShouldDoStuff(myCollection))
DoStuff(myCollection);
else
DoOtherStuff(myCollection);
}
private bool ShouldDoStuff(collection)
{
foreach()
{
if ()
return true;
}
return false;
}
This provides a much cleaner code at the higher level for dealing with your algorithms and removes all the clutter discussed about. It cleanly separates the tasks in void() of checking and performing the actions and readers instantly know exactly what the program flow is without having to discern what they're doing with a boolean or break logic lurking about. No single method has more than 1 responsibility or task.
Yeah, it's possible the poster wants to do other work in their foreach, but that's an entirely different discussion and not what was described in their question. If you simply want to check if the given collection (or object) satisfies a certain condition, that check can be moved to a separate method. Even leaves the door open for automated unit tests for all three components.
Even if DoStuff and DoOtherStuff are not abstracted to their own methods, it provides nicer readability and logical flow.
void()
{
bool process = true;
foreach()
{
if()
{
process = false;
break;
}
}
if (process)
{
//code I want to skip if "if" statement is true
}
}
As was mentioned in my comment you may do this through extra bool variable.
void()
{
bool positiveResult; // by default it gets false value
foreach()
{
if()
{
positiveResult = true;
// you may use "break" to skip the loop
break;
}
}
if( !positiveResult )
{
//code I want to skip if "if" statement is true
}
}
The 'break' keyword will break out of the loop.
foreach (someClass a in someArray)
{
if(a.someProperty) // bool property
{
//Stuff to do if that condition is true
doSomethingElse();
//Calling the break keyword will stop the loop and jump immediately outside of it
break;
}
//Other code to run for each iteration of the loop
}
//Here is where execution will pick up either after break is called or after the loop finishes
Only way I know how is a bool flag.
void()
{
bool x = false;
foreach()
{
if()
{
x = true;
break;
}
}
if(!x)
{
//Code to skip if "if" statement is true.
}
}
Not super elegant, but easy.
Edit: beat by 12 secs :)
void()
{
bool skip = false;
foreach()
{
if()
{
skip = true;
}
}
if(!skip)
{
//code I want to skip if "if" statement is true
}
}
If the collection you are iterating through contains The IEnumerable Interface, You could use Any() with a Lambda!
int[] myArray = { 1, 2, 3 };
if( myArray.Any((a) => a == 1) )
{
return;
}
It is read: if my array contains any value a where a is equal to 1, then return out of this function.
Plus if you want to make it harder to read, you can omit the curly braces/brackets.
if( myArray.Any((a) => a == 1) )
return;
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
Is this way of writing IF conditions considered good coding style in Java and C# languages or not?
if (checkIfIdInFirstRange()){
//call Range1 handling method
}else if(checkIfIdInSecondRange()){
//call Range2 handling method
}else{
//call error handling method
}
I'm wondering about the method inside the IF condition itself, or would it be better to make it like:
int idInRange = getIdInRange();
//handle isInRange
I think this is fine.
Even better is if you phrase your methods like a question, or flows with the if statement
if (thisConditionIsTrue()){
// Do this
}elseif(anotherConditionIsTrue()){
// Do this instead
}elseif(isThisParameterOkay(someParameter)){
// Yeh do this
}
Some hardcore purists will even say that if you have > 3 levels of indentation, your method is too nested and should be split into smaller methods.
Doing this is IMHO good coding practice as long as the method calls don't have any side effects.
e.g.
if checkIfIdInFirstRange() this is OK:
private bool checkIfIdInFirstRange()
{
return firstRange.Contains(ID);
}
But doing this might create confusion:
private bool checkIfIdInFirstRange()
{
SomeStringProperty = "totally new value that no caller would ever expect after a call to this method";
return firstRange.Contains(ID);
}
Another possible solution - depending on the actual type of your problem at hand - could be to define an interface / base class and use polymorphism.
example:
internal abstract class A
{
public void DoSomething(int ID)
{
if(IsInRange(ID))
DoSomethingProtected(ID);
}
protected abstract bool IsInRange(int ID);
protected abstract void DoSomethingProtected(int ID);
}
internal class B : A
{
private List<int> firstRange = new List<int> { 42, 23, 5};
protected override bool IsInRange(int ID)
{
return firstRange.Contains(ID);
}
protected override void DoSomethingProtected(int ID)
{
Console.WriteLine("{0}", ID);
}
}
public class Program
{
public static void Main(string[] args)
{
B foo = new B();
foo.DoSomething(3);
foo.DoSomething(42);
}
}
CAUTION: code written without IDE to hand.
Yes. It would be much more readable if you used just a little whitespace. Bunching it up like that makes it hard to tell where things begin and end and makes else if() look like a function call.
if ( checkIfIdInFirstRange() ) {
//call Range1 handling method
}
else if ( checkIfIdInSecondRange() ) {
//call Range2 handling method
}
else {
//call error handling method
}
Making the extra variable is likely to make code harder to read since you have to define them all before the if/else stack. However, it all depends on the case. Sometimes it might be better to use a variable if you will be using an expensive function many times or if you can make the variable have a more descriptive name than the function.
Actually it is also required if you want to test multiple methods and use short-circuit evaluation.
For instance, this is safe:
if (isResourceAvailable() && isResourceValid()) {
...
}
while this may no be:
bool resAvailable = isResourceAvailable();
bool resValid = isResourceValid(); // can you call that alone?
if (resAvailable && resValid ) {
...
}
It is good style as long as the methods you call don't just do something that would be clearer if it was coded in place:
if ( a > 0 && a < 10 ) doSomething();
is better than
if ( isInRange(a, 0, 10) ) doSomething();
Eh, it's mostly up to the coder but declaring the int is a bit more readable.
It's OK to write methods in the IF condition statement. But if the method will be used more than one time, you should first use a local variable to store the return value and use the variable as the IF condition
You can aim at writing function / method names that will make the code more readable where they are used. Like:
if (idInFirstRange()){
//call Range1 handling method
}else if(idInSecondRange()){
//call Range2 handling method
}else{
Also, usual convention for functions returning bool is that they start with is - isIdInFirstRange
Lastly, try avoiding such if-else ( and switch ) ladder. Try to use Dictionaries in such cases. ( https://stackoverflow.com/questions/6506340/if-if-else-or-switch-case/6506403#6506403 )
Although this practice is not wrong or condemned by any best practices guidelines, if you have more than one call within if condition it can be a bit difficult to know which call refused to enter if statement during a debug session.
if (idInFirstRange() && idInSecondRange()){
//call Range handling method
//if didn't reach this point, who was the responsible (idInFirstRange or idInSecondRange)?
}else if(idInSecondRange()){
//call Range2 handling method
}else{
//call something else
}
Lambdas are nice, as they offer brevity and locality and an extra form of encapsulation. Instead of having to write functions which are only used once you can use a lambda.
While wondering how they worked, I intuitively figured they are probably only created once. This inspired me to create a solution which allows to restrict the scope of a class member beyond private to one particular scope by using the lambda as an identifier of the scope it was created in.
This implementation works, although perhaps overkill (still researching it), proving my assumption to be correct.
A smaller example:
class SomeClass
{
public void Bleh()
{
Action action = () => {};
}
public void CallBleh()
{
Bleh(); // `action` == {Method = {Void <SomeClass>b__0()}}
Bleh(); // `action` still == {Method = {Void <SomeClass>b__0()}}
}
}
Would the lambda ever return a new instance, or is it guaranteed to always be the same?
It's not guaranteed either way.
From what I remember of the current MS implementation:
A lambda expression which doesn't capture any variables is cached statically
A lambda expression which only captures "this" could be captured on a per-instance basis, but isn't
A lambda expression which captures a local variable can't be cached
Two lambda expressions which have the exact same program text aren't aliased; in some cases they could be, but working out the situations in which they can be would be very complicated
EDIT: As Eric points out in the comments, you also need to consider type arguments being captured for generic methods.
EDIT: The relevant text of the C# 4 spec is in section 6.5.1:
Conversions of semantically identical anonymous functions with the same (possibly empty) set of captured outer variable instances to the same delegate types are permitted (but not required) to return the same delegate instance. The term semantically identical is used here to mean that execution of the anonymous functions will, in all cases, produce the same effects given the same arguments.
Based on your question here and your comment to Jon's answer I think you are confusing multiple things. To make sure it is clear:
The method that backs the delegate for a given lambda is always the same.
The method that backs the delegate for "the same" lambda that appears lexically twice is permitted to be the same, but in practice is not the same in our implementation.
The delegate instance that is created for a given lambda might or might not always be the same, depending on how smart the compiler is about caching it.
So if you have something like:
for(i = 0; i < 10; ++i)
M( ()=>{} )
then every time M is called, you get the same instance of the delegate because the compiler is smart and generates
static void MyAction() {}
static Action DelegateCache = null;
...
for(i = 0; i < 10; ++i)
{
if (C.DelegateCache == null) C.DelegateCache = new Action ( C.MyAction )
M(C.DelegateCache);
}
If you have
for(i = 0; i < 10; ++i)
M( ()=>{this.Bar();} )
then the compiler generates
void MyAction() { this.Bar(); }
...
for(i = 0; i < 10; ++i)
{
M(new Action(this.MyAction));
}
You get a new delegate every time, with the same method.
The compiler is permitted to (but in fact does not at this time) generate
void MyAction() { this.Bar(); }
Action DelegateCache = null;
...
for(i = 0; i < 10; ++i)
{
if (this.DelegateCache == null) this.DelegateCache = new Action ( this.MyAction )
M(this.DelegateCache);
}
In that case you would always get the same delegate instance if possible, and every delegate would be backed by the same method.
If you have
Action a1 = ()=>{};
Action a2 = ()=>{};
Then in practice the compiler generates this as
static void MyAction1() {}
static void MyAction2() {}
static Action ActionCache1 = null;
static Action ActionCache2 = null;
...
if (ActionCache1 == null) ActionCache1 = new Action(MyAction1);
Action a1 = ActionCache1;
if (ActionCache2 == null) ActionCache2 = new Action(MyAction2);
Action a2 = ActionCache2;
However the compiler is permitted to detect that the two lambdas are identical and generate
static void MyAction1() {}
static Action ActionCache1 = null;
...
if (ActionCache1 == null) ActionCache1 = new Action(MyAction1);
Action a1 = ActionCache1;
Action a2 = ActionCache1;
Is that now clear?
No guarantees.
A quick demo:
Action GetAction()
{
return () => Console.WriteLine("foo");
}
Call this twice, do a ReferenceEquals(a,b), and you'll get true
Action GetAction()
{
var foo = "foo";
return () => Console.WriteLine(foo);
}
Call this twice, do a ReferenceEquals(a,b), and you'll get false
I see Skeet jumped in while I was answering, so I won't belabor that point. One thing I would suggest, to better understand how you are using things, is to get familiar with reverse engineering tools and IL. Take the code sample(s) in question and reverse engineer to IL. It will give you a great amount of information on how the code is working.
Good question. I don't have an "academic answer," more of a practical answer: I could see a compiler optimizing the binary to use the same instance, but I wouldn't ever write code that assumes it's "guaranteed" to be the same instance.
I upvoted you at least, so hopefully someone can give you the academic answer you're looking for.
I frequently have code that looks something like this:
if (itm != null)
{
foreach (type x in itm.subItems())
{
//dostuff
}
}
//do more stuff
In situations where //do more stuff is omitted, it is very easy to avoid the extra foreach loop. By exitting scope using the appropriate command (depending on what is going on, this generally would mean a return statement or a continue statement).
This type of thing tends to result in arrow code. I currently have a few ways to deal with this:
Use code like itm = itm == null ? itm.subItems() : emptyArray
Allow arrow code
Use goto
Use evil scoping hacks (wrapping the whole thing, if statement in all, in a scope and then breaking out of it). In my opinion evil scoping hacks are basically equivalent to goto except uglier and harder to read, so I don't consider this a valid solution.
Refactor some of the chunks into new methods. There are in fact a few cases where this probably is a good solution, but mostly it's not appropriate since the null references are mainly error conditions from MS-functions.
Anyone care to offer a response on what approaches are considered preferable?
If you're using C# 3, you could always write an extension method:
public static IEnumerable<SubItem> SafeSubItems(this ItemType item)
{
return item == null ? Enumerable.Empty<SubItem> : source.SubItems();
}
Then just write:
foreach (SubItem x in itm.SafeSubItems())
{
// do stuff
}
// do more stuff
The key thing is that extension methods can be called even "on" null references.
What would be nice would be a "null-safe dereferencing" operator, so we could write:
// Not valid C# code!
foreach (SubItem x in itm?.SubItems() ?? Enumerable.Empty<SubItem>())
{
}
Or just define an EmptyIfNull extension method on IEnumerable<T> and use
// Not valid C# code!
foreach (SubItem x in (itm?.SubItems()).EmptyIfNull())
{
}
You could use the Coalesce operator (coded as a double question mark, ??, .net 2 upwards). This'll return the first non-null value in a list of values, so in this snippet...
MyClass o1 = null;
MyClass o2 = new MyClass ();
MyClass o3 = null;
return o1 ?? o2 ?? o3;
...o2 would be returned.
So you could re-code your original code sample as
foreach (type x in (itm ?? emptyArray).subItems())
{
//dostuff
}
//do more stuff
However, personally I don't mind the nesting. It's instantly clear what's going on. I find the Coalesce operator a little harder to read, and that little nest is a small price to pay for clarity.
I like less nesting, for me it reads better. No goto please :)
I keep methods short, so it is usually a return for that scenario.
if (itm == null) return;
foreach (type x in itm.subItems())
{
//dostuff
}
If the more stuff is needed, are simple statements and can be done before the foreach, you can:
if (itm == null)
{
//do more stuff
return;
}
foreach (type x in itm.subItems())
{
//dostuff
}
If the above is not the case, it is likely the method is too long and some of it would be moved away anyway. Probably:
if( itm != null ) SomeActionOnSubItems(itm.subItems);
// do more stuff (can be some method calls depending on level of abstraction).
Personally, I'd probably leave the structure the way you have it.
The first option (itm = itm == null ? itm.subItems() : emptyArray) seems less nasty than the others, but I still like your original better.
The problem is, from another developer's perspective, anything else is going to make your code less obvious. If there is a foreach running through a collection, I expect that the collection will (at least normally) have items contained in there. If the collection could be empty, that's not going to be obvious to other people without comments (which take longer to write than the if check).
Doing any of the hacks to avoid the if check just seems like you're trying to be too clever.