Basically, I want to break the method if it's on cooldown. But when I move the if statement inside a method, it will not work. The return keyword will just return to the previous method and continue the rest.
Is there any way to do it?
Let the CooldownCheck method return the stop status, e.g., through a Boolean:
public void Interact()
{
if (CooldownCheck()) {
InInteract.Invoke();
lastCooled = Time.time + cooldown;
}
}
private bool CooldownCheck()
{
if (lastCooled <= Time.time) {
Debug.Log(stuff);
return true;
}
return false;
}
Btw., your else { return; } makes no sense, as any void method has an implicit return; at its end. The return-statement does not stop anything, it returns from the method, i.e., it leaves the method at this point and continues to run the caller, i.e., the caller will then execute the next statement.
A way to interrupt the caller would be to throw an exception. But this seems not appropriate in this case.
Related
In my C# project, I want to exit Method1 on a specific condition and execute another method (Method2) without return back to Method1. I want to prevent using jump statements (goto). How can I do that?
My simplified code looks like
public void Method1 ()
{
if (condition==true)
{
Method2() // Here at this point I want to exit Method1 and execute Method2. That means after executing Method2 the program shall not return to Method1. How can I do that?
}
//some code
}
As mentioned in the comments you can return after the method call.
if (condition == true)
{
Method2();
return;
}
Alternatively, you can put else for this if statement so that it will run only Method2() if it goes inside the if.
if (condition == true)
{
Method2();
}
else
{
//Do something
}
Another way is to have to same return type (except void) (if applicable) for both methods and return like below.
if (condition == true)
{
return Method2();
}
I've different thread which contains an infinite loop, inside each loop I call this method that return a true or false based on specific condition, but I'm going to return true just for example:
public void Test()
{
return true;
}
I'm wondering if can I break or continue the execution of the loop in a quick way, I mean, without write in any loop this condition:
if(Test())
{
break;
}
If I catch your meaning, you probably want to do the work while Test() is not returning false:
do
{
//your stuff
} while (Test());
Or if you won't necessarily iterate even once:
while(Test())
{
//your stuff
}
I have a validation method which I call in a loop.
I want to call "continue" if the validation fails.
Is there a way to call "continue" from the validation method ?
I just don't want to call "continue" in so many places in the loop...
No, flow control statements only affect the blocks within which they are defined. The only built-in way to alter control flow from further up the stack like that is an exception, which is definitely the wrong mechanism for what you are doing.
If you are bothered by all the continues, I suggest you consider moving towards a more declarative way of thinking. Define the body of your validation loop like so:
bool IsValid(Foo foo) {
if (Condition1(foo)) {
return false;
}
if (Condition2(foo)) {
return false;
}
// ... and so on
}
and then validate like this:
if (!foos.All(IsValid)) {
// One of your foos is invalid
}
the LINQ extension methods All and Any will break execution as soon as they can, meaning that All will stop when it finds the first one that doesn't satisfy the condition and Any will stop when it finds the first one that does.
You have a lot of continues in your cycle and it becomes bothering. You cannot continue from the external method, as it is out of scope. There are several solutions actually though:
You can return a boolean value from your validation methods and then use it as such:
if (!IsValid()) {
continue;
}
It is not helpful though, because you will still have continues.
You can put your validations at the start of the cycle and you can use a flag to determine whether the iteration should step out, initialized by false:
while (myCondition) {
stepOut = false;
//validation region, you set stepOut to false if a validation fails
if (!stepOut) {
//operations
}
}
You can wrap all the validation call into a method, let's call it myValidation and then:
while (myCondition) {
if (myValidation()) {
//operations
}
}
or
while (myCondition) {
if (!IsValid()) {
//continue
}
}
You can throw an Exception, but DON'T do that.
Just return false in your validation method wherever it should return, then check if the validation method returns false, break out of loop in caller function.
Why Not ?
Golden Rule in Programming : "There is always a way".
C++ lets you inline Assembly Language syntax. Similar to it, C# supports it too. Let me consider your example.
void method1(){
foreach(var x in y)
{
Validate(x);
...
//Your other logic
...
EndOfLoop:
;
}
}
..
..
void Validate(T x)
{
#if IL
br EndOfLoop
#endif
}
//End Of Code
This will "jump" to the "EndOfLoop" Label from anywhere within your Code. This could be a bad practice depending on your code though..
I have a class that talks to an external .exe. The class has a bunch of similar methods; they call a function of the .exe, wait for response, and then return true or false.
The response comes in the form of events that change the values of fields of this class.
Simplified code:
class Manager
{
private static bool connected = false;
public static bool Connect()
{
runtime.Connect();
int secondsWaited = 0;
while (!connected)
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}
return true;
}
}
The other methods use the same call-wait-loop-return structure.
My goal is to make a single method to do this waiting for me, like so:
private static bool WaitReferenceEqualsValue<T>(ref T reference, T value)
{
int secondsWaited = 0;
while (!reference.Equals(value))
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}
return true;
}
Then each method would do:
runtime.DoSomething();
return WaitReferenceEqualsValue<someType>(ref someField, someSuccessfulValue);
However, when I replace the wait-loop with this method call, the field "connected", even though passed in as a reference, always stays the same.
Any idea what's going on here, and how to get the desired functionality?
Thanks in advance.
EDIT:
public static bool Connect()
{
...
runtime.Connect();
// this code works
/*int secondsWaited = 0;
while (connected != true)
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}*/
// this somehow blocks OnConnect from firing, so connected never gets set to true
lock (typeof(SkypeKitManager))
{
WaitReferenceEqualsValue<bool>(ref connected, true);
}
...
}
OnConnect:
private static void OnConnect(object sender, Events.OnConnectArgs e)
{
if (e != null && e.success)
{
lock (typeof(Manager))
{
connected = true;
}
}
}
You're not doing any synchronization on that field although you access it from multiple threads and one of them is writing. This is a race (no exception! this is a race even if it looks safe. It isn't safe.).
Probably the JIT enregistered it which is a common optimization. It just never gets read from memory, always from a register. Add synchronization (for example a lock, or Interlocked or Volatile methods).
Your usage of ref is correct.
The problem with your code is essentially compiler optimization. Fo optimization purpose compilers (or jits) necessarily take a pretty much single threaded view. The compiler/jit will then notice that you don't touch reference in your code at all, therefore it can move the comparison outside the loop. It is free to do so, since you basically create a race condition (no synchronization/atomic accesses).
Fixing it could either involve using synchronization mechanisms or add the volatile specifier to reference, thus telling the compiler/jit, that the variable can be changed from outside the method.
My code doesn't terminate on a true condition if called from another method. For example,
void RunValidation()
{
if (NameEntered == string.Empty)
{
MessageBox.Show("No name has been entered");
return;
}
}
void CreateUser()
{
RunValidation();
//Run more code
}
If I call the validation method inside the create user method, the messagebox shows up but the rest of the code gets executed even though "return" was specified.
If the validation code is not inside a method and called directly in the CreateUser method, the rest of the code doesn't run (which is what I want). I want to be able to call a validation method inside many other methods and if the conditions are true, to stop executing other code in the methods.
What is the correct way of doing this? Do I have to use some sort of try and catch?
You are returning from the RunValidation method, not the CreateUser method. If you want to control the flow of the CreateUser method based on the results of RunValidation, do something like this:
bool Validate()
{
if (NameEntered.Equals(string.Empty))
{
MessageBox.Show("No name has been entered");
return false;
}
return true;
}
void CreateUser()
{
if (Validate())
{
// Run more code
}
}
The return statement only affects the current method. Read more about the return statement here.
return; exits the RunValidation() method.
It has no effect on the function that called it.
Instead, you should make RunValidation() return a boolean indicating whether the validation succeeded.
In the calling method, you can check if it returns false and return; from there too.
you can do something like:
bool RunValidation()
{
if (NameEntered == string.Empty)
{
MessageBox.Show("No name has been entered");
return false;
}
return true;
}
void CreateUser()
{
if(RunValidation())
{
//Run more code
}
}
U talking about this code block?
void RunValidation()
{
if (NameEntered == string.Empty)
{
MessageBox.Show("No name has been entered");
return;
}
}
because if you are, I don't know what "rest of code" it's executing, because there is no code after the return statement.
If you're talking about this
void CreateUser()
{
RunValidation();
//Run more code
}
then yes, just because RunValidation had a return statement doesn't mean that it's calling method will return. that kind of behavior would cause crazy bugs.
Now, in order to achieve yoru expected behavior, you can change runValidation to
bool RunValidation()
{
if (NameEntered == string.Empty)
{
MessageBox.Show("No name has been entered");
return false;
}
return true;
}
and then call it like
void CreateUser()
{
if(RunValidation())
{
//Run more code
}
}