In Delphi you can declare a constant in a method and assign it a value in that same method. The idea is that next time you are in this method, the const will still have the same value that you last assigned it.
It looks like this in Delphi :
(I don't have Delphi here so it is untested, sorry about that, but it is enough to demonstrate what I mean)
procedure Form1.test;
const
AssignableConst: Integer = 0;
begin
ShowMessage(AssignableConst);
inc(AssignableConst);
end;
Every time you call the procedure test the messagebox will show the last value + 1
This example is completely useless I know that it is just to show how an assignable const works in Delphi.
Is there an equivalent for this in c# ?
I don't want a solution that involves private variables in the class, it has to stay inside the method.
My question is about scope. Nothing else. I don't care that the value is part of the state of the object. That is not important. What is important is that I need a variable that is only accessible from the scope of a method, nowhere else.
In Delphi this can be done by using an assignable const, so how can I do this in C#?
I don't want a solution that involves private variables in the class, it has to stay inside the method.
But the value is part of the state of the object (or type, for a static method) - so it makes sense for it to be a field declared in the object.
There's no equivalent to this in C#. The best you can do is have a private variable and document that it should only be used from a specific method. (You could write Roslyn-based tests for that if you really want.)
The closest you can get is:
class MyClass
{
static Action CreateCounter()
{
int counter = 0;
return () => {
Show(counter);
counter++;
};
}
Action showAndIncrementCounter = CreateCounter();
public ShowAndIncrementCounter()
{
showAndIncrementCounter();
}
}
But I still recommend the simple solution of using an instance field for the counter and just not accessing it from outside the method.
Related
Goal:
I am having some issues in C# when ensuring that a variable retains its assigned value for the duration / runtime of a program. In particular, I am attempting to:
Read a number in from some input
Save it to a variable of type double
Print the variable
Ensure that this value stays the same for the duration of the program, so that on the next iteration when a new value is read in, the previous value from step (2) is still printed.
Attempts:
I have attempted to use a global static variable such as public static double foo;, however, whenever the method that retrievs new values is called again, a new value is printed.
In C, for example, I believe the closest functionality to this would be to use the static keyword, however, I have read that this functionality has been intentionally excluded from C# and I am struggling to learn why this is the case.
void foo()
{
static int j;
int i = calculateSomeValue() + j;
j = i;
}
Please note that before deciding to post this question, I have consulted the following resources:
https://softwareengineering.stackexchange.com/questions/141871/false-friends-keyword-static-in-c-compared-to-c-c-and-java
https://learn.microsoft.com/en-us/answers/questions/240965/retain-previous-value-of-text-box-till-the-form-is.html
Retain local variable across method calls
How to retain old value when setting variable on c# class
https://social.msdn.microsoft.com/Forums/en-US/46243c7b-959e-4753-a173-34f52a7f8922/variables-retain-value-from-first-pass?forum=csharpgeneral
Q1. How can a value assigned to a variable be retained for the entire runtime of a 'C#' program?
Apologies if I am missing something extremely obvious, but it seems that the static keyword in C is used in a different manner compared to that of C#.
According to your description, the variable is re-assigned at step #2.
It is expected that step #3 (Print the variable) will output the changed variable value at each iteration.
Your understanding of "static" meaning in C# is correct, at least in the scope that you have described.
I'm working on doing some refactoring of functions in an existing ASP.NET MVC application, and came across the following small recursive function within a controller. I'm a little new still to C# & .NET, so please bear with me if I get some things wrong.
private int _bl;
[Session]
public void TotalMaterialSubCategories(IEnumerable<Category> materialMasterCats, int i)
{
foreach (var materialMasterCat in materialMasterCats)
{
_bl = _bl + 1;
materialMasterCat.Level = i;
if (materialMasterCat.ChildCategories.Count != 0)
{
TotalMaterialSubCategories(materialMasterCat.ChildCategories.ToList(), i + 1);
if (materialMasterCat.Parent == 0)
{
materialMasterCat.SortOrder = _bl;
_bl = 0;
}
}
}
}
The thing about it that concerned me is this private int _bl statement. Within this class, the only references to this variable are associated with this function.
I thought the line _b1 = _b1 + 1 might not be reliable because it's not manually initialized. Looking into it though, I believe that since it's an int, it cannot be null or left 'uninitialized', so it's getting a default value of 0; corroborated by the MS Docs. The way the recursion looks like it bubbles up makes me think it'll be set back to 0 at the end of this function call as well. Finally, I'm pretty sure each independent web request gets a separate instance of this controller, so it seems like the way this is written, it should function as expected.
However, I just sort of wondered why this would be written like this. Is there a reason that this isn't just a local variable to the function, initialized with 0? Can you rely on local private variables across functions in controllers? Also, are any of my assumptions / determinations incorrect?
The thing about it that concerned me is this private int _bl statement. Within this class, the only references to this variable are associated with this function.
Obviously we can't see all the code, but if I were to believe you that this Field(not variable) is only referenced by this function then I would surmise that either it's left over when other methods may have referenced it and now those methods no longer exist, used it OR it used by a method to maintain state beyond the execution of any single method (event or property).
The way the recursion looks like it bubbles up makes me think it'll be set back to 0 at the end of this function call as well.
It's set to zero before the constructor is called.
Not necessarily. It's only set back to zero after the method ends if (materialMasterCat.Parent == 0) for each instantiation of this class.
Because controllers aren't static classes, each class create has it's own private version of _bl that can only (normally) be access by the class itself (private access modifer).
However, I just sort of wondered why this would be written like this. Is there a reason that this isn't just a local variable to the function, initialized with 0?
Because then when this code ran, all of them would have a value of 1:
materialMasterCat.SortOrder = _bl;
But what's happening is that each time the function is called, it's being incremented because it's exists in the class's scope, not the functions scope.
For Example
Can you rely on local private variables across functions in MVC Controllers?
Private variables are always available until a class is disposed (generally), this time is referred to as the Lifetime of an object.
I believe that since it's an int, it cannot be null or left
'uninitialized', so it's getting a default value of 0; corroborated by
the MS Docs
Try putting the private int _bl; inside of a function as int _bl; and you will see that you get a compile error because you can't perform a _bl = _bl + 1; operation on uninitialized value. So, it doesn't get automatically initialized in scope of a function, but it does get automatically initialized when it's a property of a class instance.
You can read more on when a value gets assigned and when it doesn't here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/variables This particular case falls to:
An instance variable of a class comes
into existence when a new instance of that class is created, and
ceases to exist when there are no references to that instance and the
instance's destructor (if any) has executed. The initial value of an
instance variable of a class is the default value (Default values) of
the variable's type. For the purpose of definite assignment checking,
an instance variable of a class is considered initially assigned.
Let's say I have a simple function:
public static int NewNumber(int lowestValue, int highiestValue) {}
I would like to have some a compiler check if parameters are correct. For example, in this case, the developer could mistakenly (or on purpose) call the method like this:
NewNumber(5, -5);
which is wrong in this case - The developer lied.
Sure I could make a simple check inside the method:
public static int NewNumber(int lowestValue, int highiestValue) {
if (highiestValue <= lowestValue) {
//Error
}
}
... and it would work just perfectly. However, I'm curious if there is anything the developer can do in this case to restrict such behavior without additional checking in the method itself.
EDIT: Found out the solution but nonrelated to the C#
Since I'm working in Unity I end up with writing custom inspector so values can be entered correctly in the Unity Inspector itself, thus eliminating unnecessary checks (and slowing the performance) when calling the method many times per second.
This I don't believe is possible. Consider this situation,
NewNumber(x, y);
What's x and y? The compiler doesn't necessarily know what the input is (e.g. x = Int32.Parse(Console.ReadLine());).
You gave hard-coded examples, and perhaps you might only use the function with hard-coded values, but the compiler only knows that 5 and -5 are integers and integers can be a literal 5, -5, etc or a variable var a = 5;
I don't think there is a compiler related parameter argument check. But it is always better to have your parameter check within your method (responsibility of your method to take care the parameter) and document it better so, the caller knows what data it should pass to your method.
I'm using Visual Studio 2010 + ReSharper and it shows a warning on the following code:
if (rect.Contains(point))
{
...
}
rect is a readonly Rectangle field, and ReSharper shows me this warning:
"Impure Method is called for readonly field of value type."
What are impure methods and why is this warning being shown to me?
First off, Jon, Michael and Jared's answers are essentially correct but I have a few more things I'd like to add to them.
What is meant by an "impure" method?
It is easier to characterize pure methods. A "pure" method has the following characteristics:
Its output is entirely determined by its input; its output does not depend on externalities like the time of day or the bits on your hard disk. Its output does not depend on its history; calling the method with a given argument twice should give the same result.
A pure method produces no observable mutations in the world around it. A pure method may choose to mutate private state for efficiency's sake, but a pure method does not, say, mutate a field of its argument.
For example, Math.Cos is a pure method. Its output depends only on its input, and the input is not changed by the call.
An impure method is a method which is not pure.
What are some of the dangers of passing readonly structs to impure methods?
There are two that come to mind. The first is the one pointed out by Jon, Michael and Jared, and this is the one that ReSharper is warning you about. When you call a method on a struct, we always pass a reference to the variable that is the receiver, in case the method wishes to mutate the variable.
So what if you call such a method on a value, rather than a variable? In that case, we make a temporary variable, copy the value into it, and pass a reference to the variable.
A readonly variable is considered a value, because it cannot be mutated outside the constructor. So we are copying the variable to another variable, and the impure method is possibly mutating the copy, when you intend it to mutate the variable.
That's the danger of passing a readonly struct as a receiver. There is also a danger of passing a struct that contains a readonly field. A struct that contains a readonly field is a common practice, but it is essentially writing a cheque that the type system does not have the funds to cash; the "read-only-ness" of a particular variable is determined by the owner of the storage. An instance of a reference type "owns" its own storage, but an instance of a value type does not!
struct S
{
private readonly int x;
public S(int x) { this.x = x; }
public void Badness(ref S s)
{
Console.WriteLine(this.x);
s = new S(this.x + 1);
// This should be the same, right?
Console.WriteLine(this.x);
}
}
One thinks that this.x is not going to change because x is a readonly field and Badness is not a constructor. But...
S s = new S(1);
s.Badness(ref s);
... clearly demonstrates the falsity of that. this and s refer to the same variable, and that variable is not readonly!
An impure method is one which isn't guaranteed to leave the value as it was.
In .NET 4, you can decorate methods and types with [Pure] to declare them to be pure, and R# will take notice of this. Unfortunately, you can't apply it to someone else's members, and you can't convince R# that a type/member is pure in a .NET 3.5 project as far as I'm aware. (This bites me in Noda Time all the time.)
The idea is that if you're calling a method which mutates a variable, but you call it on a read-only field, it's probably not doing what you want, so R# will warn you about this. For example:
public struct Nasty
{
public int value;
public void SetValue()
{
value = 10;
}
}
class Test
{
static readonly Nasty first;
static Nasty second;
static void Main()
{
first.SetValue();
second.SetValue();
Console.WriteLine(first.value); // 0
Console.WriteLine(second.value); // 10
}
}
This would be a really useful warning if every method which was actually pure was declared that way. Unfortunately they're not, so there are a lot of false positives :(
The short answer is that this is a false positive, and you can safely ignore the warning.
The longer answer is that accessing a read-only value type creates a copy of it, so that any changes to the value made by a method would only affect the copy. ReSharper doesn't realize that Contains is a pure method (meaning it has no side effects). Eric Lippert talks about it here: Mutating Readonly Structs
It sounds like ReSharper believes that the method Contains can mutate the rect value. Because rect is a readonly struct, the C# compiler makes defensive copies of the value to prevent the method from mutating a readonly field. Essentially, the final code looks like this:
Rectangle temp = rect;
if (temp.Contains(point)) {
...
}
ReSharper is warning you here that Contains may mutate rect in a way that would be immediately lost because it happened on a temporary.
An Impure method is a method that could have side-effects. In this case, ReSharper seems to think it could change rect. It probably doesn't but the chain of evidence is broken.
In my program i am passing a locally constructed variable to a global class object's member function. The member function will assign this variable to a private member and use it through out the program. Is there any drawback in this approach?
public void function()
{
int a = 0;
globalClassObject.StoreValue(a);
}
This is fine. The problem would be if you would pass a reference to this variable. In this case the value is "copied" to the variable within the function so the original a variable isn't actually used.
I don't see a problem with this. The variable is used in local scope only, so no unexpected results here.
The big drawback is if this value can be changed anywhere else in the program. If it can, your program will become a swamp for bugs to breed. If the globalClassObject stores the value immutably, there is no problem.