Need to check for null on something that throws exception - c#

_sponsorOrBankFacingBorrowerCompanyWizardData = CompanyData.GetCompanyWizardData(SponsorOrBankFacingBorrowerCompany.CompanyID);
So the problem here is that the code tries to go into this statement no matter what, I want it to only go if it CAN go, obviously.
However, if I perform a watch in Visual Studio 2010 ONLY on this object SponsorOrBankFacingBorrowerCompany, no properties, methods, anything, I get a null reference exception.
How do I check for null when I get an exception before the check even happens?
Here's the watch:
EDIT:
public STPProject STPData
{
get { return _STPData; }
set
{
_STPData = value;
//set WebIds
foreach (STPCompany comp in _STPData.STPCompanyCollection)
{
comp.WebId = comp.WebId < 1 ? GetNextWebId() : comp.WebId;
foreach (STPContact cont in comp.STPContactCollection)
{
cont.WebId = cont.WebId < 1 ? GetNextWebId() : cont.WebId;
}
}
//must be before AttachSTPEvents
_STPData.AffiliateTradeIndicator = _STPData.AffiliateTradeIndicator.HasValue ? _STPData.AffiliateTradeIndicator.Value : false;
//set company wizard defaults
_sponsorOrBankFacingBorrowerCompanyWizardData = CompanyData.GetCompanyWizardData(SponsorOrBankFacingBorrowerCompany.CompanyID);
AttachSTPEvents(_STPData);
}
}
Getter for other that is throwing exception:
public STPCompany SponsorOrBankFacingBorrowerCompany
{
get
{
if (STPData.AffiliateTradeIndicator.Value)
{
return BankFacingBorrower;
}
else
{
return Sponsor;
}
}
}

Something like the following, unless I'm mistaking your question:
if (SponsorOrBankFacingBorrowerCompany != null)
{
_sponsorOrBankFacingBorrowerCompanyWizardData =
CompanyData.GetCompanyWizardData(
SponsorOrBankFacingBorrowerCompany.CompanyID);
}
Update:
Okay, this is elaborate but will hopefully make the problem become immediately evident, so let's drill this down, the long way; can you amend your property code to look like the following:
public STPCompany SponsorOrBankFacingBorrowerCompany
{
get
{
if (STPData == null)
{
throw new InvalidOperationException("'STPData' is null");
}
if (STPData.AffiliateTradeIndicator == null)
{
throw new InvalidOperationException(
"'STPData.AffiliateTradeIndicator' is null");
}
if (STPData.AffiliateTradeIndicator.Value == null)
{
throw new InvalidOperationException(
"'STPData.AffiliateTradeIndicator.Value' is null"); ;
}
if (STPData.AffiliateTradeIndicator.Value)
{
return BankFacingBorrower;
}
else
{
return Sponsor;
}
}
}

I'm betting you're getting a null reference from your SponsorOrBankFacingBorrowerCompany getter in here:
STPData.AffiliateTradeIndicator.Value
Check all those parts in the debugger...

Related

Initialize value in dictionary only once, then just update

