Do Loop, an efficient break method? - c#

I have a section inside a method that does something similar too:
do
{
// some query
// another query
if another query != null
{
// return something
}
}while(some query != null)
Obviously this does not work, because some query is not declared until it is inside the loop. One solution I tried was
bool flag = false;
do
{
// some query
if some query == null
{
flag = true;
// or
break;
}
// another query
if another query != null
{
// return something
}
}while(flag != true)
Neither method really satisfies me, and quite honestly I am not sure if they would be considered good coding practice, which irks me. Moreover this has pretty much has been my go to solution in cases like this up until this point, but due to the garbage nature of the flag, I wanted to find out if there is a better way to handle this for future reference, instead of making a junk variable. I should note the other solution which I thought of would arguably be uglier. That solution being to run the query once outside the loop, and convert it into a while loop and recall the query again inside itself, rather than a do loop.
While the code works with the above solution, I was wondering if anyone had a better solution that does not require an arguably pointless variable.
Though I understand that such a better solution may not be possible, or really even needed, it could be ridiculous to even try.

Having a break or flag variable isn't what would make something inefficient, it's what inside the loop that should be your concern. In other words it's just a preference and either is fine.

I think you need
while(true)
{
// some query
if some query == null
{
break;
}
// another query
if another query != null
{
// return something
}}

You can try this:
do
{
// some query
if some query == null
{
break;
}
// another query
if another query != null
{
// return something
}
}while(true);

Related

Exception handling with lambda/linq statements

