Sample code below is just a short one, my real code for one if statement is more than 1000 lines of code and those need to be called multiple times. So, to save lines I plan on putting it into a method and just calling that method, which is only around 1 line?
I was wondering if there is a possible way of putting multiple if else statements into MULTIPLE methods, and then calling those methods in the main method. If Method SuperSignalQ1 is true, then it will check method SuperSignalQ2, and so on.
I need this because without the method, my current code is more than 900k, which crashes my PC. This is the only way I could think of shortening my code, by putting it into a method and calling it in the main method as needed, rather than typing those 100s of lines everytime I need those.
So basically my question is:
How to call a method in the main method
How to check if that method is true so that it can then proceed to the next method. I receive error when doing the code in the MainCalculation
Cannot convert method group 'SuperSignalQ1' to non-delegate type 'bool'. Did you intend to invoke the method?
public void SuperSignalQ1()
{
if(RSI > RSI2)
{
if(CCI > CCI2) //There are actually more than 20 if else here which is around 1000 lines
{
return;
}
}
}
public void SuperSignalQ2()
{
if(RSI2 > RSI3)
{
if(CCI2 > CCI3) //There are actually more than 20 if else here which is around 1000 lines
{
return;
}
}
}
public void SuperSignalQ3()
{
if(RSI3 > RSI4)
{
if(CCI3 > CCI4) //There are actually more than 20 if else here which is around 1000 lines
{
return;
}
}
}
public void MainCalculation()
{
if (SuperSignalQ1 = True)
{
if(SuperSignalQ2 = True)
{
if SuperSignalQ3 = True)
{
SetColor(Color.White);
}
}
}
}
So basically, put multiple nested if statement into multiple methods, and then do an boolean check of those methods in the main method
You have
public void SuperSignalQ1()
and later on you have
if (SuperSignalQ1 = True)
This if statement is broken.
In c#, you test with the double equals:
if (someVariable == true)
What you've got is an assignment statement, because there's one equals sign.
You're also missing some brackets, so C# thinks you are referring to it as a variable instead of a method.
So it thinks you are trying to assign a value of True to the method pointer. Which it quite rightly complains about.
It looks like you actually want those methods to return a boolean value, and you could do something like this:
public bool SuperSignalQ1()
{
if(RSI > RSI2)
{
if(CCI > CCI2) //There are actually more than 20 if else here which is around 1000 lines
{
return true;
}
}
return false; // if none of the conditions are valid
}
public bool SuperSignalQ2()
{
if(RSI2 > RSI3)
{
if(CCI2 > CCI3) //There are actually more than 20 if else here which is around 1000 lines
{
return true;
}
}
return false; // if none of the conditions are valid
}
public bool SuperSignalQ3()
{
if(RSI3 > RSI4)
{
if(CCI3 > CCI4) //There are actually more than 20 if else here which is around 1000 lines
{
return true;
}
}
}
public void MainCalculation()
{
if (SuperSignalQ1() == true)
{
if(SuperSignalQ2() == true)
{
if (SuperSignalQ3() == true)
{
SetColor(Color.White);
}
}
}
}
BUT
For boolean, you don't usually use the == format, you'd just go if (SuperSignalQ1())
As #aether643 suggested, you might want to refactor your code so you don't have such a long chunk of code without mental breaks
In C#, you can actually do assignments in if tests. Don't do that.
Related
I would like to know how to go from a method back to main. For example, I want to check if number passes a certain criteria; I would perform a test in a different method and if it returns true, I want to continue using that number back in main. How can go from one method to main again in a continuous loop? I tried calling the main method but the program displays a message for error.
The way my project is set out is that a menu appears for the user to enter a postal code. The menu has many options to add, quit, or view their codes. Once they have added their postal code and it is valid, how can I loop it back to main with the menu appearing again, performing the same functions?
Small section from main:
if (decision.Equals("A"))
{
Console.Write("\n");
Console.WriteLine("Please enter your postal code: ");
for (i = 0; i < 1; i++)
{
postalcodez = Console.ReadLine().ToUpper();
if (isValid(postalcodez, i, number, j, num))
{
postalcode[i] = postalcodez;
Console.WriteLine("It worked!");
Console.ReadLine();
}
}
}
Now it goes through the method to check for conditions. If it returns true, how can I make it go back to main?
public static bool isValid(string postalcodez, int i, int number, int j, int num)
{
if (postalcodez.Length > 7 || postalcodez.Length < 7)
{
return false;
}
if (postalcodez[0].ToString().Equals("W") || postalcodez[0].ToString().Equals("Z"))
{
return false;
}
if (postalcodez.Length.Equals(7))
{
if (postalcodez[3].ToString().Equals(" "))
{
return true;
}
else
{
return false;
}
Another question is that how can I make an array so that I can set a condition for a specific character number. Instead of doing this ( where I hard code specific digits) I want it that the 1, 4 and 6th character must be a certain value :
if (postalcodez[1].ToString().Equals(0) || postalcodez[1].ToString().Equals(1) || postalcodez[1].ToString().Equals(2) || postalcodez[1].ToString().Equals(3) || postalcodez[1].ToString().Equals(4))
{
return true;
}
Since this is for school, I can use any special functions to resolve the issue. It has to be very basic.
It seems like you have a bit of a misunderstanding of what Main() actually is. Main() is, in effect, your entire application. Main is the root that everything will flow back to when the current call stack finishes resolving, and if there are no additional statements after that point, Main will complete, and the application will close. When you call methods from Main, when they return a value (if not void), you are then back inside of Main.
Based on what you have stated is your need, here is a very basic example of what will happen - the flow of the code should be reasonably clear:
private static void Main(string[] args)
{
int number = 5;
bool isValid = VerifyNumber(number);
if (!isValid)
Console.WriteLine("Not valid.");
else
Console.WriteLine("Valid.");
Console.ReadKey();
}
private static bool VerifyNumber(int number)
{
return number > 2;
}
Things to take note of:
Since the method being called from Main has an argument, that argument is provided from inside of Main. This means that when the method finishes, Main still has access to that value.
The output of the method is stored so that work can be done inside of Main based on it.
This question already has answers here:
Is async always asynchronous in C#? [duplicate]
(1 answer)
Do you have to put Task.Run in a method to make it async?
(3 answers)
async method in C# not asynchronous?
(3 answers)
Closed 5 years ago.
I have a TextBox with a TextChanged event that calls a custom event if the text of the textbox represents an existing file. In this event, there is a call to an outside dll that does some processing on the File, which can take upwards of a minute to finish. There is also some post-processing I do, dependent on what result this method returns to me. Currently, this is blocking my UI, which is highly undesirable.
There are essentially 2 "options"/scenarios I see.
Within the custom event, somehow wait for the dll call to finish, before continuing the event, while also keeping the UI free. This seems like the simplest idea from my multithreading-untrained self, but it also conceptually throws red flags at me: Is this even possible given that the custom event itself (called from TextChanged) is on the UI thread?
Throw the entire custom event into it's own thread using Task.Run(). Downside here is that apart from the dll method call, there is quite a good amount of UI elements that are affected by getters/setters after the long method. I could write alternated getters/setters based on the appropriate InvokeRequired, but if there is a more correct way to do this, I'd rather take that approach.
I made a much shorter (although contrived) example project, which shows essentially what I'm after, using option 2 from above:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
comboBox1.Items.Add("Select One...");
comboBox1.Items.Add("Item 1");
comboBox1.Items.Add("Item 2");
Value = 0;
}
public string SetMessage
{
set
{
if (lblInfo.InvokeRequired)
lblInfo.BeginInvoke((MethodInvoker)delegate () { lblInfo.Text = Important ? value + "!" : value; });
else
lblInfo.Text = Important ? value + "!" : value;
}
}
public bool Important
{
get
{
return chkImportant.Checked;
}
set
{
if (chkImportant.InvokeRequired)
chkImportant.BeginInvoke((MethodInvoker) delegate() { chkImportant.Checked = value; });
else
chkImportant.Checked = value;
}
}
public SomeValue Value
{
get
{
if (comboBox1.InvokeRequired)
{
SomeValue v = (SomeValue)comboBox1.Invoke(new Func<SomeValue>(() => SomeValue.Bar));
return v;
}
else
{
switch (comboBox1.SelectedIndex)
{
case 1:
return SomeValue.Foo;
case 2:
return SomeValue.Bar;
default:
return SomeValue.Nothing;
}
}
}
set
{
if (comboBox1.InvokeRequired)
{
comboBox1.BeginInvoke((MethodInvoker)delegate ()
{
switch (value)
{
case SomeValue.Nothing:
comboBox1.SelectedIndex = 0;
break;
case SomeValue.Foo:
comboBox1.SelectedIndex = 1;
break;
case SomeValue.Bar:
comboBox1.SelectedIndex = 2;
break;
}
});
}
else
{
switch (value)
{
case SomeValue.Nothing:
comboBox1.SelectedIndex = 0;
break;
case SomeValue.Foo:
comboBox1.SelectedIndex = 1;
break;
case SomeValue.Bar:
comboBox1.SelectedIndex = 2;
break;
}
}
}
}
private void CustomEvent(object sender, EventArgs e)
{
if (!Important)
Important = true;
SetMessage = "Doing some stuff";
if (Value == SomeValue.Foo)
Debug.WriteLine("Foo selected");
//I don't want to continue until a result is returned,
//but I don't want to block UI either.
if (ReturnsTrueEventually())
{
Debug.WriteLine("True!");
}
Important = false;
SetMessage = "Finished.";
}
public bool ReturnsTrueEventually()
{
//Simulates some long running method call in a dll.
//In reality, I would interpret an integer and return
//an appropriate T/F value based on it.
Thread.Sleep(5000);
return true;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
//Do I *need* to multithread the whole thing?
Task.Run(() => CustomEvent(this, new EventArgs()));
}
}
public enum SomeValue
{
Nothing = 0,
Foo = 100,
Bar = 200
}
Note: I'm not asking for code review on my option 2 code. Rather, I'm asking if option 2 is necessary to accomplish, since that option causes me to change a considerably larger portion of code, given that it's only 1 method within it holding up the entire process.
I also realize I can simplify some of the code in these properties to prevent replication. For the sake of demonstrating to myself and debugging, I am holding off on that at this time.
Here is what I had related to option 1 (left out duplicate code and the getters/setters without their invokes):
private async void CustomEvent(object sender, EventArgs e)
{
if (!Important)
Important = true;
SetMessage = "Doing some stuff";
if (Value == SomeValue.Foo)
Debug.WriteLine("Foo selected");
//I don't want to continue until a result is returned,
//but I don't want to block UI either.
if (await ReturnsTrueEventually())
{
Debug.WriteLine("True!");
}
Important = false;
SetMessage = "Finished.";
}
public async Task<bool> ReturnsTrueEventually()
{
//Simulates some long running method call in a dll.
//In reality, I would interpret an integer and
//return an appropriate T/F value based on it.
Thread.Sleep(5000);
return true;
}
This is basically what you want. I'm violating a couple best-practices here, but just showing it's not that complicated. One thing to keep in mind is that the user can now click this button multiple times in a row. You might consider disabling it before processing. Or you can do a Monitor.TryEnter() to make sure it's not already running.
private async void buttonProcess_Click(object sender, RoutedEventArgs e)
{
textBlockStatus.Text = "Processing...";
bool processed = await Task.Run(() => SlowRunningTask());
}
private bool SlowRunningTask()
{
Thread.Sleep(5000);
return true;
}
How do I do this? I have an if-else statement like this (not exact code but a symbolic idea):
if(formNull)
{
MessageBox.Show("empty")
}
else if(FormNotNull)
{
// I have validation if/elses here for input fields like
if(regex textbx1)
{
error
}
else
{
normal
}
if(regex textbx2)
{
error
}
else
{
normal
}
//Some more like this
} <<<<<<<<<<<< It stops here and never goes in the next 'else' statement even if the form is OK.
else
{
DBConn.myMethod(a, b, c, etc.)
if true
{
success!;
}
else
{
failed!;
}
}
I tried some nesting combinations, but nothing worked.
Seems like there's nothing left, as you already handled all cases in the if and else if.
if(formNull)
{
// goes here when `formNull` is true
}
else if(FormNotNull)
{
// goes here when `FormNotNull` is true and `formNull` is false
}
else
{
// goes here in any other case (but I guess there is no other case left)
}
That just means your two conditions (in the if and else if statements) are returning true. If either ever returns true, you will never go into your else block (both MUST be false).
Thank you all for suggestions. I simply used the separate textChanged events with Regex for errors and used simple if-statement like this
if (FormNull)
{
Message.Show("error");
}
else
{
DBConn.myMthod(a,b,c)
if(true)
{
sucess;
}
else
{
failed;
}
}
Just wanted to know the other option for what I was trying to do.
I have a program that is completely functional, and I am now refactoring it. I am just in the process of learning c# so the original code was pretty terrible despite the fact that it ran just fine. One of the requirements of the program is that the user be able to return to the main menu at any point. I accomplished this as follows:
static bool bouncer = false
static void Exit(string input)
{
if (input == "\t")
{
bouncer = true
}
}
static string Prompt(string msg)
{
// takes input and passes it to Exit() then returns the input
}
static string FunctionA()
{
while(true)
{
if (bouncer == true)
{
break;
}
Prompt("whatever")
if (bouncer == true)
{
break;
}
Prompt("whatever")
if (bouncer == true)
{
break;
}
// return some stuff
}
}
static void Main()
{
bouncer = false
// writes the menu to console and handles UI
// FunctionA
{
The variable bouncer gets set to true if the user enters the "tab" character at any input point. The proliferation of break statement conditionals provides the structure that actually breaks out back to Main(). This is obviously not a very good solution and it makes the code hard to read.
Other attempts that I considered to accomplish the same task are:
Goto statement that jumps straight back to Main(). I scrapped this because goto has a very limited scope in c# and I don't think there is any good way to make it workable in this situation.
Calling Main() directly from Exit(). This is probably a bad idea, and I can't do it anyway because apparently Main() is "protected" in some way.
Using an event to react to TAB or ESC being pressed. It's unclear to me how I could use an event to do this since I still wouldn't be able to break right out of the event. My understanding is that the break statement has to actually be contained in the loop that needs to be broken as opposed to being written into a different function that is called from within the loop.
Any suggestions are greatly appreciated. I'm hoping there's something to be done with event handling or that I've overlooked something more simple. Thanks!
As a matter of coding style, the way it is works, but is seen as ugly. Unfortunately, if you need to break out immediately between sections of work, there is not a lot of ways around that.
You can change your current format of using breaks to using "if( bContinue ) { /* do next section of work */ }" control style. It changes the code from break out of the while loop to this:
static string FunctionA()
{
bool bContinue = true;
while( true == bContinue )
{
// Do initital work.
//
// Initial work can set bContinue to false if any error condition
// occurs.
if( true == bContinue )
{
// Do more work.
int returnCheck = MakeACall(); // Presume MakeACall returns negative interger values for error, 0 or positive values for success or success with condition/extra information.
if( 0 < returnCheck )
{
bContinue = false;
}
}
if( true == bContinue )
{
Prompt("whatever")
// Do more work.
bContinue = MakeASecondCall(); // Presume that MakeASecondCall returns true for success, false for error/failure
}
if( true == bContinue )
{
Prompt("whatever")
// Do more work.
// If error encountered, set bContinue to false.
}
if( true == bContinue )
{
Prompt("whatever else")
// Do more work.
// If error encountered, set bContinue to false.
}
// Done with loop, so drop out.
bContinue = false;
// return some stuff
}
}
Looking at your pseudo code, it reads like you only do a single pass through your work loop. If so, you can switch to a Do-While(false) format, and use the break to just drop to the bottom. Or, if you are only doing a single pass through your FunctionA, just do away with the While or Do-While control structure, and just use the if(true==bContinue){ /* Do more work */ }. It is not the cleanest of code, but when you perform long periods of serial work, you end up with such structures if you are not going to use a while or do-while for controlling the flow.
The disadvantage to using the if(bContinue){} style is that when an error condition occurs during the early stages of the process, the code does not exit out as quickly from the function as a break out of the while() or do-while() structure if the error occurs near the top of the work, as there will be the series of if statements that the code will test and then skip over. But it is readable, and if you use a descriptive name for your control variable (ie, nContinue or bContinue or workLoopControl) it should be fairly obvious that it is the master control flag for the function's work flow to whoever works or reviews the code after you.
Instead of an infinite loop and break statements, try using a conditional flag instead.
static void FunctionA()
{
bool done = false;
string response = string.Empty;
while (!done)
{
response = Prompt("whatever");
if(response == '\t')
{
done = true;
}
}
}
As a side note, I'm not sure why you have 'string' as the return type of several methods (e.g., 'FunctionA') when you aren't using the return value. That's why the code I gave above has it as 'void'.
This is a bit hard to explain, but I'm hoping this example will clear it up.
Say I have some function call Visible:
public bool Visible(/* Some page element */)
{
// Checks if something on a webpage is visible. Returns a "true" is yes, and "false" if not
}
Is it possible to some how wait for this function to return true? What I've written out so far looks like this:
public void WaitUntil(/*function returning bool*/ isTrue)
{
for (int second = 0; ; second++)
{
if (second >= 12)
{
/* Thow exception */
}
else
{
if (isTrue /*calls the isTrue function with given parameters*/)
{
return;
}
}
}
}
Such that these two method could be used together like:
WaitUntil(Visible(/* Some page element */));
to wait until a page element is visible... Is this possible?
Here is how to do it (although you should consider using events as this kind of "waiting" is strongly discouraged)
/*Important Note: This is ugly, error prone
and causes eye itchiness to veteran programmers*/
public void WaitUntil(Func<bool> func)
{
DateTime start = DateTime.Now;
while(DateTime.Now - start < TimeSpan.FromSeconds(12))
{
if (func())
{
return;
}
Thread.Sleep(100);
}
/* Thow exception */
}
//Call
WaitUntil(() => Visible(/* Some page element*/));