I'm currently working to track packages when they move between bays, these changes happen every dozen or so seconds, so I have several threads accessing some dictionaries. The idea is that the first few times, I will not have the lastBay value (the program is just starting), but when A == B for the first time, I save the value of A (the bay that the pacakage has landed into, therefore the last bay at which it has been) and then just update said value every time A == B again.
private void in_bay()
{
String line_type = getDictionaryValues("global", "line_type").getStringValue();
bool result = false;
switch (line_type)
{
case "A_1":
int A = getVariableFromBucket("A_Act").getIntValue();
int B = getVariableFromBucket("A_Next").getIntValue();
result = A == B ? true : false;
if (result)
{
setDictionaryValues("global", "lastBay", new Variable("UNSIGNED8") { binaryValue = Utils.intToByteArray(A) });
}
break;
}
setVariableInBucket("IN_BAY", BitConverter.GetBytes(result));
log("IN_BAY flag in BUCKET: " + getVariableFromBucket("IN_BAY").getBoolValue(), DEBUG);
if (getDictionaryValues("global", "lastBay").binaryValue != null)
{
log("lastBay value in global: " + getDictionaryValues("global", "lastBay").getIntValue(), DEBUG);
}
else
{
log("undefined bay",DEBUG);
}
}
I have a getDictionaryValue() function that returns the variables (or an empty one if it's not in the dictionary):
public Variable getDictionaryValues(String DictionaryName, String VarName)
{
try
{
return functionDictionary[DictionaryName][VarName];
}
catch (Exception)
{
Variable emptyVariable = new Variable()
{
additionalInfo = null,
arrivalTime = 0,
binaryValue = null,
numBits = 0,
signed = false,
varType = null
};
return emptyVariable;
}
}
and a setDictionaryValue() function that actually sets the values to the dictionary selected:
public void setDictionaryValues(String DictionaryName, String VariableName, Variable VaValue)
{
try
{
lock (GlobalConstants.filtersLock)
{
if (!functionDictionary.ContainsKey(DictionaryName))
{
functionDictionary.Add(DictionaryName, new Dictionary<String, Variable>());
}
if (!functionDictionary[DictionaryName].ContainsKey(VariableName))
{
functionDictionary[DictionaryName].Add(VariableName, Value);
}
else
{
functionDictionary[DictionaryName][VariableName] = Value;
}
}
}
catch (Exception e)
{
log("An error has ocurred when setting values to functionDictionary: "+ e,DEBUG);
throw new Exception(e.ToString());
}
}
The problem is that the first time A == B It logs correctly the values being received, but when the values change again (the package starts moving again) the code no longer displays the values of lastBay, as if the dictionary global no longer has a value for lastBay. I attach an image with a reference as to the expected results and the results obtained:
What am I missing here?
From the comment thread, it looks like the problem is that in_bay is being called on different object instances, and functionDictionary is a non-static field, so you're dealing with different dictionary instances each time.
I just want to take the opportunity to point out how much simpler your code could be if you just used classes and variables rather than adding dictionaries and "Variable" objects as a layer of abstraction.
private void in_bay()
{
string? line_type = BayState.line_type;
bool result = false;
if(line_type == "A_1")
{
int A = Bucket.A_Act;
int B = Bucket.A_Next;
result = A == B;
if (result)
{
BayState.lastBay = A;
}
}
Bucket.IN_BAY = result;
log("IN_BAY flag in BUCKET: " + Bucket.IN_BAY, DEBUG);
if (BayState.lastBay != null)
{
log("lastBay value in global: " + BayState.lastBay.Value, DEBUG);
}
else
{
log("undefined bay", DEBUG);
}
}
I can pretty much guarantee whatever "business need" is driving the desire for dictionaries and such can be accomplished in another way that still allows you to write clean and less error-prone code.

Throw an exception or just return a string?

Say I have this function which checks for user details
//check valid user's details.
private bool checkUserDatails(String nickname, String groupId)
{
//check nickname
if ((nickname == null || nickname.Trim().Equals("")))
{
return false;
}
//check groupId
if (groupId == null)
return false;
//convert to int
int id;
try
{
id = int.Parse(groupId);
}
catch (Exception) { return false; }
//check id
if (id < 0 | id > 100)
return false;
return true;
}
It works great, but the caller function doesn't know why the function returned false if it did. My initial thought was to create my own exceptions such as IncorrectUsernameException etc. and throw them. I could also make the return value string and just return "Incorrect username".
What's the correct C# approach to this?
Following Microsoft conventions (in some places, at least), this should look like:
private void EnsureValidDetails(string nickname, string groupId)
{
if (string.IsNullOrWhiteSpace(nickname))
{
throw new ArgumentNullException(nameof(nickname));
}
else if (string.IsNullOrEmpty(groupId))
{
throw new ArgumentNullException(nameof(groupId));
}
int parsedGroupId;
if (!int.TryParse(groupId, out parsedGroupId))
{
// or some better wording
throw new ArgumentException("GroupId is not a valid number.");
}
if (parsedGroupId < 0 || parsedGroupId > 100)
{
throw new ArgumentOutOfRangeException("GroupId must be between 0 and 100.");
}
}
Notice though, that this method is doing more than it should be doing. groupId should be an int parameter, and the method should only check for the value to be inside the valid range:
private void EnsureValidDetails(string nickname, int groupId)
{
if (string.IsNullOrWhiteSpace(nickname))
{
throw new ArgumentNullException(nameof(nickname));
}
else if (groupId < 0 || groupId > 100)
{
throw new ArgumentOutOfRangeException("GroupId must be between 0 and 100.");
}
}
Yet, this might not be the best way to actually validate this kind of stuff. It certainly works as a generic, framework-independent way, but some .NET frameworks (WPF, WCF, WinForms, ASP.NET) provide built-in ways for doing this.
You shouldn't throw an exception, as it will probably happen quite often that the value false is returned. This would cause a pretty big performance decrease. Instead you could for example use an enum, with values like correct, invalid_nickname, invalid_id and so on.
enum CheckUserDetailsResult { correct, invalid_nickname, invalid_id }
Alternatively you could provide the message via the out reference like that:
private bool checkUserDetails (String nickname, String groupId, out String message)
{
if (String.IsNullOrEmpty (nickname))
{
message = "Invalid nickname!";
return false;
}
//and so on
}

c# two nested if statements, one else

Please excuse the question that seems simple, but for some reason I cannot think of an elegant solution at the moment.
I have the following situation:
if (Request.QueryString["name"] != null)
{
if (Request.QueryString["name"].ToString() != "")
{
nameSpan.InnerHtml = Request.QueryString["name"].ToString();
}
}
The problem is, if I want to hide the nameSpan if querystring["name"] is either null or emtpy. The ugly solution would be:
if (Request.QueryString["name"] != null)
{
if (Request.QueryString["name"].ToString() != "")
{
nameSpan.InnerHtml = Request.QueryString["name"].ToString();
}
else
{
nameSpan.Visible = false;
}
}
else
{
nameSpan.Visible = false;
}
I would like to have a situation where both the nameSpan.Visible = false; sections could be merged into one area so I only have to write it once.
As far as I am aware, it is not possible to do the following:
if (Request.QueryString["name"] != null && Request.QueryString["name"].ToString() != "")
{
nameSpan.InnerHtml = Request.QueryString["name"].ToString();
}
else
{
nameSpan.Visible = false;
}
But please tell me if I am wrong! If you have a different solution which changes the logic then I am more than happy to have different views! Thank you!
Your && solution should be fine. If left side of && is false, right side it not evaluated so there will be no exception.
If you want, you could use String.IsNullOrEmpty static method:
if (!string.IsNullOrEmpty(Request.QueryString["name"]))
{
nameSpan.InnerHtml = Request.QueryString["name"].ToString();
}
else
{
nameSpan.Visible = false;
}
if you are after compact code, I'd use next (NameValueCollection returns null if key does not exist, and indexer returns string):
nameSpan.InnerHtml = Request.QueryString["name"];
nameSpan.Visible = !string.IsNullOrEmpty(nameSpan.InnerHtml);

C# error - "Not all code paths return a value"

This is fairly simple method. I use entity framework to get some data and then check some values in a if statement. However right now the method is marked with red.
This is my method:
private bool IsSoleInProduction(long? shoeLastID)
{
if (shoeLastID == null)
{
MessageBox.Show(Resources.ERROR_SAVE,
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
ISoleService soleService =
UnityDependencyResolver.Instance.GetService<ISoleService>();
List<Sole> entity =
soleService.All().Where(s => s.ShoeLastID == shoeLastID).ToList();
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
}
else
{
return false;
}
}
What am I missing?
You need to take advantage of LINQ with Any, replace your code:
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
}
else
{
return false;
}
with simpler code:
return entity.Any(item => item.Status == 20);
Or even better performance:
return soleService.All()
.Any(s => s.ShoeLastID == shoeLastID
&& s.Status == 20);
Edit: With you comment, below code is what you need:
List<Sole> entity = soleService.All()
.FirstOrDefault(s => s.ShoeLastID == shoeLastID);
return entity == null ? false : entity.Status == 20;
If there's no item in your entity collection, then neither of the containing if/else branches will be executed. In this case there's no return statement anymore, because the else part won't be executed, and outside your foreach you have no return statement.
The compiler does not "see" that if
entity.Count() != 0
then your loop
foreach (var items in entity)
will run at least once. Therefore it sees a possibility of running the forech zero times, and not running the else block.
Suppose first time the entity is enumerated, it yields some (finite number of) items. Then the Count will be non-zero. Then suppose next time the same entity is enumerated then it yields no items! That would cause your code to "fall through" without returning.
It is very probably that you can guarantee that the source yields the same number of items each time it is re-enumerated. But the compiler cannot.
Solution: Just skip if (entity.Count() != 0) and do foreach right away.
You haven't retrun anything from this code block
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
// return someting
}
You might consider doing the following. This will adhere to the "single exit-point" principle (which can sometimes help improve code clarity), and ensure you have a default value in any case:
private bool IsSoleInProduction(long? shoeLastID)
{
// The main change: A default value, assuming "no":
var isSoleInProduction = false;
if (shoeLastID == null)
{
MessageBox.Show(Resources.ERROR_SAVE,
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
isSoleInProduction = false;
}
ISoleService soleService =
UnityDependencyResolver.Instance.GetService<ISoleService>();
List<Sole> entity =
soleService.All().Where(s => s.ShoeLastID == shoeLastID).ToList();
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
isSoleInProduction = true;
}
else
{
isSoleInProduction = false;
}
}
}
else
{
isSoleInProduction = false;
}
return isSoleInProduction;
}
What will be your entity.Count() is not 0 and your entity doesn't have any items?
That means your if block will work but foreach part will not work. Since your if part doesn't have any return statement, that's why you get an error.
You should put return statement in your if part.
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
//return true or false
}
If your entity collection has no elements you will not reach a return statement - you need to add a return false forexample as last statement
As the error states there can be cases in which none of your return clause is evaluated (e.g. if there are no elements in your list).
To quickly solve it you can put a default return statement, for example by moving the last return clause outside the else statement. But it really depends on the behavior you'd expect.
private bool IsSoleInProduction(long? shoeLastID)
{
if (shoeLastID == null)
{
MessageBox.Show(Resources.ERROR_SAVE, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
ISoleService soleService = UnityDependencyResolver.Instance.GetService<ISoleService>();
List<Sole> entity = soleService.All().Where(s => s.ShoeLastID == shoeLastID).ToList();
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
}
return false;
}
The compiler can't guarantee that the first call to Count means that the foreach will loop at least once (with good reason, because you could, if you wished, create a collection where this wasn't true). You can do this instead (with no need for the outer if):
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
return false;