I have the following statement that I am trying to use a try-catch block with
var val= db.shops.where(x=>×.id==ID).Select (a=>a.address).First();
I tried following but has many issues won't even compile.
var val=db.shops.Where(x=>
{
try
{
(x.Id==ID).Select(a=>a.address).First();
}
catch(ex)
{
return ex;
}
}
Please let me know how can I handle the exception in this statement Thanks.
Note: writing this question from mobile phone can't format code. Apologize for it.
Everything inside brackets ({ }) need to have 'regular' block syntax, so return is required here:
...
.Where
(x=>
{
try
{
return (x.Id == ID);
}
catch(ex)
{
throw;
}
}
)
.Select(a=>a.address)
.First(); // Or FirstOrDefault if you expect this statement to yield no result.
As you see, the Where is more like a regular statement now. The Select is moved to outside the Where. If you need exception handling in there, you have to do the same as in the Where block now. Last, return ex is probably meant to be throw ex, which should be throw in this case to preserve call stack.
...that I am trying to use try catch block with
I am guessing you probably meant to write FirstOrDefault based on where you want the try/catch. In the sample code you have provided I see no reason to try to make a catch block into one of the lambda statements. The best thing to do would be to simply use FirstOrDefault as that is the reason why you might get an exception in the code shown.
var address = db.shops.FirstOrDefault(x => ×.id == ID)?.Address;
if(address == null)
// nothing was found or address is null, do something else
Or similar code closer to what you had without my "optimization"
var shop = db.shops.FirstOrDefault(x => ×.id == ID);
if(shop == null) {
// nothing was found, do something else
}
var address = shop.address;
The other reason not to use try/catch is that it can't be translated into SQL and the variable name db which is the container for the shops collection which leads me to believe you are using EF or some other ORM. So even if you were to fix the syntax and your code with added try/catch block compiles you will get a run time error later when you execute the lambda.
You should place the try around your original statement:
try
{
var val= db.shops.where(x=>×.id==ID).Select (a=>a.address).First();
}
catch (Exception ex)
{
return ex; //I assume the return type here is wrong. Maybe return null?
}
However, there's nothing about that line that should require a try/catch. Try this:
var val= db.shops.where(x=>×.id==ID).Select(a=>a.address).FirstOrDefault();
The FirstOrDefault will return null if there are no results.

Scope of string inside lambda

I have an interesting scenario in which I've built a validation checking system that maintains a series of requirements in the form List<Tuple<Func<bool>, string>> where the Func should return true if validation failed and false otherwise. The string is a corresponding rejection description that describes the condition should the test fail.
In more simple tests like the following the validation system is quite simple:
validationChecks.Add(Tuple.Create<Func<bool>, string>(() =>
value1 == requiredValue, "value 1 did not have the required value"));
I'm struggling to understand the scope of variables within the lambda for the Func in a more advanced scenario in which the rejection string is calculated in a call to another part of the system. The scenario looks something like this:
string rejectionString = null;
validationChecks.Add(Tuple.Create<Func<bool>, string>(() => {
rejectionString = CallToAnotherMethodThatReturnsString(parameter);
if (rejectionString != null) {
return true;
} else {
return false;
}
}, rejectionString));
EDIT: As observed through testing, when this check fails the rejectionString from the Tuple is still null. I want the rejectionString that was generated by the CallToAnotherMethod to be used instead, is there any way I can do this using ref or otherwise? I need the Func's code to be able to affect the value of the string inside Item2 of the Tuple.
The problem is that the code inside of CallToAnotherMethodThatReturnsString might be code that I only want executed ONCE. However should the check fail I want to use the string that would have been returned from it as my rejection description in the Tuple. I'm unable to tell at this point what the effect of my use of rejectionString in this second example will accomplish? Will rejectionString inside the Tuple always be null? Or if CallToAnotherMethodThatReturnsString returns a different value will it be updated?
Just an idea that might work. I think if you change your second Tuple parameter to a Func that returns string instead of string value, you could come close to what you need.
string rejectionString = null;
validationChecks.Add(Tuple.Create<Func<bool>, Func<string>>(() =>
{
rejectionString = CallToAnotherMethodThatReturnsString(parameter);
if (rejectionString != null) {
return true;
} else {return false;}
},
()=>rejectionString));
In the first case your validation check would be set as
validationChecks.Add(Tuple.Create<Func<bool>, Func<string>>(() => value1 == requiredValue, ()=>"value 1 did not have the required value"));
And your validation is logic is then
if(validationChecks[0].Item1()==false)
var error = validationChecks[0].Item2();

Will following ever cause RACE CONDITION when accessing ASP.Net Cache Item?

I am using the following code, and to me it seems that a race condition would never happen with code below. Or there is still a chance of race condition?
List<Document> listFromCache = Cache[dataCacheName] as List<Document>;
if (listFromCache != null)
{
//do something with listFromCache. **IS IT POSSIBLE** that listFromCache is
//NULL here
}
else
{
List<Document> list = ABC.DataLayer.GetDocuments();
Cache.Insert(dataCacheName, list, null, DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration);
}
UPDATE:
Chris helped me solve this problem, but I just thought, I would share some details that would be be very helpful to others.
To completely avoid any race condition, I had to add a check within the true part, else I could end up with a List with zero count, if someone else clears it in Cache ( not remove the item, but just call Clear method on the List object in Cache) after my if has evaluated to TRUE. So then, I would not have any data within my true part of if in listFromCache object.
To overcome, this subtle RACE condition in my original code, I have to double check listFromCache in the true part as in code below, and then repopulate Cache with latest data.
Also, as Chris said, if someone else 'removes' the items from Cache by calling the method Cache.Remove, then listFromCache would not be affected, since the Garbage Collector will not remove the actual List object from HEAP memory because a variable called 'listFromCache' is still having a reference to it ( I have explained this in more detail in a comment under Chris's answer post).
List<Document> listFromCache = Cache[dataCacheName] as List<Document>;
if (listFromCache != null)
{
//OVERCOME A SUBTLE RACE CONDITION BY IF BELOW
if( listFromCache == null || listFromCache.Count == 0)
{
List<Document> list = ABC.DataLayer.GetDocuments();
Cache.Insert(dataCacheName, list, null, DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration);
}
//NOW I AM SURE MY listFromCache contains true data
//do something with listFromCache. **IS IT POSSIBLE** that listFromCache is
//NULL here
}
else
{
List<Document> list = ABC.DataLayer.GetDocuments();
Cache.Insert(dataCacheName, list, null, DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration);
}
No, it's not possible in your comment that listFromCache will become null as it's a local reference at that point. If the cache entry is nullified elsewhere, it doesn't affect your local reference. However, you could possibly get a condition where you retrieved a null value, but while in the process of gathering the documents (ABC.DataLayer.GetDocuments()) another process has already done so and inserted the cache entry, at which point you overwrite it. (this may be perfectly acceptable for you, in which case, great!)
You could try locking around it with a static object, but honestly, I'm not sure if that'll work in an ASP.NET context. I don't remember if Cache is shared across all ASP.NET processes (which IIRC, have different static contexts) or only shared within each single web worker. If the latter, the static lock will work fine.
Just to demonstrate too:
List<Document> listFromCache = Cache[dataCacheName] as List<Document>;
if (listFromCache != null)
{
Cache.Remove(dataCacheName);
//listFromCache will NOT be null here.
if (listFromCache != null)
{
Console.WriteLine("Not null!"); //this will run because it's not null
}
}

Best practice of SingleOrDefault()

I want to make my code better. Can I safely rewrite the first example to the second?
IQueryable<PDF> pdfList = (from pdfobj in pdfDataContext.PDFs
where pdfobj.Id == pdfId
select pdfobj);
if (pdfList.Count() > 0)
{
PDF pdfOldWay = pdfList.FirstOrDefault();
pdfOldWay. // do something. (pdfOldWay can't be null here...)
}
--
PDF pdfNewWay = (from pdfobj in pdfDataContext.PDFs
where pdfobj.Id == pdfId
select pdfobj).SingleOrDefault();
if (pdfNewWay != null)
{
// do something
}
--
EDIT:
Sorry for not being clear. My issue is to get the PDF object out directly without having to use a list first. I don't want to make a check for count is greater than 0 and because it just doesn't look good.
Yes, that looks safe. You can also simplify your query slightly:
PDF pdfNewWay = pdfDataContext.PDFs.SingleOrDefault(p => p.Id == pdfId);
if (pdfNewWay != null)
{
// do something
}
The only difference between SingleOrDefault and FirstOrDefault is that SingleOrDefault will throw an exception if more than one match is found, so unless you want this check then you may as well stick to FirstOrDefault.
You should use FirstOrDefault in the second case too as SingleOrDefault will throw an exception if there is more than one item. Is that ok for you?
On the other hand if you want to guarantee that there is only one pdfobject for some id than using SignleOrDefault is better.
If it's guaranteed that it always has 0 or 1 rows, then sure, SingleOrDefault is the best solution.
Yes you will achieve the same result, I don't see any issue.

Refactor help c#

I have several hundred lines of code like this:
if (c.SomeValue == null || c.SomeProperty.Status != 'Y')
{
btnRecordCall.Enabled = false;
}
if (c.SomeValue == null || (c.SomeProperty.Status != 'Y' &&
c.SomeOtherPropertyAction != 'Y'))
{
btnAddAction.Enabled = false;
}
if (c.SomeValue == null || c.SomeProperty.Processing != 'Y')
{
btnProcesss.Enabled = false;
}
How can I refactor this correctly? I see that the check 'c.SomeValue == null' is being called every time, but it is included with other criteria. How can I possibly eliminate this duplicate code?
I would use the specification pattern, and build composite specifications that map to a proper Enabled value.
The overall question you want to answer is whether some object c satisfies a given condition, which then allows you to decide if you want something enabled. So then you have this interface:
interface ICriteria<T>
{
bool IsSatisfiedBy(T c);
}
Then your code will look like this:
ICriteria<SomeClass> cr = GetCriteria();
btnAddAction.Enabled = cr.IsSatisfiedBy(c);
The next step is to compose a suitable ICriteria object. You can have another ICriteria implementation, (in additon to Or and And), called PredicateCriteria which looks like this:
class PredicateCriteria<T> : ICriteria<T>
{
public PredicateCriteria(Func<T, bool> p) {
this.predicate = p;
}
readonly Func<T, bool> predicate;
public bool IsSatisfiedBy(T item) {
return this.predicate(item);
}
}
One instance of this would be:
var c = new PredicateCriteria<SomeClass>(c => c.SomeValue != null);
The rest would be composition of this with other criteria.
If you don't want to do much refactoring, you can easily pull the null check out.
if (c.SomeValue == null)
{
btnRecordCall.Enabled = false;
btnAddAction.Enabled = false;
btnProcesss.Enabled = false;
}
else
{
if(c.SomeProperty.Status != 'Y')
{
btnRecordCall.Enabled = false;
}
if((c.SomeProperty.Status != 'Y') &&
(c.SomeOtherPropertyAction != 'Y'))
{
btnAddAction.Enabled = false;
}
if(c.SomeProperty.Processing != 'Y')
{
btnProcesss.Enabled = false;
}
}
If you're looking to refactor instead of shuffle, the wall of boolean testing could be moved in to methods/extension methods of whatever class your object c is an instance of - that way you could say
btnRecordCall.Enabled = c.IsRecordCallAllowed();
Create properties on "c" such as "CanRecordCall", "CanAddAction", "CanProcess" so that your code becomes this:
btnRecordCall.Enabled = c.CanRecordCall;
btnAddAction.Enabled = c.CanAddAction;
btnProcess.Enabled = c.CanProcess;
The "c.SomeValue == null" is a typical response to NullReferenceExceptions. You could improve "c" by initializing its SomeValue property to a null object so that there is never a null reference (just an object that does nothing).
In specific, since you seem to be setting UI elements state, you could consider more of a two-way data binding model where you set up a data context and a control-to-property mapping and let that govern the control state. You can also consider a more heavy-weight solution that would be something like the Validation Application Block from Enterprise Library. There are also some fluent validation projects that you should take a look at.
I'd start by making sure all such code is contiguous. Anything other than this code should be moved before or after the code.
Then, for each reference to a control property, create a corresponding local variable, e.g., processEnabled. Define it before the first if statement. For each such property, move, e.g., btnProcesss.Enabled = false; to the end of this code block, and change "false" to processEnabled. Replace the original with processEnabled = false;.
When the code block has no more references to controls (or to anything else having to do with the UI), select the entire block, from the added variables to the control property sets at the end, and use the Extract Method refactoring. That should leave you with a method that accepts c, and produces values you can later use to set control properties.
You can even get fancier. Instead of individual local variables, define a class that has those "variables" as properties. Do pretty much the same thing, and the extracted method will wind up returning an instance of that class, instead of individual out parameters.
From there, you may start to see more things to clean up in the extracted method, not that you'll have removed anything to do with UI from that code.
I'm guessing the issue here is about 'boolean map' style refactorings, i.e., being able to refactor complementary boolean cases where there might be some gaps and some repetition. Well, if that's what you're after, you can certainly write a tool to do this (it's what I would do). Basically, you need to parse a bunch of if statements and take note of condition combinations that are involved. Then, through some fairly simple logic, you can get your model to spit out a different, more optimized model.
The code you show above is one reason why I love F#. :)
Interestingly, in our current Winforms app, the three conditions would be in three different classes, since each button would be attached to a different Command.
The conditions would be in the CanExecute methods of the commands and control the enable/disable behaviour of the button that triggers the command. The corresponding execution code is in the Execute method of the class.

Categories

Resources