How to fix unreachable code dedected warning - c#

dbLinq XMlMappingSource.cs contains code:
public void ReadEmptyContent(XmlReader r, string name)
{
if (r.IsEmptyElement)
r.ReadStartElement(name, DbmlNamespace);
else
{
r.ReadStartElement(name, DbmlNamespace);
for (r.MoveToContent(); r.NodeType != XmlNodeType.EndElement; r.MoveToContent())
{
if (r.NamespaceURI != DbmlNamespace)
r.Skip();
throw UnexpectedItemError(r);
}
r.ReadEndElement();
}
}
This causes compile warning
Warning CS0162 Unreachable code detected
at line
for (r.MoveToContent(); r.NodeType != XmlNodeType.EndElement; r.MoveToContent())
( https://github.com/DbLinq/dblinq2007/blob/d7a05bb452b98fd24bca5693da01ecfecd4f3d40/src/DbLinq/Data/Linq/Mapping/XmlMappingSource.cs#L176 )
in third part of for clause r.MoveToContent()
It looks like normal node traversal code and third part of for is reached.
How to fix this ?
Using .NET 4

You never execute the increment step, because your first run through the loop always throws an exception.

As Rawling stated you are throwing the exception no matter what.
Try changing the loop to this:
for (r.MoveToContent(); r.NodeType != XmlNodeType.EndElement; r.MoveToContent())
{
if (r.NamespaceURI != DbmlNamespace)
r.Skip();
else
throw UnexpectedItemError(r);
}
This will fix your issue.

Related

C# lambda null runtime binding

I'm running into an odd scenario that doesn't happen on my PC, but does for a coworkers.
I have this piece of code:
LoaderHelpers.SetStringValue<blah>(this, "x", $"x response in Header",
() => jsonData.x.response[0].value, false);
The problem is that sometimes, "jsonData.x" is null and, for my coworker a 'cannot bind to null at runtime exception' is thrown, but not for me there isn't. I have code to handle the null scenario, but it's like his code never gets to that point and fails at the call level.
jsonData is of type dynamic.
The method code that handles the null scenario:
public static void SetStringValue<T>(IValidate data, string propertyName,
string valuePath, Func<string> value, bool required)
{
if (data.GetType().GetProperty(propertyName) != null)
{
try
{
if (string.IsNullOrEmpty(value()))
{
if (required)
data.DataValidationErrors.Add($"{valuePath} can't be empty");
data.GetType().GetProperty(propertyName).SetValue(data, null);
}
else
{
data.GetType().GetProperty(propertyName).SetValue(data, value());
}
}
catch
{
//property doesn't exist
if (required)
data.DataValidationErrors.Add($"{valuePath} doesn't exist");
data.GetType().GetProperty(propertyName).SetValue(data, null);
}
}
else
{
throw new NullReferenceException($"In {data.GetType()} => SetStringValue. " +
$"Passed property {propertyName}, but property doesn't exist.");
}
}
Again. Works perfect for me, but not for him. I'm completely lost. Maybe I don't understand how the lamba/function parameters work 100%, but I thought it only got evaluated when value() is invoked.
I should also mention that when I debug this code, I can step into the Nuget package and when he hits the same line, he can't. This maybe a useful hint.
If jsonData (or jsonData.x) is null (as it seems to be at this point) it will crash and give you that error every time you call the method value().
You need to check why jsonData.x is null. Maybe it´s a race condition caused by another thread setting this value to null, maybe it´s because a bad jsonData initialization... Can´t say since that code is not here.
There are so many things wrong with your code, i can't resist.
First of all, instead of copy/pasting the same stuff over and over, you might want to use a variable:
var property = data.GetType().GetProperty(propertyName);
Second, you pass a Func<string> and execute it multiple times, why is it even a function then? Yet again, better only evaluate it once and use a variable...
var unwrapped = value();
That would solve the issue, that Roberto Vázquez' answer adresses.
Then you are misusing NullReferenceException, instead rather use a ArgumentException
Next issue, that valuePath is only used in the exception message, that is a poor design to my beliefs.
The generic T parameter isnt even used, so get rid of it.
Last but not least, that catch-block doing the exact thing that could possibily throw the exception again, i cant see any reason why you would do this.
Finnaly this whole thing becomes a little more clear but its still a mess.
public static void SetStringValue(IValidate data, string propertyName,
string valuePath, Func<string> value, bool required)
{
if(data == null)
throw new ArgumentNullException(nameof(data));
var property = data.GetType().GetProperty(propertyName);
if(property == null)
throw new ArgumentException($"In {data.GetType()} => SetStringValue. " +
$"Passed property {propertyName}, but property doesn't exist.");
var unwrapped = value();
try
{
if (string.IsNullOrEmpty(unwrapped))
{
if (required)
data.DataValidationErrors.Add($"{valuePath} can't be empty");
unwrapped = null; // this might be unecessary.
}
property.SetValue(data, unwrapped);
}
catch(Exception e)
{
// This is probably a bad idea.
property.SetValue(data, null);
if (required)
data.DataValidationErrors.Add(Atleast put a better message here. e.Message ...);
}
}

Why is this null check incurring a null dereference error?

So basically I want to check that a setting is not set in my C# application. The code here
if (Default["StudentAccountTypeDefault"] is null) // Crashes after this
{
//
}
else
{
//
}
seems to be crashing on the null-check. I've put a breakpoint there, and it shows Default["DefaultStudentAccountType"] to just be a blank string. Why is it crashing with a NullReferenceException? I'm pretty sure this is where it crashes-if I comment out if statement it works as expected.
Edit: To alleviate some confusion. Sooooo, Default is actually Settings.Default, and to add to that, I was actually trying to access it inside the Settings() constructor. So, before it had been initialized, obviously. Oops. "Full"-er code below.
public Settings() {
// // To add event handlers for saving and changing settings, uncomment the lines below:
//
// this.SettingChanging += this.SettingChangingEventHandler;
//
// this.SettingsSaving += this.SettingsSavingEventHandler;
//
if (Settings.Default["DefaultStudentAccountType"] is null)
{
}
else
{
}
}
You should be checking with == not with is, also depending on your data type you may need to check if Default is null too. Try this:
if(Default == null || Default["StudentAccountTypeDefault"] == null)
{
}
else
{
}
Default is a variable, so if it is null, accessing the indexer ["StudentAccountTypeDefault"] will throw a null reference exception.
If you're using a new enough .NET version, you can use:
if (Default?["StudentAccountTypeDefault"] is null)
(the null-coalescing operator). Otherwise, just check Default for null before using its indexer.

Throwing exceptions at multiple points (refactoring)

I'm writing a function that takes user input, runs a procedure in our database, and compares the values. Along the way, I need to check that we've received proper input and then that the query has returned an acceptable value.
private void DoTheThing(int? userInput1, int? userInput2, int valuePassedIn)
{
if (userInput1 == null || userInput2 == null)
{
Exception ex = new Exception();
ex.Data.Add("Message", "You screwed up.");
throw ex;
}
var queryResult = 0; //execute a query using the non-null inputs
if (queryResult == null) //or otherwise doesn't return an acceptable value
{
Exception ex = new Exception();
ex.Data.Add("Message", "some other thing happened");
throw ex;
}
else
{
//We're good, so do the thing
}
}
A quick note about this: I'm aware of the argument against exceptions as flow control and that I'd be better off checking the user's input before I even get this far. I won't get into all the details, but please accept that I'm kind of stuck writing the function this way.
That having been said, here's my question:
Given that the only differences between the 2 exceptions here is the message and the time at which they are thrown, how can I clean this code up to be both DRY and avoid running unnecessary code after determining that there will be a problem?
I thought about using a goto and placing the error code there, but that really only moves the problem around. If I move the exception code to the bottom and check for a message variable (or something similar), then I'm just running code that doesn't need to be run in the first place.
I suggest not throwing Exception (which means something went wrong, no comments are available), but ArgumentNullException and InvalidOperationException classes. Another amendment is avoding arrow-head
antipattern:
private void DoTheThing(int? userInput1, int? userInput2, int valuePassedIn)
{
// What actually went wrong? An argument "userInput1" is null
if (null == userInput1)
throw new ArgumentNullException("userInput1");
else if (null == userInput2)
throw new ArgumentNullException("userInput2"); // ...or userInput2 is null
var queryResult = executeSomeQuery(userInput1, userInput2, valuePassedIn);
// What went wrong? We don't expect that null can be returned;
// so the operation "executeSomeQuery" failed:
// we've provided validated (not null) values and got unexpected return.
// Let it have been known.
if (null == queryResult)
throw new InvalidOperationException(
String.Format("Query ({0}, {1}, {2}) returned null when bla-bla-bla expected",
userInput1, userInput2, valuePassedIn));
// We're good, so do the thing
// Note that's there's no "arrow-head antipattern":
// we're not within any "if" or "else" scope
}
Edit: Since every *Exception is inherited from Exception you can put some info into Data:
Exception ex = new ArgumentNullException("userInput1");
ex.Data.Add("Some key", "Some value");
throw ex;
but often Message is a far better place to explain what had heppened.
You might be better off creating a BadInputException class and a NullQueryResultException class. These do two different things and throwing a specific exception is better than throwing a generic Exception(...). In fact I think FXCop or Visual Studio's Code Analysis will give you a warning about throwing generic Exceptions.
It's not really all that much new code to write.
public class BadInputException : Exception
{
public BadInputException()
{
this.Data.Add("Message", "You screwed up.")
}
}
Then instead of this:
Exception ex = new Exception();
ex.Data.Add("Message", "You screwed up.");
throw ex;
Do this:
throw new BadInputException();
Edit: moved the "You screwed up" message from the Message property to the Data collection to match what the OP wants.
I would create a method:
private void CheckResult(bool cond, string msg, string info) {
if (!cond)
return;
Exception ex = new Exception();
ex.Data.Add(msg, info);
throw ex;
}
and call
CheckResult(userInput1 == null || userInput2 == null, "Message", "You screwed up.");
and
CheckResult(queryResult == null, "Message", "You screwed up.");
I think the QuestionRefactoring Guard Clauses is helpful for you .
There are something about this in Replace Nested Conditional with Guard Clauses.
Hope it's useful.

Null check returns true for non-null value

Having an odd problem. It's happened a few times over the years, but I've never been able to figure out why. Always solved it by rearranging the code I had in place, but would like to know is there's a more proper way of dealing with it, or at least figuring out what's behind it.
Non-working version:
public bool CaptureFrame(ArrayCache cache)
{
if (cache == null)
throw new ArgumentNullException("cache");
DataArray frame = cache.CacheData;
if (frame == null)
throw new ArgumentNullException("cache.CacheData");
// do stuff
}
Working version:
public bool CaptureFrame(ArrayCache cache)
{
if (cache == null)
throw new ArgumentNullException("cache");
if (cache.CacheData == null)
throw new ArgumentNullException("cache.CacheData");
DataArray frame = cache.CacheData;
// do stuff
}
The problem is this: frame is not null (at least according to the debugger, and by any measure I can trace of the code), however when it does the if (frame == null) check, it comes out true and throws the exception. I rewrote to check cache.CacheData and it works fine, but it really shouldn't make any difference to the code logic.
I managed to find one other question on the site with a similar problem, which ended up being related to the == and != operators being overloaded. Those operators are not overloaded for the class in question in my code, and it's a standalone class so there's nothing for it to inherit.
Edit: John Saunders requested code for the CacheData property:
private DataArray cacheData;
public DataArray CacheData
{
get
{
return cacheData;
}
set
{
cacheData = value;
}
}
looks like you are mapping the exception in the non working one then calling
DataArray frame = cache.CacheData;
but what if cache.CacheData if null then you are assigning it to DataFrame.. it's always best in my opinion to do the Check for null first before assigning or assuming your second one looks fine.. prehaps instead of throwing an exception maybe you could trap the exception and try some test cases for both scenarios

Can't find why do I have a null reference exception

Below is the code and the problematic line.
When I hover with the mouse on src.EnergyServiceLevel, it shows that it's null.
How can that be if I'm checking for null in the previous line?
My guess was that maybe there are threads that making the problem so I've add a lock,
but it didn't helped.
public static ServiceLevelsGroup SafeClone(this ServiceLevelsGroup src) {
ServiceLevelsGroup res = null;
lock (_locker) {
if (src != null) {
res = new ServiceLevelsGroup();
if (src.EnergyServiceLevel != null) {
res.EnergyServiceLevel = new ServiceLevelInfo { ServiceGrade = src.EnergyServiceLevel.ServiceGrade };
if (src.EnergyServiceLevel.Reason != null)
res.EnergyServiceLevel.Reason = src.EnergyServiceLevel.Reason;
}
}
}
return res;
}
The exception occurs at the res.EnergyServiceLevel = ... line in the above code.
Here's a screenshot of the exception occurring in debug mode:
Your code shows lock(_locker) - so it looks like you're in a multithreaded environment. Can you check that nothing else is NULLing your variable? i.e. that everything else is also calling lock(_locker) correctly?
Maybe your NULL is at res.EnergyServiceLevel.
src.EnergyServiceLevel.ServiceGrade may be null
Moving mouse pointer to each reference will exactly show you which is null.

Categories

Resources