I am making a save option in my program that saves the changes to a file. I am using this code to save and get a MessageBox to show the result of the process I am getting an error on this line "Object reference not set to an instance of an object."
SaveFileCheck = StockHandler.SaveChangesToFile();
this is my code
private void Save_Click(object sender, EventArgs e)
{
bool SaveFileCheck = false;
var result = MessageBox.Show("Are you sure you want to Save the changes ?", "My Application",
MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk);
if (result == DialogResult.Yes)
{
SaveFileCheck = StockHandler.SaveChangesToFile();
if (SaveFileCheck)
{
MessageBox.Show("The process was a success");
}
else
{
MessageBox.Show("The process failed please make sure that the file is not been used and try again");
}
//Save the file back
}
}
}
}
public bool SaveChangesToFile()
{
try
{
if (FileName != null)
{
using (StreamWriter Write = new StreamWriter(FileName, false))
{
foreach (Stock s in FileStockList)
{
Write.Write(s.ToString() + "\r\n");
}
}
}
else {
return false;
}
}
catch(IOException ex)
{
return false;
throw new ArgumentException("something went wrong an error" + ex + "is been cought");
}
return true;
}
StockHandler is null.
If StockHandler is not a static class, you need to create an instance of it before you can call methods on it:
var handler = new StockHandler();
SaveFileCheck = handler.SaveChangesToFile();
Or, if StockHandler is a member variable:
StockHandler = new // something
You haven't shown what StockHandler is, or where you're getting it from - but it looks like it's null. You'll need it to be a reference to a valid object. There's not a lot more we can say just from the code you've given.
Note that this has nothing to do with a method returning a bool.
It could be that StockHandler is null, or something in the SaveChangesToFile method is null or invalid.
EDIT
See here:
private StockHelper StockHandler;
StockHandler.SaveChangesToFile(); // = bang :(
You need to initialize the StockHelper instance:
private StockHelper StockHandler = new StockHelper();
StockHandler.SaveChangesToFile(); // = okay :)
I'm assuming that this code doesn't compile, which probably means that StockHandler is null. Otherwise, the error would likely be pointing to the SaveChangesToFile method.
Secondly, you either need to swallow exceptions in the SaveChangesToFile() method (not advisable), or you need to remove the return statement and throw the exception. If you do decide to throw an exception, it should definitely not be an ArgumentException, as it has nothing to do with arguments supplied to the method (or lack thereof).
What is stockhandler -- your SaveChangesToFile method is an instance method -- so have you instantiated a variable 'StockHandler' to an instance of whatever class contains the method SaveChangesToFile();
Related
I'm working with the following code, but I'm not sure how is the proper way to do it.
try
{
// Do code for Try1
Console.WriteLine("Try1 Successful");
}
try
{
// If try1 didn't work. Do code for Try2
Console.WriteLine("Try2 Successful");
}
try
{
// If try2 didn't work. Do code for Try3
Console.WriteLine("Try3 Successful");
}
catch (Exception)
{
// If try1, 2 and 3 didn't work. print this:
Console.WriteLine("The program failed");
}
What I want is to try 3 different ways of a task, and if the 3 of them fail, print "The program failed", but if one of them is successful, don't do the other ones and continue with the program
Edit:
The task that I am trying to do, is looking for a NETWORK PATH.
The Task 1 will look if a path can be opened, if so OPEN THE DIRECTORY.
If not: Task 2 will look if a second path can be opened, if so OPEN THE DIRECTORY.
If not: Task 3 will look if a third path works, if so OPEN IT.
If not "no paths can be found on this pc"
You can make it without try catch block.
For the simplicity make that Task1, Task2, Task3, have some kind of return types.
For example if they return boolean type. TRUE if Task succededd or FALSE if Task failed.
Or they can return some custom type with boolean result, and string error message. I would not go with nested try catch blocks.
executeTasks() {
Console.WriteLine("Try 1");
if (Task1()) return;
Console.WriteLine("Try 2");
if (Task2()) return;
Console.WriteLine("Try 3");
if (Task3()) return;
Console.WriteLine("The program failed");
}
Hopefully this snippet can be easily adapted to meet your needs.
namespace StackOverflow69019117TryCatch
{
using System;
using System.IO;
public class SomeClass
{
public void MainMethod()
{
var paths = new string[] {
#"C:\Users\otherUser\Documents", // exists but I don't have access to it
#"C:\temp", // exists but doesn't contain the folderToSearchFor subfolder
#"Z:\doesntexist", // doesn't exist
};
foreach (var path in paths)
{
Console.WriteLine($"Trying with path {path}");
if (this.ProcessDirectory(path, "folderToSearchFor"))
{
// We've succeeded so exit the loop
Console.WriteLine($"Succeeded using path {path}");
return;
}
else
{
// We've failed so continue round the loop and hope we succeed next time
Console.WriteLine($"Failed using path {path}");
}
}
}
private bool ProcessDirectory(string directoryPath, string folderToSearchFor)
{
// First, check whether the directory we want to search actually exists.
if (!Directory.Exists(directoryPath))
{
// Then the directory we're trying to search in doesn't exist.
// Return false, no need to incur the overhead of an exception.
Console.WriteLine($"Directory {directoryPath} doesn't exist");
return false;
}
// This doesn't appear to throw an exception if directoryPath isn't accessible to the current user.
// Instead it just returns whatever the current user has access to (which may be an empty array).
var propFolderCandidates = Directory.GetDirectories(directoryPath, $"{folderToSearchFor}*");
// But did it return anything?
// If not then what we're looking for either doesn't exist or the user doesn't have access to it.
if (propFolderCandidates.Length == 0)
{
// Then there's no folder here matching the search path.
// Return false, no need to incur the overhead of an exception.
Console.WriteLine($"Couldn't find folder matching {folderToSearchFor} in {directoryPath}");
return false;
}
var propFolder = propFolderCandidates[0];
// Consider implementng similar checks in Process.Start.
// e.g. if it's reading a file, check whether the file exists first
if (Process.Start(propFolder))
{
Console.WriteLine($"Process.Start succeeded using {directoryPath}");
return true;
}
else
{
Console.WriteLine($"Process.Start failed using {directoryPath}");
return false;
}
}
}
}
As #BionicCode has pointed out in various comments, it's less expensive to check whether an action might throw an exception before performing that action, than it is to perform the action and then handle the exception if it's thrown by the action.
I had to do a bit of digging to establish what happens when Directory.GetDirectories tries to get the subfolders of a folder that the current user doesn't have access to - I was expecting it to throw an exception, but it seems that it doesn't, it just returns an empty array representing the nothing that the current user has access to in that location, so no exception to handle in that scenario.
Throwing and catching of exceptions definitely has its place in .net software, but you should treat it as something to fall back on if something happens which you can't anticipate at design time - if there's a way at design time of detecting that a particular action isn't going to work, then you should detect it and report to the caller that the action they've requested won't work, rather than performing the action and trying to handle any exception it might throw.
There is some wise advice from Microsoft on the subject of best practice for exceptions.
Use exception handling if the event doesn't occur very often, that is, if the event is truly exceptional and indicates an error (such as an unexpected end-of-file). When you use exception handling, less code is executed in normal conditions.
Check for error conditions in code if the event happens routinely and could be considered part of normal execution. When you check for common error conditions, less code is executed because you avoid exceptions.
Hope this is useful :-)
You're gonna have to nest your try-catch blocks:
try {
Console.WriteLine("Try1 successful");
} catch {
try {
Console.WriteLine("Try2 successful");
} catch {
try {
Console.WriteLine("Try3 successful");
} catch {
Console.WriteLine("The program failed");
}
}
}
I have already found a way, to be honest I don't know if this is the best way, but totally works.
The solution was to nest a few try-catch(exception)
This is what I am doing...
try
{
try
{
//Check if PROP can be found inside initial path A
string[] PROP_FOLDER = Directory.GetDirectories(Full_PathA, $"{PROP}*");
Process.Start(PROP_FOLDER[0]);
//Open PROP in path A and RETURN
status_label.Text = " Found it!";
status_label.ForeColor = Color.LimeGreen;
}
catch (Exception) //If an error occurs on path A
{
try
{
//Check if PROP can be found inside initial path B
string[] PROP_FOLDER = Directory.GetDirectories(Full_PathB, $"{PROP}*");
Process.Start(PROP_FOLDER[0]);
//Open PROP in path B and RETURN
status_label.Text = " Found it!";
status_label.ForeColor = Color.LimeGreen;
}
catch (Exception) //If an error occurs on path B
{
//Check if PROP can be found inside initial path C
string[] PROP_FOLDER = Directory.GetDirectories(Full_PathC, $"{PROP}*");
Process.Start(PROP_FOLDER[0]);
//Open PROP in path C and RETURN
status_label.Text = " Found it!";
status_label.ForeColor = Color.LimeGreen;
}
}
}
catch (Exception) //If PROP cannot be found on any of those paths, the PROP doesn't exist
{
status_label.Text = " Not Found!";
status_label.ForeColor = Color.Red;
}
I'm writing a code to create a new object with key metadata being provided by a user input form. I'm wondering if there's a way to return the object (q) in the try block and not at the end of the method?
Here's my current code with some notes about how I want it all to look:
public NewSearchQuery GetEntry()
{
//pull all input field information and store ready for validation
string name = Convert.ToString(Companies.SelectedItem);
string location = String.Concat(Convert.ToString(Property.Text), " ", Convert.ToString(SearchLocation.Text).ToLower());
string searchtype = Convert.ToString(Search.SelectedItem);
var q = new NewSearchQuery();
//check all required input fields are filled in
if (String.IsNullOrEmpty(name) || String.IsNullOrEmpty(location) || String.IsNullOrEmpty(searchtype))
{
MessageBox.Show("Please ensure you have filled in all the required fields (*) before proceeding", "Insufficient Information");
this.ShowDialog();
}
else
{
try
{
q.GetFormData(name, location, searchtype, Paid.Checked); //replace this with a constructor for var q
q.Contract = ThisAddIn.GetContract(q.Name);
q.CreateIdNum();
q.CreateFilePath(q.Contract, q.RefNum);
q.CalculateFees();
}
catch (Exception d)
{
MessageBox.Show(Convert.ToString(d)); //return null if the try fails
}
}
return q; //relocate this to the try block
}
I want to make these changes because I suspect that returning the q value irrespective of the process working or not is causing my winform to error out it if try to exit it prematurely.
Is there a way I can get around the inevitable 'not all code paths return a value' error?
You can rewrite your method as follows:
public NewSearchQuery GetEntry()
{
//pull all input field information and store ready for validation
string name = Convert.ToString(Companies.SelectedItem);
string location = String.Concat(Convert.ToString(Property.Text), " ", Convert.ToString(SearchLocation.Text).ToLower());
string searchtype = Convert.ToString(Search.SelectedItem);
//check all required input fields are filled in
if (String.IsNullOrEmpty(name) || String.IsNullOrEmpty(location) || String.IsNullOrEmpty(searchtype))
{
MessageBox.Show("Please ensure you have filled in all the required fields (*) before proceeding", "Insufficient Information");
this.ShowDialog();
return null;
}
try
{
var q = new NewSearchQuery();
q.GetFormData(name, location, searchtype, Paid.Checked); //replace this with a constructor for var q
q.Contract = ThisAddIn.GetContract(q.Name);
q.CreateIdNum();
q.CreateFilePath(q.Contract, q.RefNum);
q.CalculateFees();
return q;
}
catch (Exception d)
{
MessageBox.Show(Convert.ToString(d)); //return null if the try fails
return null;
}
}
Now all code paths return a value. I omitted the else block, because if you leave the method inside the if block. This means, that the code following the if block is never executed when your condition is true, as it would be with the else block. The advantage of this is that you don't have so much nested bracings, which makes the code easier to understand.
Be sure to check whether the return value is not null, otherwise you might have a NullReferenceException.
Yes,
Write a return statement within every single block.
if(something)
{
return value;
}
else
{
try
{
return value;
}
catch
{
return value;
}
}
I have a problem regarding try catch when creating an object in C#.
My problem appears when an object is supposed to be created and the webservice which defines the object isn't available or has been modified.
That is the problem I would like my program to handle.
When I try to do this:
try
{
var Customer = new Customer();
}
catch
{
//handling the exception.
}
Later on in my program I need that particular object, but due to the try catch the object isn't available in all cases (of course when the try fails, the object isn't created).
without if(customer != null)
if (insertCustomer(lead, LS_TS, out Customer) == true)
{
insert = true;
}
with if(customer != null)
if(customer != null)
{
if (insertCustomer(lead, LS_TS, out Customer) == true)
{
insert = true;
}
}
No matter what, the compiler says: "The name 'Customer' does not exist in the current context
How do I solve this problem? I need a program to be running all the time and when checking an object which isn't created then I need to exit the method and try again later.
Thanks in advance
You can just do this:
Customer customer = null;
try
{
customer = new Customer();
}
catch
{
// handling the exception.
}
and whenever you need to use the object customer you should do this
if(customer != null)
{
// do stuff
}
I need to capture any exceptions thrown by the validator but I cannot figure out how to due it. Here is the code I have tried:
internal static class XMLValidator
{
public static void Validate(XElement elem)
{
string xsdMarkup;
using(var file = new StreamReader(Constants.Xsd))
{
xsdMarkup = file.ReadToEnd();
}
XmlSchemaSet schema = new XmlSchemaSet();
bool valid = true;
schema.Add(XmlSchema.Read(XElement.Parse(xsdMarkup).CreateReader(), (o, e) => { }));
new XDocument(elem).Validate(schema, (o, e) => { valid = false; exception = e; });
if (valid == false)
{
throw exception;
}
valid = true;
}
}
I get a "the name exception does not exist in current context" error. I'm pretty sure that the problem is that I have not given exception a data type. However I have no idea what type to use.
I tried adding var before the exception but then it's not recogonized inside of the if statement and of course var cannot be declared outside of a method
I then tried declaring exemption globally as a string and setting to e like this:
exception = e.ToString();
but then I can't throw it inside of the if statement.
How would I go about doing this?
The delegate you're using creates an XmlSchemaValidationException:
XmlSchemaValidationException exception = null;
new XDocument(elem).Validate(schema, (o, e) => { valid = false; exception = e.Exception; });
if (valid == false)
{
throw exception;
}
Well, in this particular case you probably want to create your own type of Exception to throw.
public class InvalidDataException : Exception
{ }
(There are times where it's appropriate to do something within the definition of the class, but in most cases you really don't need anything.)
Then you can do something like this:
throw new InvalidDataException("Error message goes here");
Or, you can find some existing type of exception to throw that is created by the standard library or what have you.
I have to create a bunch of methods that look like this. The things that change will be the method name, the return type and the lines marked in the middle - the rest will be the same. Is there a clean way to refactor this so that I don't repeat myself?
private bool CanPerform(WindowsIdentity identity, string applicationName, int operation)
{
IAzApplication3 application = null;
IAzClientContext3 context = null;
try
{
application = this.store.OpenApplication(applicationName, null) as IAzApplication3;
ulong token = (ulong)identity.Token.ToInt64();
context = application.InitializeClientContextFromToken(token, null) as IAzClientContext3;
// lines that change go here
}
catch (COMException e)
{
throw new SecurityException(string.Format("Unable to check operation '{0}'", operation), e);
}
finally
{
Marshal.FinalReleaseComObject(context);
Marshal.FinalReleaseComObject(application);
}
}
I realise this is probably basic stuff but I work alone so there's no one else to ask.
It sounds like a delegate would be appropriate here, with a generic method to cover the return type changing:
private T ExecuteWithIdentity<T>(WindowsIdentity identity,
string applicationName, int operation,
Func<IAzApplication3, IAzClientContext3, T> action)
{
IAzApplication3 application = null;
IAzClientContext3 context = null;
try
{
application = this.store.OpenApplication(applicationName, null) as IAzApplication3;
ulong token = (ulong)identity.Token.ToInt64();
context = application.InitializeClientContextFromToken(token, null) as IAzClientContext3;
return action(application, context);
}
catch (COMException e)
{
throw new SecurityException(
string.Format("Unable to check operation '{0}'", operation), e);
}
finally
{
Marshal.FinalReleaseComObject(context);
Marshal.FinalReleaseComObject(application);
}
}
Then you put the code for each check in a separate method, or even just use a lambda expression:
bool check = ExecuteWithIdentity(identity, "Foo", 10,
(application, context) => context != null);
or
string check = ExecuteWithIdentity(identity, "Foo", 10, SomeComplexAction);
...
private static string SomeComplexAction(IAzApplication3 application,
IAzClientContext3 context)
{
// Do complex checks here, returning whether the user is allowed to
// perform the operation
}
You may want to change the delegate type of course - it's not clear what operation is meant to be used for, for example.
I would also strongly consider casting instead of using as. If the application or context is returned from OpenApplication/InitializeClientContextFromTokenas a non-null value which just isn't the right type, do you really want to handle that the same was as a null value being returned?
You could do your error handling slightly higher up the stack, so rather than catching and rethrowing the exception inside the method you could do it where the method is called?
If your method calls are all wrapped in a Manager class that might save a bit of time. If they're just ad-hoc called everywhere then naturally maybe not :)
I hope that might help.