Nullable Property throwing NullReferenceException on .HasValue

This line of (C#) code
if (!currentLap.S1.HasValue)
is giving me
System.NullReferenceException: Object reference not set to an instance of an object.
provided I'm sure that currentLap variable is instantiated (because it's being used a few lines before and it is a local variable) and it has following property:
private double? _s1;
[DefaultValue(null)]
[JsonConverter(typeof(ShortDoubleConverter))]
public double? S1
{
get { return _s1; }
set { _s1 = value; }
}
how can it possibly throw NullReferenceException? Can it be something to do with optimization on Release mode?
Thanks,
Stevo
EDIT:
here is full method code.
public void Update(DriverData driverData)
{
LapInfo currentLap = this.CurrentLap;
if (currentLap != null &&
this.LastDriverData != null &&
driverData.TotalLaps != this.LastDriverData.TotalLaps &&
driverData.InPits &&
driverData.Speed < 10 &&
!this.LastDriverData.InPits)
{
currentLap.Escaped = true;
}
this.LastDriverData = driverData;
if ((currentLap == null || currentLap.Lap != driverData.LapNumber) &&
!this.Laps.TryGetValue(driverData.LapNumber, out currentLap))
{
currentLap = new LapInfo() { Lap = driverData.LapNumber, Parent = this, Class = driverData.Class };
this.Laps.Add(driverData.LapNumber, currentLap);
int lapsCount = 0, completedDriverLaps = 0, cleanLaps = 0;
this.TotalLaps = driverData.TotalLaps;
//if it's not the first lap
if (driverData.TotalLaps > 0)
{
//previous lap
if (this.CurrentLap == null || !this.CurrentLap.Escaped)
{
this.CompletedLaps++;
if (this.CurrentLap == null || !this.CurrentLap.MaxIncident.HasValue)
this.CleanLaps++;
}
}
foreach (DriverLapsInfo laps in this.Parent.LapsByVehicle.Values)
{
lapsCount += laps.TotalLaps;
completedDriverLaps += laps.CompletedLaps;
cleanLaps += laps.CleanLaps;
}
this.Parent.Parent.SetLapsCount(driverData, lapsCount, driverData.Class, completedDriverLaps, cleanLaps);
}
this.CurrentLap = currentLap;
//add incidents
if (driverData.Incidents != null)
{
foreach (IncidentScore incident in driverData.Incidents)
{
this.CurrentLap.MaxIncident = Math.Max(this.CurrentLap.MaxIncident ?? 0, incident.Strength);
this.CurrentLap.Incidents++;
this.Incidents++;
}
}
LapInfo previousLap = null;
if ((this.PreviousLap == null || this.PreviousLap.Lap != driverData.TotalLaps) &&
this.Laps.TryGetValue(driverData.TotalLaps, out previousLap))
{
this.PreviousLap = previousLap;
if (!this.PreviousLap.Date.HasValue)
{
this.PreviousLap.Date = DateTime.UtcNow;
}
}
if (currentLap.Position == 0)
currentLap.Position = driverData.Position;
if (driverData.CurrentS1 > 0)
{
**if (!currentLap.S1.HasValue)**
{
this.UpdateBestS1(driverData.BestS1);
this.Parent.Parent.UpdateBestS1(driverData.BestS1, driverData.UniqueName);
currentLap.UpdateS1(driverData.CurrentS1, driverData);
//reset the best split set at the finish line
if (this.PreviousLap != null && this.PreviousLap.SplitBest < 0)
this.PreviousLap.SplitBest = 0;
}
if (driverData.CurrentS2.HasValue && driverData.CurrentS1.HasValue && !currentLap.S2.HasValue)
{
double s2 = driverData.CurrentS2.Value - driverData.CurrentS1.Value;
this.UpdateBestS2(s2);
this.Parent.Parent.UpdateBestS2(s2, driverData.UniqueName);
currentLap.UpdateS2(s2, driverData);
}
}
if (this.PreviousLap != null)
{
if (driverData.LastLap > 0)
{
if (!this.PreviousLap.S3.HasValue && driverData.LastS2.HasValue)
{
double s3 = driverData.LastLap.Value - driverData.LastS2.Value;
this.UpdateBestS3(s3);
this.Parent.Parent.UpdateBestS3(s3, driverData.UniqueName);
this.PreviousLap.UpdateS3(s3, driverData);
}
if (!this.PreviousLap.LapTime.HasValue)
{
double? bestLap = this.Parent.Parent.BestLap;
this.PreviousLap.UpdateLapTime(driverData, 0);
this.Parent.Parent.UpdateBestLap(this.PreviousLap, driverData.BestLap, driverData);
this.UpdateBestLap(driverData.BestLap, this.PreviousLap);
this.PreviousLap.UpdateLapTime(driverData, bestLap);
}
}
else
{
if (this.PreviousLap.SplitBest.HasValue)
this.PreviousLap.UpdateBestSplit();
if (this.PreviousLap.SplitSelf.HasValue)
this.PreviousLap.UpdateSelfSplit();
}
}
if (driverData.InPits)
{
switch (driverData.Sector)
{
case Sectors.Sector1:
if (previousLap != null)
previousLap.InPits = true;
break;
case Sectors.Sector3:
currentLap.InPits = true;
break;
}
}
//lap to speed
if (currentLap.TopSpeed < driverData.Speed)
{
driverData.TopSpeedLap = driverData.Speed;
currentLap.UpdateTopSpeed(driverData.Speed);
}
else
driverData.TopSpeedLap = currentLap.TopSpeed;
//overall top speed
if (this.TopSpeed < driverData.Speed)
{
driverData.TopSpeed = driverData.Speed;
this.TopSpeed = driverData.Speed;
this.Parent.Parent.UpdateTopSpeed(this.TopSpeed, driverData);
}
else
driverData.TopSpeed = this.TopSpeed;
}
There is no way on earth the code can make it to that line and currentLap beeing null.
Or am I going crazy? :)
.HasValue will not throw if the nullable reference is null, but a.b.HasValue will if a is null.
I suspect that currentLap == null. I know you say you're sure that currentLap is not null, but I think that's the most likely explanation. Can you post more code?
Update:
Thanks for posting your code.
This doesn't throw:
void Main() {
var f = new Foo();
Console.WriteLine (f.S1);
Console.WriteLine (f.S1.HasValue);
}
class Foo {
private double? _s1 = null;
public double? S1 {
get { return _s1; }
set { _s1 = value; }
}
}
Could you try to create a minimal reproduction? (minimal code that exhibits the issue)
Maybe have a look at the previous line of code :) - debugger often highlights the next line after the one where the NullReferenceException was actually thrown.

Categories

Resources