How to enforce a method to only be called in a if statement?
You… nest it in an if-statement?
This is a pretty vague question so you’re going to need to supply more information to get a more detailed answer.
Yes, but I would have been more clear and only nest the method call in that if statement, not the method itself. But I agree, such super basic questions without a concrete code example are kinda pointless. We have trouble understanding the exact problem and readers don’t really get much out of it.
@Bunny83
How would i enforce CustomMethod
to only be allowed to be called in a if statement.
if (CustomMethod())
{
}
void bool CustomMethod()
{
return true;
}
You can’t enforce that. If a method can be called, it can be called.
An if-statement is only looking for a boolean value.
How would I detect where a method is being called and display it at runtime. i.e in a struct, class, forloop, etc.
Ok, this is something completely different from what we thought you meant ^^. So you want to use the return value of your method in the condition of an if statement. But what’s the point of restricting such a method call to be used in an if statement? That doesn’t make much sense. Usually such method calls shouldn’t have any side effects as this would be code-smell. So if you call a method as part of a condition, it should not hurt or change anything if someone calls this method outside of an if statement. You also can always do
bool res = CustomMethod();
if (res)
{
// [ ... ]
}
Here we still use the return value in the if statement, but we call the method before the if statement.
So to answer your question directly: No, you can not restrict a method to be only called in an if statement. An if statement expects just a boolean value. Where this value comes from is completely irrelevent for the compiler. It can be a boolean expression which may involve a method call or it can be just a boolean variable. So this is not possible and also doesn’t make much sense.
If you think you have an actual reason why this would be useful, please provide a concrete example.
ps: Methods which just return a value without side effects usually start with GetXXXX()
so it’s clear what it does and that it doesn’t have side effects.
Methods can only be called from code. That is from inside other methods. So you can not call methods from a struct or class. If you ask to know the callstack from inside the method, you can use the Stacktrace class or if you just want to print out the stacktrace, there’s also the System.Environment.Stacktrace property which directly returns a string of the stack trace.
What’s the end goal here? That might be more useful to know than some abstract questions.
The method is intended to be used in a certain way for workflow.
Like how Unity.Entities.SystemAPI
throws an error if you are calling it outside it’s intended location.
I’m not 100% sure, but I assume SystemAPI is using a custom Roslyn Analyzer. You can get started with writing them here, and how to add them to Unity here.
You should probably be writing something pretty non-standard before it becomes actually usefull to do such a thing, but that’s how you do it.
I agree with the others here that trying to limit where a method can be called from is a bit suspicious, without further information, regarding why you would even want that. But, I think the best way to know where a method is being called from is probably with Caller Information Attributes: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/caller-information
If you add those attributes to the end of any method, you will automatically get those arguments when you run the code. The values are calculated at compile time, so there is no runtime performance penalty, like the big performance hit you get when taking a stack trace.
However, there are some issues:
- You cannot rely on the line number because that could easily change over time.
- You can combine the file name and method name to calculate a reasonable indication of where the method was called from. However, you will need to strip everything from the file path except the part that matches the class name, and you will need to make sure your file names always match your class names or it just won’t work as intended.
- Also, you will need to make sure you strip those file paths down to file names appropriately on every OS, as they use different path separator characters, and the caller info values are determined at compile time, not by which hardware platform the app is currently running on. I’ve had issues in the past trying to use the C# System methods for this because they will try to match only the directory separator character for the current platform. So, you may have to write your own file path stripping code that works on all platforms.
- You will want your conditional check that determines whether to call the underlying method to use the nameof(Class/Method) operator so that if you refactor the class or method name it will still work. (Note: This inherently establishes a tight coupling between the class containing this internal method, and the place(s) you expect it to be called from, which is kind of a red flag in itself.)
- You will have to make sure not to have more than one matching method name on the class that you are checking for, unless they all can call the underlying method.
- Anyone who wants to get past your check can just enter the class and method name you’re checking for in your conditional if statement as manual arguments to those optional caller info parameters, and it will pass your check and allow the underlying method to be called from anywhere.
Of note, you can also nest a method in a method, so that only the outer method can call the nested method, but private/protected scope on the underlying method accomplishes the same thing really.
If you can live with those limitations, it’s possible to do what you’re trying to do without any real performance cost at runtime, but again I would question whether you really need to do this at all.