The proper way to use parameters/arguments in c#? - c#

I have an app that gets 3 main parameters: sum, substract, print. If one of this parameters is given the app calls the methods: sum for sum, substract for substract, print for print.
Calling with parameters all examples:
myapp.exe sum 1 2
myapp.exe substract 3
myapp.exe print whatever
This is my actual code which doesn't work
static void Main(string[] args)
{
Program package = new Program();
if (args[0] == #"sum")
{
package.sum(args[1], args[2]);
}
else if (args[0] == #"substract")
{
package.substract(args[1]);
}
else if (args[0] == #"print")
{
package.print(args[1]);
}
else
Console.Write("Invalid Parameters");
}
But this is the error I get when debugging:
A first chance exception of type 'System.IndexOutOfRangeException' occurred in myapp.exe
An unhandled exception of type 'System.IndexOutOfRangeException' occurred in myapp.exe
Additional information: Index was outside the bounds of the array.
What am I doing wrong? What is the best way to work with parameters ?

What am I doing wrong?
You are assuming that the program is always called with the proper number of parameters. Specifically, that
At least one parameter is present
When the initial parameter is sum or print, two parameters are present
When the initial parameter is add, three parameters are present
This is not always correct, depending on what the user enters. You need to add code checking for the length of the args array before referencing its elements:
if (args.Length < 2) {
Console.Error.Write("Invalid Parameters");
return;
}
if (args[0] == #"sum" && args.Length == 3) {
...
}
... // The rest of your code can assume that there's at least two args

The answer above is great but I feel like there is a little more to this answer than just the number of variables.
I find that the following type of solution works best for me when in need of a somewhat robust argument solution:
if (args.Length > 0)
{
if (args.Contains<string>("--help"))
{
Console.WriteLine("appname [--debug] [--bootstrap <bootstrap name>]");
Console.WriteLine(" --debug Runs \"appname\" in debug mode.")
Console.WriteLine(" --bootstrap If no bootstrap name is provided the default \"AppName v1.2\" will be used.")
Console.WriteLine("")
}
//simple single argument passed to application
if (args.Contains<string>("--debug"))
{
DEBUG_ON = true;
Console.WriteLine("Found argument: --debug");
}
//more complex relational argument passed to application
if (args.Contains<string>("--bootstrap"))
{
int bootstrapLoc = Array.IndexOf<string>(args, "--bootstrap");
//always check that there is one more argument in the array
if(args.Length > bootstrapLoc + 1)
{
string bootstrapArg = args[bootstrapLoc + 1];
//this is where you would do your error checking against the second argument, ex: determine that it is what is expected
if (bootstrapArg != null && bootstrapArg != "")
{
this.MongoDBInstallName = bootstrapArg;
Console.WriteLine("Using the passed bootstrap arg: " + bootstrapArg);
}
}
}
}
There are definitely better ways to do this and this by no means is fool proof but I just wanted to add some more detail to this question.

Related

Error Loging with variable names and values that was used in method

Is there any way, to log all variables and the values that were used in the method?
I want to see log information like I showed in the method ErrorWriter. I don't want to use something like ErrorWriter(names, values). Can anyone suggest a solution?
static int number3;
static void Main(string[] args)
{
number3 = 0;
Method(1, 2);
}
static void Method(int number, int number2)
{
int number4;
try
{
number4 = number / number2 / number3;
}
catch
{
ErrorWriter();
}
}
private static void ErroWriter()
{
/// number = 1
/// number2 = 2
/// number3 = 0
}
I need information about variable values which was used. For example. If i have a line number4=number/number2/number3 . How can i know which variable value was 0? Number 2 or number 3? That's why i need exact values. I don't want to hardcode parameter for every different method. I need dynamic solution.
I would use some kind of aspect programming/interception for this. Any other approach you take will probably end up being to low level or complicated for something that shouldn't be on the actual class you are implementing.
Error Handling is not necessarily one of the responsabilities of your class so it can be delegated to an aspect.
One possible solution would be to use some kind of IoC framework (like Unity and Ninject, there are many others) and set up your classes to be intercepted by an error handling interceptor, which will catch exceptions and log the parameters in those cases.
This article has an example using Unity that can point you to the right solution
As others have stated, using standard error handling routines would probably serve you much better than what you're trying to accomplish here.
Anyway, your ErrorWriter method could take a parameter of type int[].
chatch
{
ErrorWriter(new int[3] { number1, number2, number3 });
}
(...)
private static void ErrorWriter(int[] numbers)
{
int index = 1;
foreach(var i in numbers)
{
Console.WriteLine("number" + index.ToString() + " = " + i.ToString());
}
}
Seems like you would want to avoid the try/catch in this case.
Check in Method if your input is valid (ie. number, number 2 and number 3). Throw exception if validation fails.
If all you want is to be able to determine if one of the variables is zero (or has failed validation), throw the Exception in a check like follows:
private void Method(int number, int number2) {
if (number3 == 0) throw new Exception("number3 is zero, resulting in division by zero");
if (number2 + number == 0) throw new Exception("number2 + number is zero");
number 4 = (number2 + number) / number3
}
No try/catch needed. The exception will bubble up.
Always check your input (instance variables and parameters) before using in any method!

String Comparison Troubles

Let me start by saying that I have read up on my problem, specifically this question and this one also. My problem is a little different, however. I understand the differences between the different methods, but cannot get my code to run correctly for the life of me.
In part of my code, I have the comparison below. But the comparison always fails, and "Type is:leg" prints out.
if (String.Compare(timer.Type,"leg",true) == 0)
{
timer.StopTime = DateTime.Now;
// TODO Log into database here
toRemove.Add(timer);
}
//Couple more conditions in here...
else
{
Console.WriteLine("Attempting to remove cycle timer of invalid type");
Console.WriteLine("Type is:" + timer.Type);
//TODO: Log error
}
I also tried alternative methods, but none of them seem to work for me.
if(timer.Type == "leg" || timer.Type == "Leg") //Fails
if(time.Type.Equals("leg") || timer.Type == "Leg") //Fails
String type = timer.Typer; //Worth a shot...
if(type == "leg" || type == "Leg") //No luck
EDIT: More code has been requested, so here is the entire method.
private void stopFinishedTimers(AGVData agv)
{
List<CycleTimer> toRemove = new List<CycleTimer>();
foreach (CycleTimer timer in AllRunningCycleTimers)
{
if (agv.CurrentRFIDNumber == timer.CycleStopRfid)
{
if (String.Compare(timer.Type,"leg",true) == 0)
{
timer.StopTime = DateTime.Now;
// TODO Log into database here
toRemove.Add(timer);
}
else if (timer.Type.Equals("route") || timer.Type.Equals("Route"))
{
timer.StopTime = DateTime.Now;
// TODO Log into database here
toRemove.Add(timer);
}
else
{
Console.WriteLine("Attempting to remove cycle timer of invalid type");
Console.WriteLine("Type is:" + timer.Type);
//TODO: Log error
}
}
}
Where CycleTimers are a class containing a fields called type, accessed through a property.
I'll add my two cents:
The line String type = timer.Typer seems wrong because the property name is Type in most of your examples. Also if(time.Type.Equals("leg") || timer.Type == "Leg") seems suspicious since you are referencing time and timer instead of the same variable both times.
Lastly, I always always use StringComparison.Ordinal when comparing strings in .Net because of culture info and character set differences, etc. I'm not sure if that could be an issue but see this for more information.
EDIT:
On a side note, StringComparison.OrdinalIgnoreCase is also an option.
Debug and put a break statement to see what timer.Type equates to, or put a Console.WriteLine(timer.Type.ToString())... Could timer have gone out of scope?
or maybe change the test to timer.Type.ToString() == "Leg"

c# try and catch/ error handling

I am currently working on a program and I am finalising it by going over with error handling. I have several cases which look like:
int stockbankInput = Convert.ToInt32(Console.ReadLine());
Here, the user must enter either 1, 2, 3. I have tried to use an if statement to catch the error if anybody inputs a blankspace/string/character or a number that is not 1,2 or 3 but it doesn't work in the same sense as a string input. Below is what I have tried:
if(stockbankInput == null)
{
Console.WriteLine("Error: Please enter either 1, 2 or 3");
stockbankInput = 0;
goto menuRestartLine;
}
However, you cannot link 'null' with an integer input, only a string. Can anybody help with this please?
Use the Int32 TryParse method:
int input;
var successful = Int32.TryParse(Console.ReadLine(), out input);
if (!successful)
// do something else
else
return input;
You're checking if an int is null, which will always return false because an int cannot be null.
You can use 'int?' (Nullable int) but Convert.ToInt32 will not return null. If the value of the int cannot be resolved it will resolve to the default value of zero. You can either check if the returned int is zero or do some further checking of the returned string:
int input = 0;
string errorMessage = "Error: Please enter either 1, 2 or 3";
while(true)
{
try
{
input = Convert.ToInt32(Console.ReadLine());
if (input == 0 || input > 3)
{
Console.WriteLine(errorMessage);
}
else
{
break;
}
}
catch(FormatException)
{
Console.WriteLine(errorMessage);
}
}
With this you your returned value "int input" will either be 0 or the number you entered and FormatExceptions caused by the string to convert containing symbols other than the digits 0-9 will be caught in the try/catch statement.
give this sample program a try:
static void Main(string[] args)
{
int stockbankInput = 0;
bool firstTry = true;
while(stockbankInput < 1 | stockbankInput > 3)
{
if(!firstTry)
Console.WriteLine("Error: Please enter either 1, 2 or 3");
firstTry = false;
Int32.TryParse(Console.ReadLine(), out stockbankInput);
}
}
First of all, don't use goto statements. They are considered bad practice, and it's like a blinding red light when reading your question - that's all I can focus on.
As per your question, an int or Int32 cannot be null. So you can't compare it to null. Give it a default value, and then check that.
This is a scenario where you don't need to check for an error, but just need to validate input. Use TryParse, which will set your out parameter if the parse is successful, or else set it to 0.
Next, you want to loop until you are given good input. An if statement is executed once, a loop will guarantee that when you leave it, your input will be valid.
Lastly, the firstTry is just a nice way to let the user know, after their first try, that they screwed up.

How do I best handle arguments with modifiers in a console program?

I'm writing an argument parser for a console program, but I'm certain that my current implementation is not the best way to do this. Since this is a common problem, is there a standard/better/best way to pass multiple arguments with optional modifiers to a console program?
private static void Main(params string[] args)
{
for (int i = 0; i < args.Length; i++)
{
// Is there a valid argument?
if (args[i] == "/r")
{
Console.WriteLine("Argument: /r");
// Is there a successive argument?
if (i + 1 < args.Length)
{
// Is the successive argument an argument or a modifier?
if (args[i + 1].IndexOf("/", StringComparison.CurrentCultureIgnoreCase) == -1)
{
Console.WriteLine("Argument: /r " + args[i + 1]);
}
}
}
}
}
The main problem I see with this implementation is that I'd have to rewrite the last two if blocks for each argument and modifier, which would become unwieldy for a large program, I think.

Adding custom variables to the end of application path when executed in c#

How would I read custom variables end of my application path? I am not sure exactly what they are called, but for example in in the shortcut path of Google Chrome you can add settings to the end of the path such as:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe --Custom-setting"
How would I read these arguments after my application has started?
They are arguments that you are passing to the application. For example take the following application:
static void Main(string[] args)
{
if (args == null)
{
Console.WriteLine("args is null"); // Check for null array
}
else
{
Console.Write("args length is ");
Console.WriteLine(args.Length); // Write array length
for (int i = 0; i < args.Length; i++) // Loop through array
{
string argument = args[i];
Console.Write("args index ");
Console.Write(i); // Write index
Console.Write(" is [");
Console.Write(argument); // Write string
Console.WriteLine("]");
}
}
Console.ReadLine();
If you ran the following from the command line:
"C:\ConsoleApplication1.exe" a b c
The program would display:
args length is 3
args index 0 is [a]
args index 1 is [b]
args index 2 is [c]
http://msdn.microsoft.com/en-us/library/acy3edy3.aspx
http://msdn.microsoft.com/en-us/library/cb20e19t.aspx
These values will be contained in the args array in the Main() method which serves as the entry point of your application.
static void Main(string[] args) { }
Command-Line Arguments
Main() and Command-Line Arguments
They are called command line arguments. Although you can parse them manually directly from your main() program entry point, there are several helper libraries which can make life even easier for you and your users, such as this one here and here.

Categories