Understanding Return Values in C# - c#

So this question follows on from a previous post that I am just trying to understand in full before I move on to more complicated C# stuff.
My question relates specifically to the return value of a function.
Consider the following function code:
public static void DisplayResult(int PlayerTotal, int DealerTotal){
if (PlayerTotal > DealerTotal) {
Console.WriteLine ("You Win!");
Console.ReadLine ();
}
else if (DealerTotal > PlayerTotal) {
Console.WriteLine ("Dealer Wins!");
Console.ReadLine ();
} else {
Console.WriteLine ("It is a Draw!");
Console.ReadLine ();
}
I could be wrong of course but I believe that the "void" keyword in the first line of code means that the function code result does NOT return a value.
What I am trying to understand is - the function calculates a result. It distributes text (eg: "you win!" etc) based on the result. Is the result of the function not considered a value?
By my own (novice) logic, I would have thought one of two things:
The return value of this function is a string because it is the output of the calculated result.
The return value of this function is an int because it calculates int results.
I hope this makes sense. I think understanding this concept will make it easier for me in future to write functions without second guessing return values. If anyone has an example of a function that actually DOES return a value it would also be appreciated.

A bit of terminology first: C# doesn't have functions, it has methods.
Return values give some value to the method's caller. They aren't related to the statements executed within that method, except for the return statement. The method's signature dictates what (if any) type is returned by that method.
public void NoReturnValue()
{
// It doesn't matter what happens in here; the caller won't get a return value!
}
public int IntReturnValue()
{
// Tons of code here, or none; it doesn't matter
return 0;
}
...
NoReturnValue(); // Can't use the return value because there is none!
int i = IntReturnValue(); // The method says it returns int, so the compiler likes this

A void method, as you have surmised, is one that returns no value. If you wrote:
var myResult = DisplayResult(3, 7)
you would get an error because there is no returned value to assign to myResult.
Your method outputs text to the console. This is a "side effect" of the method, but has nothing to do with its return value.
Also, the fact that your method interacts with ints has nothing to do with what its return value is either.
As a final point. The most basic thing to keep in mind is that a return value is a value that comes after the return keyword:
return "All done!";
Anything that doesn't involve the return keyword is not a return value.

calling Console.writeline is not returning from the DisplayResult method/function
what you have is 3 execution paths only one of which can happen. after it happens the method/function returns void not a string
Tip:
you could get rid of the Console.WriteLine and .ReadLine and replace it with return "result of if statment"; then call your method/function like Console.WriteLine(DisplayResult(/*params*/)); which means you only write Console.WriteLine()/.ReadLine() once
public static string DisplayResult(int PlayerTotal, int DealerTotal){
if (PlayerTotal > DealerTotal) {
return "You Win!"
}
else if (DealerTotal > PlayerTotal) {
return "Dealer Wins!";
} else {
return "It is a Draw!" }}
in main():
Console.WriteLine(DisplayResult(playerscore,dealerscore));
Console.ReadLine();

Related

Function returns only the first value of the input variable

I have a problem with the variable result. I have a function that asks for the input number. It returns the first input of the AskForNumber function. Can anyone help me, please? I'm new in C# and don't know many details I should. I hope for your help:))
that's the main function
static void Main() {
string playersNum = AskForNumber(numberLength);
Console.WriteLine(playersNum);
}
that's the function that asks for the number
static string AskForNumber(int numberLength) {
Console.WriteLine($"Write number of Length {numberLength}");
string number_string = Console.ReadLine();
if (!CheckCondition(numberLength, number_string)) {
AskForNumber(numberLength);
}
return number_string;
}
then the number should be checked in the CheckCondition function and return whether its true or false
static bool CheckCondition(int length, string number_string) {
if (!int.TryParse(number_string, out int number)) {
Console.WriteLine("thats nan!!");
return false;
} else if (number_string.Length != length) {
Console.WriteLine($"number's length must be {length} digits");
return false;
}
return true;
}
depends on that it should return the number in the variable only when it's true
that's the result of the terminal
Write number of the length 4
qwerty
Thats nan!
1234
qwerty (Thats the result of the Console.WriteLine(playersNum); in the main function)
It's because you are calling AskForNumber() recusively.
In Main you are calling AskForNumber() for the first time and enter "querty". Then the CheckCondition method returns false because it is not a number and you are calling AskForNumber() again. Then you enter "1234" for which the CheckCondition returns true and therefore "1234" is retuned by the second time AskForNumber() is called. "1234" is returned to the first time AskForNumber() is called where you don't do anything with the returned value, just leave the if block and return the value which is stored in number_string. But because you did not assign the return value of the second call to AskForNumber() to this variable it still contains "qwerty" and therefore the Main receives "qwerty" and prints it.
Just change your code to
static string AskForNumber(int numberLength) {
Console.WriteLine($"Write number of Length {numberLength}");
string number_string = Console.ReadLine();
if (!CheckCondition(numberLength, number_string)) {
return AskForNumber(numberLength); // Return statement added here
}
return number_string;
}
and it will work as expected.
You can either return the value then call the method or call the method while returning the value.
static string AskForNumber(int numberLength) {
Console.WriteLine($"Write number of Length {numberLength}");
string number_string = Console.ReadLine();
if (!CheckCondition(numberLength, number_string)) {
return AskForNumber(numberLength); /* this will call the method in a return statement
}
return number_string;
}

Unassigned variable in return statement

for some reason I don't seem to be able to put the return in a fashion that captures this stored procedure's return value (0 or -1), either it returns the value which was used to initialize the variable or keeps telling me the local variable is unassigned.
public int changePass(int idUsuario, String old_pass, String new_pass)
{
int result;
try
{
DataTable tablaResultado =
DataBaseAccess.advanceStoredProcedureRequest(
"pa_usuario_change_pass",
new SPP[]
{
new SPP("id_usuario", idUsuario.ToString()),
new SPP("old_pass", old_pass.ToString()),
new SPP("new_pass", new_pass.ToString())
});
if (tablaResultado.Rows.Count > 0)
{
if (tablaResultado.Rows[0] != null)
{
result = (int.Parse(tablaResultado.Rows[0].ItemArray[0].ToString()));
}
}
return result;
}
catch (System.Data.SqlClient.SqlException sqlException)
{
throw sqlException;
}
}
I have multiple methods which follow the same pattern and all of those works, I have been trying to get this to work for awhile now, and I'm sure I'm overlooking something very, very obvious. Either way I cannot find it right now so I was hoping someone could refresh my memory or give me a tip.
The code only assigns a value to the result variable if two different conditions both happen to be true. That is, if the row count is > 0 and the first row is non-null. The compiler is telling you, completely legitimately, that your code contains a path to the return statement where the variable being used hasn't been assigned a value yet.
You need to decide what the method should return if either of those conditions are not true, and then assign that value to the result variable as part of its initialization.
EDIT:
To be clear: it seems you may be overlooking the possibility that your code won't successfully execute the stored procedure. But it can only return a value to be assigned to result when those two conditions are true. You either need to pick a default value that is reasonable to return when one or the other of the conditions aren't true, or you need to fix the code so that those conditions are always both true (and so the SP always executes successfully).

not all code paths return a value in c#

I'm trying to make clap programe for kinect in c# but I'm getting this error "not all code paths return a value " for the GetJointDistance method
here is my method
The method you have written supposedly returns a float:
private float GetJointDistance
However, your method body doesn't have any return statements - so not only do not all code paths return a value, none do.
You should fix this by adding a return:
private float GetJointDistance(Joint handR, Joint handL)
{
Skeleton s = new Skeleton();
Joint handRight = s.Joints[JointType.HandRight];
Joint handLeft = s.Joints[JointType.HandLeft];
if (handRight.TrackingState == JointTrackingState.Tracked &&
handLeft.TrackingState == JointTrackingState.Tracked)
{
this.GetJointDistance(handRight, handLeft);
}
return xyz; // xyz must be a float
}
Note that if your if statement means you need to return something else you need a second return in the if statement. Although you're quite likely to overflow the stack at the moment, depending on how often the state is Tracked.
Alternatively, make your method return void as you don't seem to need a return at the moment:
private void GetJointDistance

Function does not return negative value

I am doing a small project on 4x4 tic-tac-toe game. I am using Alpha Beta Search for finding the next best move. In the alpha beta search, I am using a cutoff evaluation function that is being called in "utility" function of the following algorithm
I implemented everything successfully, but the problem is the utility function doesn't return a negative value and I really don't know why! Following is the function
private static int utility(GameTreeNode gtn, bool isMin = false)
{
int nodeValue = 0;
switch (gtn.NodeBoard.getBoardStatus())
{
case Status.Success:
nodeValue = 50;
if (isMin) nodeValue = -50; /// here
break;
case Status.Incomplete:
if (isMin)
nodeValue = gtn.evaluate(State.X);
else
nodeValue = gtn.evaluate(State.O);
break;
}
// case Status.Draw:
return nodeValue;
}
isMin is set to true, when it is called from MinValue function
isMin is the move of O and the AI's move is X. If O wins the utility is supposed to return -50. But it returns only 0. I debugged the program and it actually assigns -50 to nodeValue (nodeValue changes in the debugger to -50), but when I receive in the Min or Max function, it is zero.
Note: All the int used in the entire project is signed int. No unsigned keyword is used, if you are thinking the function-caller is unsigned
The full code of alpha-beta search is here: http://pastie.org/8538015
Please friends, help as soon as possible.
Since you're using an optional parameter in your method signature, I'd caution you to pay attention to what your code is actually running when entering your function. You said you debugged it and the value gets assigned, but I don't have enough context to know if it only happens in one of many cases or not. Anyway, just be careful with those!
I would rewrite your function like this:
private static int utility(GameTreeNode gtn, bool isMin)
{
switch (gtn.NodeBoard.getBoardStatus())
{
case Status.Success:
return isMin
? -50
: 50;
case Status.Incomplete:
return isMin
? gtn.evaluate(State.X)
: gtn.evaluate(State.O);
default:
throw new NotImplementedException("The status is not implemented.");
}
}
A few improvements I see with this approach:
You don't need to store a value and return it at the end. In your case, you're always storing 50 into nodeValue when you take the Status.Success path, and then sometimes assigning -50 to it. Unless you're adamant about one return in your function, I think this approach is more clear. Might just be my opinion though.
There's a default in the switch statement so that you'll explicitly throw an exception in the case where you have a status that isn't implemented.
There is no optional parameter to your function. I don't see the benefit of making this parameter optional. In my opinion, it only looks like it's adding room to make things harder to debug.
EDIT:
Based on the code at:http://pastie.org/8538015#33,43
It looks like the only time you can ever get utility to return a negative value is when if (gtn.Nodes.Count == 0) return utility(gtn, true); is hit in the private static int MinValue(GameTreeNode gtn, int alpha, int beta) function. Otherwise, unless there's more code which you haven't posted, no other call to the utility function will hit the logical path your going for. You've mentioned when you step into there, you can see the value for nodeValue get properly assigned.
I'm suggesting you change:
// if Terminal-test(state) then return utitly(state)
if (gtn.Nodes.Count == 0) return utility(gtn, true);
gtn.Value = Globals.MAXINT;
To
// if Terminal-test(state) then return utitly(state)
if (gtn.Nodes.Count == 0)
{
int retVal = utility(gtn, true);
return retVal;
}
gtn.Value = Globals.MAXINT;
At least temporarily, and then put a breakpoint on return retVal. If your utility function is actually setting the value you expect like you say, there's no way that it could magically go away when it returns it to the MinValue function. I have a feeling something fishy is happening and the code isn't actually executing the path you expect.

Input string was not in a correct format. Converting string to int

Input string was not in correct form.
I'm getting an exception on runtime as "System.FormatException".
Follwing lines shows exception-
public int Task
{
get
{
return Int32.Parse(TaskText.Text);
}
set
{
TaskText.Text = value.ToString();
}
}
public int Project
{
get
{
return Int32.Parse(ProjectText.Text);
}
set
{
ProjectText.Text = value.ToString();
}
}
I also tried -
Convert.ToInt32(TaskText.Text)
Convert.ToInt32(ProjectText.Text)
I need to pass these to following constructor,
Harvest_TimeSheetEntry entry = new Harvest_TimeSheetEntry(client,starttime,stoptime,task,project);
this constructor is stored in some class with task and project as integer parameters. And I can't change it because if i changed, it affects other code.
It looks as though you're getting your input from controls accepting user input, which is just asking for failure, since a user can potentially enter something that doesn't represent an integer value. You can use TryParse to avoid this:
var result = 0;
if (int.TryParse(TaskText.Text, out result)) {
return result;
}
return 0;
So, if the value of TaskText.Text == "1", this will succeed; if the value of TaskText.Text == "aaaa", this will fail - and return zero. You example would raise the appropriate exception, as experienced.
However, an exception might be the right thing to happen here, if you can't handle a bad value, don't have an alternative, and the application relies on the input to move forward. More likely, you could do with some validation on your input fields to prevent bad data being submitted.
Since your Harvest_TimeSheetEntry constructor expects task and project to be integers, you must have a list of integers that correspond to the different tasks and projects. Now you can't expect Int32 to know which task corresponds to which number, can you?
I would suggest you use ComboBoxes for TaskText and ProjectText. Then, you can assign the correct corresponding integer to each ComboBoxItem.Tag.
Please note that this goes far beyond the kind of answers you should expect from SO.
if you do not use MVVM or binding you can simply do the check before your need it. t
int task;
int project;
if(!Int32.TryParse(TaskText.Text, out task))
{} //errorhandling here
if(!Int32.TryParse(ProjectText.Text, out project))
{}//errorhandling here
//all fine
var entry = new Harvest_TimeSheetEntry(client,starttime,stoptime,task,project);
You must check if you can parse it into Integer
try
Int32 foo =0;
if (Int32.TryParse(TaskText.Text, out foo))
{
return foo;
}

Categories

Resources