I have written a method in c# to get a count of a table, and saves the count in settings properties.
public static bool CompareCount(int? currentCount)
{
Properties.Settings.Default.Count = (int)currentCount;
Properties.Settings.Default.Save();
if (currentCount < Properties.Settings.Default.Count)
{
return false;
}
else
{
return true;
}
}
At first time if the count returned is 20. I will save it in the settings and I shud not compare that wiht the previous count. ON second time I want to compare the current count wiht the previoulsy saved count in settings. The above method should assign the current count for the first time . but on second time it shud compare.
thanks in advance.
First of all, think about what would happen when you cast the int? that's coming in to int if the parameter is null. It doesn't make sense to use a nullable parameter if you don't do anything with it later on. You should either change the parameter type to int or you could do this:
Properties.Settings.Default.Count = currentCount ?? 0;
Then, the method will always return true, as the if condition is always false - remember you're setting Properties.Settings.Default.Count to currentCount just two lines above that? So how should it ever be larger than currentCount?
You need to define for yourself how to determine "the first time" and "the second time". What's the condition to find out whether the method is run for the first time? For the code below I'll assume that there's some default value for Properties.Settings.Default.Count that helps you determine whether the method runs for the first time.
Then, from what you say, your code should look like this:
public static bool CompareCount(int? currentCount)
{
int countValue = currentCount ?? 0;
if (Properties.Settings.Default.Count == <some default value>)
{
Properties.Settings.Default.Count = (int)currentCount;
Properties.Settings.Default.Save();
}
else
{
return currentCount >= Properties.Settings.Default.Count;
}
}
What is your problem in implementing it? You have all the blocks already here at hand. Just reorder them properly.
If the problem is that the "int Count" defined in settings is "0" by default, you can change it i.e. to default to -1 so it obviously will be NOT a Count written before. Or, you can change it to int? to have default null..
Ask the current found Count to check if it is equal to the default value (zero, or not found or set your own once not found let say -1), so once not found you do not compare otherwise compare the values.
For Example:
public static bool CompareCount(int? currentCount)
{
int foundCount = ReadFoundCountFromProperties;
if (foundCount != 0)
{
Properties.Settings.Default.Count = (int)currentCount;
Properties.Settings.Default.Save();
if (currentCount < foundCount)
return false;
return true;
}
Related
I am trying to write a program that lets me enter a list of names with their respective film rating into an array (Would do a list but the course material wants me to use array). Before I add the names to the array I want to make sure that a valid rating has been entered.
I am currently using a for statement that cycles through he array length and lets the user enter each movie to the list that way. This happens in a while loop to make them re-enter the name if the rating is invalid before the name is committed to Array. I check the names by calling a method with a temporary string assigned with the current entered name and rating which will do some conditional checks and return either false or true depending on the outcome. But the way I am doing it is not working at all..
Problem is that I have no idea how to make practical use of the bool statement my method returns:
string[] filmNames = new string[ArrayLength];
for (int i = 0; i < filmNames.Length; i = i + 1)
{
bool ratingFail = true;
int displayNumber = i + 1;
while (ratingFail)
{
Console.Write($"> Enter the Name and Rating of film number {displayNumber} of {ArrayLength}: ");
string checkRating = Console.ReadLine();
CheckRating(checkRating); // currently just does "return false;" for testing purposes
if (true) // this statement is clearly not effected by whatever the return value is from above method. Why? What to do?
{
ratingFail = true;
}
else
{
filmNames[i] = checkRating; // this bit is marked as unreachable, which is is.
ratingFail = false;
}
}
}
my test method:
public static bool CheckRating(string checkRating)
{
return false;
}
I am VERY (a week) new to programming and C# so please keep in mind when answering that I may not understand particular lingo referring to programming terms outside of the scope of what you can see here within, but I will Google and research to the best of my abilities if there is no way to simplify what you want to say. Thank you for your time and effort.
if (true) // this statement is clearly not effected by whatever the return value is from above method. Why? What to do?
{
ratingFail = true;
}
This will always be true, because you're creating a variable that is always true. You want this:
ratingFail = CheckRating(checkRating)
if (!ratingFail) {
The rating is valid, do stuff here.
}
If ratingFail is true, the loop will continue.
This assumes that CheckRating returns true if the input is invalid, and false if it is valid. The variable naming here is pretty confusing, and I recommend you refactor.
I would do it this way, assuming CheckRating returns true if valid:
for (int i = 0; i < filmNames.Length; i = i + 1)
{
bool ratingValid; // Defaults to false
int displayNumber = i + 1;
while (!ratingValid)
{
Console.Write($"> Blablabla: ");
string input = Console.ReadLine();
ratingValid = CheckRating(input);
}
// Do stuff if rating is valid here. If you got here, rating is valid.
}
// edit by iluvpancakes //
I decided to add a comment made by #Sinatr since that was the (version of the) solution I personally ended up using:
if(CheckRating(checkRating))
{
[do stuff and things]
}
bool ret = CheckRating(checkRating); // currently just does "return false;" for testing purposes
if (ret)
{
[...]
}
Or, like Sinatr's comment:
if(CheckRating(checkRating))
{
[...]
}
protected IteratorAdvance<int> Advance;
public delegate void IteratorAdvance<T2>(out T2 itemIndex);
public IteratorBase()
{
Advance = delegate(out int i) { i++; }; // <--- here
}
Above is a snippet of a class that is a wrapper for a number of types of loop. In the constructor overload below, the instantiator can specify the method by which the condition of continuing a for loop is determined and also how the control value of that loop is modified on each iteration.
Obviously, the simplest and most likely use of this is to start at 0 and increment by 1 until the last index of the data source is reached. To that end I've provided default methods and an initial value that are effectively (and in this case a very convoluted version of)
for(var i = 0; i < list.Count; i++)
Here's the constructor:
public IteratorBase(IterationStyle style, Func<int, T1, bool> complete, IteratorAdvance<int> advance, bool onErrorAbort = true, int initialValue = 0)
{
Style = style;
InitialValue = initialValue;
Complete = complete;
Advance = advance;
AbortOnError = onErrorAbort;
}
The problem is where I'm incrementing the control value, the compiler wants a default value for a variable (i) that is declared in that scope and because it is an out parameter, cannot accept a default value.
Even if I move the body of the function to a separate method, the same problem exists. I cannot initialise the out parameter prior to the for loop itself initialising it.
case IterationStyle.For:
for (controlValue = InitialValue; !Complete(controlValue, item); Advance(out controlValue))
{
action.TargetItem = item = dataSource[controlValue];
if (!ActWrapper(action))
return false;
}
break;
The only solution I can think of is to intialise the out parameter only on the first call of the method, which will involve using some kind of boolean external to the method. I don't think I'm alone in preferring to avoid that sort of thing. And it turns out it that doesn't work either so I would have to make the control value global. Over my dead body.
Usually, in this sort of situation it means your approach is wrong. But I can't think of another way. I'm hoping you can. Or else tell me how I can either initialise an out parameter or give it a default value.
Just in case anyone else is having a bad brain day, here's the solution. Use ref not out.
Advance = delegate(ref int i) { i++; };
With some help I have managed to get the right answer to these questions but I want to get my head around the concepts (i.e. understanding why these codes are correct), as understanding is very important and not just memory of syntax.
The first question is You're given the result of 3 competitions (true = win) , the prize for the first is 1, second is 2, third is 3. Return the total prize amount (you can win any combination of prizes)
The answer is:
public static int GetTotalPrize(bool first, bool second, bool third)
{
var result = 0;
if (first)
{ result += 1; }
if (second)
{ result += 2; }
if (third)
{ result += 3; }
return result;
}
How does the program know that if you were to win, let's say, the first, second and third prizes, that the total is 6? Or if you were to win the first and third, the total is 4? In other words, how does the code above account for all possible combinations?
The second question is You're given the result of 3 competitions in one of which you've won (true = win). The prize for the first is 1, second is 2, third is 3. Return the prize amount.
My answer is:
public static int GetPrize(bool first, bool second, bool third)
{
if (first)
return 1;
if (second)
return 2;
if (third)
return 3;
return 0;
}
Without the "return 0;" part at the end, my code was shown as incorrect. Why? As the question states that I have won one of the prizes, so in other words, I am not leaving the competition empty-handed.
Thanks in advance
Well, lets take it step by step.
First answer:
public static int GetTotalPrize(bool first, bool second, bool third)
{
var result = 0;
if (first)
{ result += 1; }
if (second)
{ result += 2; }
if (third)
{ result += 3; }
return result;
}
What happens here is the following:
The variable result is initialized with a value of 0.
What follows is a series of if statements. Notice how they are only if and not if-else, meaning they are not mutually exclusive.
When an if statement is true, then result += [some number] happens. This means that result is assigned the value (result + [some number]).
Finally, result is returned.
Second answer:
public static int GetPrize(bool first, bool second, bool third)
{
if (first)
return 1;
if (second)
return 2;
if (third)
return 3;
return 0;
}
Over here you are told that you have won one of them for sure. If you have not won the first, then you could have won the second or the third. If you have also not won the second, then you must have won the third. So the correct code would be:
if (first)
return 1;
else if (second)
return 2;
else
return 3;
In this case, the if statements are mutually exclusive, since you are told you have won one of them. Unlike the first answer, this syntax guarantees that one of the values (1, 2, or 3) will be returned.
The return guarantee is important because you have defined your function as having return type int. This means that, no matter what happens in the code, it will always return an int. In your code, if it weren't for the return 0, then there would be no return statement if all ifs were false. Of course, you are told that at least one will be true. The compiler however doesn't know that, and so it won't let you compile a function that doesn't fulfill the requirement of always returning a value.
The first piece of code works as follows (reading as pseudocode)
define a numer named result
set its value to 0
if the parameter (first) equals true, add 1 to result
[do this again for (second), and (third), but with their respective numeric values]
return result
it just counts the score, then returns it.
The second part of your question :
you defined your method as guaranteeing to return an int. thus, you cannot write the method without following up on that guarantee. you cannot return NOTHING (void), or the compiler will complain.
you also cannot return null , since an int is not nullable.
If we took the logic of your second question, and were told to make it capable of accepting any number of rounds, the reason for that last return statement might become more obvious:
public static int GetPrize(params bool[] scores)
{
for (int i = 0; i < scores.Length; i++)
{
if (scores[i]) // there is no guarantee any of the bools passed along equals true, so we might never hit this return statement.
return i + 1;
}
//if we never hit the first return statment,
//we will end up here, and will not have won anything.
//we still need to return an int, though.
return 0;
}
I'm trying to make a program that finds the factors of a number. I made a fairly simple one but it always repeated the same two factors twice i.e. 1 and 2, 2 and 1. So, to fix that I tried to check if the number had been used before but it keeps saying the bool proceed is unassigned.
using System;
namespace FactorableOrNah
{
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("Enter a whole number to view its factors: ");
int userInput = int.Parse(Console.ReadLine ());
int[] antiDoubler = new int[userInput];
bool proceed;
Console.Clear();
for (int i = 1; i != userInput; i++) {
antiDoubler[i] = userInput / i;
for(int j = 0; j < userInput; j++) {
if (antiDoubler [j] == i)
proceed = false;
else
proceed = true;
}
if ((userInput % i) == 0 && i != 1 && proceed == true)
Console.WriteLine("{0} and {1}", i, (userInput / i));
}
}
}
}
Using uninitialized variables in C# is not allowed. The compilation error can be solved by using either:
bool proceed = false;
or
bool proceed = default(bool);
since the default value of bool is false;
However, the algorithm is too complicated and very hard to read. Just for fun. A recursive example.
static IEnumerable<int> GetFactors(int number)
{
return GetFactors(number, number);
}
static IEnumerable<int> GetFactors(int number, int check)
{
if (check > 0)
{
if (number % check == 0)
{
yield return check;
}
foreach (var f in GetFactors(number, --check))
{
yield return f;
}
}
}
UPDATE:
Local variables cannot be left uninitialized, however class members (static members and instance variables), furthermore array elements are initialized automatically by the memory manager, so they are never uniitialized.
From the specification:
A variable must be definitely assigned (ยง5.3) before its value can be
obtained. As described in the following sections, variables are either
initially assigned or initially unassigned. An initially assigned
variable has a well-defined initial value and is always considered
definitely assigned. An initially unassigned variable has no initial
value. For an initially unassigned variable to be considered
definitely assigned at a certain location, an assignment to the
variable must occur in every possible execution path leading to that
location.
For your case you have an initially unassigned variable. Thus, the variable must be set in every possible execution path. There is one possible execution path to which your variable is not defined - when userInput >= j.
This would happen if userInput is 0. Following your program manually:
The first for case will check if i != userInput. Since i = 1 this is true, thus it will continue in the for loop.
the second for case will check if j < userInput. Since j = 0 this is false, thus it will skip the for case and never set proceed
Now you have arrived to where you check proceed and it was never set. So the compiler tells you that this is not allowed.
To solve your issue, you have to decide whether to:
define a default value for proceed, for instance false and set it at declaration, i.e. bool proceed = false;.
Rewrite your logic so that you do not need the boolean, for instance like Daniel Leiszen suggests.
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;
}